paintComponent () vs paint () y JPanel vs Canvas en una GUI tipo pincel

Obtuve algunas ideas y críticas interesantes sobre esto , esta y esta publicación (ver la última publicación para el código de la GUI en cuestión). Sin embargo, todavía estoy bastante confundido sobre algunas cosas. Principalmente, ¿cuál es la forma menos costosa de mostrar gráficos introducidos por el usuario?

Más específicamente, utilicé un método paintComponent() de la clase JPanel al hacer un objeto de esta clase en el método MouseDragged() junto con el método paintComponent(getGraphics()) ( AuxClass2 y AuxClass1 consecuencia).

Aparentemente, usar getGraphics() y paintComponent() lugar de repaint() son malas ideas, sospecho que algo tiene que ver con el uso de la memoria. También llamar a AuxClass2 cada vez que el usuario arrastra el mouse también es una mala idea.

También JPanel vs Canvas (es decir, swing vs awt) es un poco confuso. ¿Qué se usa y cuándo?

He estado tratando de encontrar soluciones temporales, pero no he encontrado ninguna, especialmente para el método getGraphics() : ¿de qué otra manera se pueden agregar los gráficos al panel?

He estado tratando de encontrar soluciones temporales, pero no he encontrado ninguna, especialmente para el método getGraphics (): ¿de qué otra manera se pueden agregar los gráficos al panel?

Recuerdas lo que necesita ser pintado como una variable y lo usas en paintComponent (). Por ejemplo, lo que parecía estar tratando de hacer en su otra pregunta se vería así:

 import java.awt.*; import java.awt.event.*; import javax.swing.*; public class PaintRectangle extends JPanel { private Point mouseLocation; public PaintRectangle() { setPreferredSize(new Dimension(500, 500)); MouseAdapter listener = new MouseAdapter() { @Override public void mousePressed(MouseEvent e) { updateMouseRectangle(e); } private void updateMouseRectangle(MouseEvent e) { mouseLocation = e.getPoint(); repaint(); } @Override public void mouseDragged(MouseEvent e) { updateMouseRectangle(e); } @Override public void mouseReleased(MouseEvent e) { mouseLocation = null; repaint(); } }; addMouseListener(listener); addMouseMotionListener(listener); } private Rectangle getRectangle() { if(mouseLocation != null) { return new Rectangle(mouseLocation.x - 5, mouseLocation.y - 5, 10, 10); } else { return null; } } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); Rectangle rectangle = getRectangle(); if(rectangle != null) { Graphics2D gg = (Graphics2D) g; gg.setColor(Color.BLUE); gg.fill(rectangle); gg.setColor(Color.BLACK); gg.draw(rectangle); } } public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { @Override public void run() { JFrame frame = new JFrame("Test"); frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); frame.getContentPane().add(new PaintRectangle()); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } }); } } 

Ver también http://docs.oracle.com/javase/tutorial/uiswing/painting/

Pesado vs peso ligero

Básicamente, un componente de gran peso está vinculado a su propio par nativo, donde los componentes livianos comparten un par nativo común.

En general, no es una buena idea mezclar componentes pesados ​​y livianos ya que hay problemas con el orden Z y, en mi experiencia (aunque se supone que es mejor ahora), hay problemas de pintura que pueden surgir.

Esta es la razón por la que no te animaste a utilizar la clase Canvas , probablemente porque intentabas colocarlo en un componente ligero … supongo

La ilusión de control

Uno de los mayores problemas para los recién llegados a la API de Swing es la ilusión de que tienes algún tipo de control sobre el proceso de pintura, y no es así. Es más fácil simplemente aceptarlo.

Lo mejor que puede hacer es solicitar que el administrador de repintado realice una actualización lo antes posible.

Además, no se garantiza que llamar a getGraphics devuelva un valor no nulo.

El orden correcto de las cosas

paint vs paintComponent

El problema aquí es que paint realiza varios trabajos importantes, y llamar a paintComponent es solo uno de ellos.

En Swing nos anima enormemente utilizar paintComponent siempre que deseemos realizar una pintura personalizada, esto es, generalmente, el nivel más bajo en el componente y se llama antes de que se pinten los componentes secundarios.

Si anulas la paint y luego pintas en los Graphics después de la llamada a super.paint terminarás pintando encima de todo, este no es siempre el resultado deseado

Incluso si lo fuera, los componentes secundarios se pueden pintar independientemente de su contenedor principal, haciendo que la pintura “sobre” los efectos de pintura que haya agregado.

Enlaces útiles

  • Pintura en Swing (habla de cómo funciona el proceso de pintura)
  • Realizando el Duelo Personalizado (en Swing)
  • Gráficos 2D Trail

Pensamientos de despedida

Solo los componentes que realmente se agregan a un componente, que está conectado a un par nativo, tendrán alguna vez un método de paint llamado. Así que intentar pintar a un componente que no se ha agregado a un contenedor es inútil …

..paintbrush-tipo GUI ..

Use una BufferedImage como superficie de pintura. Muestrelo en un JLabel . Coloque la etiqueta en el centro de un panel dentro de JScrollPane .

Llame a bufferedImage.getGraphics() según sea necesario, pero recuerde dispose() cuando label.repaint() y luego llame a label.repaint() .

Use componentes Swing en todo momento, y no anule nada.

Aquí hay un ejemplo del uso de una imagen como superficie de pintura .

¡Y aquí hay uno mejor !

No dije que la captura de pantalla era mejor, es el código que es mejor. 😉