Domanda

Sono stato codificare fino Java con Netbeans per circa un anno, e ho scritto un sacco di codice manipolazione dei dati che riporta i grafici sullo schermo. Io in genere pianta un oggetto JPanel nella mia finestra principale, personalizzati in scrittura pittura di codice, e chiamare il metodo repaint (), se necessario.

Ma oggi, per la prima volta, ho provato a richiamare un ridisegno su un pannello da una classe (oggetto) diverso da quello che conteneva il pannello. Anche se il compilatore ha trovato sbagliato nulla con questo, e in modalità debug, single-passo correttamente alla chiamata esterna al ridisegno, non riverniciare è effettivamente verificata, e il codice non ha in realtà passo nel metodo repaint.

Ho scritto un programma minimale per dimostrare il problema, come illustrato di seguito (viene omesso principale, dal momento che contiene soltanto il codice per impostare i due pannelli sullo schermo.)

--- Descrizione delle classi, prima contiene la superficie di disegno, altri la chiamata ridisegno ---

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class Panel1 extends JComponent
{
   GraphPnl graphPnl;
   boolean colorFlag;

   public Panel1()
   {
     setLayout(null);
     colorFlag = true;

     graphPnl = new GraphPnl();
     graphPnl.setBounds(10, 10, 110, 110);
     graphPnl.setBackground(Color.black);
     add(graphPnl);

}//Panel1()

public class GraphPnl extends JPanel
{
  //just draws a line segment, toggling color

  @Override
  public void paint(Graphics g)
  {
      super.paint(g);
      Graphics2D g2 = (Graphics2D) g;
  g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
               RenderingHints.VALUE_ANTIALIAS_ON);

      if (colorFlag) {g2.setColor(Color.red);} else {g2.setColor(Color.green);}
      g2.drawLine(10, 10, 50, 50);
   }//paint
 }//GraphPnl
}//Panel1

import javax.swing.*;
import java.awt.event.*;

public class Panel2 extends JComponent
{
   JButton testBtn;
   TestAction testAction;
   Panel1 p1;

   public Panel2()
   {
      p1 = new Panel1();
      testBtn = new JButton("Click");
      testBtn.setBounds(10, 10, 80, 30);
      add(testBtn);
      testAction = new TestAction();
      testBtn.addActionListener(testAction);
   }//Panel2()


   public class TestAction implements ActionListener
   {
     public void actionPerformed(ActionEvent evt)
     {
       p1.colorFlag = ! p1.colorFlag;
       p1.graphPnl.repaint();
     }
   }//TestAction
}//Panel2

Se qualcuno ha qualche intuizioni in questo, o sa di una soluzione, sarei molto felice di sentire da voi.

Grazie in anticipo per eventuali approfondimenti.

John Doner

È stato utile?

Soluzione

Credo che quando si sta disegnando un JComponent, l'area di visualizzazione è impostata su quella JComponent. Quindi, se gli altri componenti cercano di dipingere (o se si chiama il loro ridisegno), non lo faranno, a causa della saturazione.

Altri suggerimenti

  

principale è omesso, in quanto contiene soltanto il codice per impostare i due pannelli sullo schermo.)

Bene, per definizione, quando si ha un problema che non si sa quale codice è o non è relativo fino a quando il problema è risolto. Quindi un completo SSCCE dovrebbe essere pubblicato.

Come un ipotesi direi il componente ha una dimensione di 0 quindi non c'è nulla di dipingere.

  

Io in genere pianta un oggetto JPanel nella mia finestra principale, personalizzati in scrittura pittura di codice, e chiamare il repaint () Metodo secondo necessità

Probabilmente è stato fortunato perché si è aggiunto il pannello al centro di una BorderLayout che dà automaticamente il pannello di tutto lo spazio a disposizione del telaio.

di trashgod esempio mostra un modo per impostare la dimensione preferita di un componente personalizzato. Un altro modo è quello di sovrascrivere il metodo getPreferredSize () per restituire il valore corretto.

Si dovrebbe davvero imparare ad usare gestore di layout piuttosto che utilizzare i layout nulli ed eviterete problemi come questo in futuro. Non v'è alcuna necessità di utilizzare un layout nulla a meno che non si dispone di un tipo drag / drop di applicazione.

"programmi dell'oscillazione dovrebbe ignorare paintComponent() invece di override paint()." - Pittura in AWT e swing:. I metodi di vernice

  

main viene omesso, in quanto contiene soltanto il codice per impostare i due pannelli sullo schermo.

Verificare che si costruisce la vostra interfaccia grafica sul EDT, come mostrato in questo articolo Le discussioni iniziali .

Addendum: Ecco un esempio che mostra entrambi i principi:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

/** @see http://stackoverflow.com/questions/4282159 */
public class GraphPanel extends JPanel {

    private boolean colorFlag;

    public GraphPanel() {
        this.setPreferredSize(new Dimension(640, 480));
    }

    public void toggle() {
        colorFlag = !colorFlag;
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);
        if (colorFlag) {
            g2.setColor(Color.red);
        } else {
            g2.setColor(Color.blue);
        }
        g2.drawLine(0, 0, getWidth(), getHeight());
    }

    private void display() {
        JFrame f = new JFrame("GraphPanel");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(this, BorderLayout.CENTER);
        f.add(new ControlPanel(this), BorderLayout.SOUTH);
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                new GraphPanel().display();
            }
        });
    }
}

class ControlPanel extends JPanel {

    public ControlPanel(final GraphPanel gp) {
        this.add(new JButton(new AbstractAction("Click") {

            @Override
            public void actionPerformed(ActionEvent e) {
                gp.toggle();
                gp.repaint();
            }
        }));
    }
}

Addendum: Come notato nel commento di @ camickr, A visiva Guida ai gestori di layout può aiutare a guidare la selezione di layout.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top