Pregunta

He estado codificar hasta Java con Netbeans por alrededor de un año, y he escrito un montón de código de manipulación de datos que traza los gráficos en pantalla. en general, me planta un objeto JPanel en mi ventana principal, escritura personalizado pintura código y llamar al método repaint (), según sea necesario.

Pero hoy, por primera vez, traté de invocar un repintado en un panel de una clase (objeto) que no sea la que contenía el panel. Aunque el compilador encontró nada malo con esto, y en el modo de depuración, es solo un paso correctamente a la llamada exterior al repintado, repintado sin que realmente ocurrió, y el código en realidad no paso en el método de pintar.

Me escribió un programa minimalista para demostrar el problema, como se muestra a continuación (principal se omite, ya que sólo contiene código para configurar los dos paneles de la pantalla.)

--- Descripción de las clases, contiene en primer lugar la superficie de dibujo, otra la llamada repinte ---

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

Si alguien tiene alguna ideas sobre esto, o sabe de una solución, estaría muy feliz de escuchar de ti.

Gracias de antemano por cualquier idea.

John Doner

¿Fue útil?

Solución

Creo que cuando se está pintando un JComponent, la región de recorte se ajusta a ese JComponent. Así que si otros componentes tratan de pintar (o si se llama a su repinte), no lo harán, debido al recorte.

Otros consejos

  

principal se omite, ya que sólo contiene código para configurar los dos paneles de la pantalla.)

Bueno, por definición, cuando se tiene un problema que no sabe qué código es o no es relativo hasta que el problema está resuelto. Por lo que una completa SSCCE debe ser publicado.

Como una suposición que diría su componente tiene un tamaño de 0 por lo que no hay nada que pintar.

  

Me planto en general, un objeto JPanel en mi ventana principal, escritura personalizado pintura de código, y llamo el repinte () Método según sea necesario

Probablemente tuvo suerte, ya que ha añadido el panel para el centro de un BorderLayout que da automáticamente el panel de todo el espacio disponible en el bastidor.

de trashgod ejemplo muestra una manera de establecer el tamaño preferido de un componente personalizado. Otra forma es reemplazar el método getPreferredSize () para devolver el valor adecuado.

Usted realmente debe aprender a utilizar el controlador de distribución en lugar de utilizar diseños nulos y evitará problemas como éste en el futuro. No hay necesidad de usar un diseño nula a menos que tenga un tipo de arrastrar / gota de aplicación.

"programas Swing debe pasar por encima paintComponent() en lugar de anular paint()." - Pintura de AWT y swing:. Los métodos de pintura

  

main se omite, ya que sólo contiene código para configurar los dos paneles de la pantalla.

Compruebe que construye su interfaz gráfica de usuario de la EDT, como se muestra en el artículo Temas iniciales .

Adición: He aquí un ejemplo que muestra dos principios:

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();
            }
        }));
    }
}

Adición: Como se señaló en el comentario de @ camickr, Un Visual guía de Controladores de distribución puede ayudar a guiar a su selección de diseño.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top