paintComponent () vs paint () e JPanel vs Canvas em uma GUI do tipo pincel

Eu tenho algumas idéias interessantes e críticas a partir deste , este e este post (veja o último post para o código da GUI em questão). No entanto, ainda estou bastante confuso sobre algumas coisas. Principalmente, qual é a maneira menos dispendiosa de exibir os charts do usuário?

Mais especificamente, usei um método paintComponent() da class JPanel , criando um object dessa class no método MouseDragged() junto com o método paintComponent(getGraphics()) ( AuxClass2 e AuxClass1 acordo).

Aparentemente, usando getGraphics() e paintComponent() vez de repaint() são idéias ruins, suspeito que algo tenha a ver com o uso da memory. Também chamando o AuxClass2 toda vez que o usuário arrasta o mouse também é uma má idéia.

Também JPanel vs Canvas (ou seja, swing vs awt) é um pouco confuso. O que é usado e quando?

Eu tenho tentado encontrar algumas soluções alternativas, mas não encontrei uma, especialmente para o método getGraphics() : como mais os charts podem ser adicionados ao painel?

Eu tenho tentado encontrar algumas soluções alternativas, mas não encontrei uma, especialmente para o método getGraphics (): como mais os charts podem ser adicionados ao painel?

Você se lembra do que precisa ser pintado como uma variável e usa isso em paintComponent (). Por exemplo, o que você parecia estar tentando fazer na sua outra pergunta seria:

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

Veja também http://docs.oracle.com/javase/tutorial/uiswing/painting/

Peso pesado vs leve

Basicamente falando, um componente de peso pesado está ligado ao seu próprio par nativo, onde os componentes leves compartilham um par nativo comum.

Em geral, não é uma boa idéia misturar componentes pesados ​​e leves, pois há problemas com o z-order e, na minha experiência (embora deva ser melhor agora), há problemas de pintura que podem surgir.

Esta é a razão pela qual você foi desencorajado de usar a class Canvas , provavelmente porque você estava tentando colocá-lo em um componente leve … Eu acho

A ilusão do controle

Um dos maiores problemas para os novatos na API do Swing é a ilusão de que você tem algum tipo de controle sobre o processo de pintura, você não tem. É mais fácil apenas aceitá-lo.

O melhor que você pode fazer é solicitar que o gerente de repintura realize uma atualização assim que possível.

Além disso, não é garantido que chamar getGraphics retorne um valor não nulo.

A ordem correta das coisas

paint vs paintComponent

O problema aqui é que a paint faz um número de trabalhos importantes, chamando paintComponent é apenas um deles.

No Swing, somos muito encorajados a usar o paintComponent sempre que quisermos executar a pintura personalizada, geralmente, é o nível mais baixo no componente e é chamado antes que os componentes filhos sejam pintados.

Se você replace a paint e, em seguida, pintar no Graphics após a chamada para super.paint você vai acabar pintando em cima de tudo, isso nem sempre é o resultado desejado

Mesmo que fosse, os componentes infantis podem ser pintados independentemente do recipiente principal, fazendo com que a tinta “supere” qualquer efeito de pintura que você tenha adicionado

Links Úteis

  • Pintura no Swing (fala sobre como funciona o processo de pintura)
  • Executando Pains Customizadas (no Swing)
  • Trilha Gráfica 2D

Pensamentos de despedida

Somente os componentes que são realmente adicionados a um componente, que é anexado a um par nativo, sempre terão o método paint chamado. Então, tentar pintar para um componente que não foi adicionado a um contêiner ainda é bastante inútil …

..paintbrush-tipo GUI ..

Use um BufferedImage como a superfície de pintura. Exibe-o em um JLabel . Coloque o label no centro de um painel dentro de um JScrollPane .

Chame bufferedImage.getGraphics() conforme necessário, mas lembre-se de dispose() quando terminar e, em seguida, chamar label.repaint() .

Use componentes Swing por toda parte e não substitua nada.

Aqui está um exemplo de usar uma imagem como superfície de pintura .

E aqui está um melhor !

Eu não disse que a canvas era melhor, é o código que é melhor. 😉