Jump to content

Dúvida no método paintComponent(Graphics g)


Nuno_Martins
 Share

Recommended Posts

Olá pessoal,

À poucos dias comecei a aprender umas coisas sobre Swing, mas estou com uma dúvida acerca do método paintComponent(Graphics g) .

Basicamente a dúvida consiste em saber quando é que o método é chamado no código que vos vou apresentar de seguida.

O que o programa faz é desenhar um circulo e podermos aumentar ou diminuir o seu tamanho.

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

public class ControlBall extends JFrame{

private JButton jbtEnlarge = new JButton("Enlarge");
private JButton jbtShrink = new JButton("Shrink");
private BallCanvas canvas = new BallCanvas();

public ControlBall() {
	JPanel panel = new JPanel();
	panel.add(jbtEnlarge);
	panel.add(jbtShrink);

	this.add(canvas, BorderLayout.CENTER);
	this.add(panel, BorderLayout.SOUTH);

	jbtEnlarge.addActionListener(new ActionListener() {
		public void actionPerformed(ActionEvent arg0) {
			canvas.enlarge();
		}
	});

	jbtShrink.addActionListener(new ActionListener() {
		public void actionPerformed(ActionEvent e) {
			canvas.shrink();
		}
	});
}

public static void main(String[] args) {
	JFrame frame = new ControlBall();
	frame.setTitle("ControlBall");
	frame.setLocationRelativeTo(null);
	frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	frame.setSize(200, 200);
	frame.setVisible(true);
}

public static class BallCanvas extends JPanel {
	private int radius = 5;

	public void enlarge() {
		radius += 1;
		repaint();
	}

	public void shrink() {
		radius -= 1;
		repaint();
	}

	protected void paintComponent(Graphics g) {
		super.paintComponent(g);
		g.drawOval(getWidth() / 2 - radius, getHeight() / 2 - radius, 
					2 * radius, 2 * radius);
	}
}
}

Para ver se eu estou a compreender bem a sequência do código, vou aqui fazer um resumo de como eu penso que funciona:

Temos a aplicação a ser executada... acontece um click no botão Enlarge, vai para o respectivo Listener que lá dentro chama o método enlarge() . Dentro deste método aumenta-se o raio e volta-se a desenhar. Supostamente depois disto, o programa fica à "escuta" de novos eventos, certo? Então no meio de tudo isto, quando é que o método paintComponent(Graphics g) é realmente chamado?  🙂

Já agora para aproveitar, o método repaint() desenha toda a janela da aplicação, ou seja, toda a JFrame ou apenas algum componente em especifico?

NOTA: Eu estou a aprender Swing a seguir um livro que compre à uns tempos, mas se acharem que alguma coisa não esteja correcta agradeço que critiquem, mais vale aprender agora de inicio do que mais tarde estar a alterar  😛

Link to comment
Share on other sites

O método paintComponent é chamado automaticamente pela JVM. Tipicamente não é invocado pelo programador, aliás, é raro ter de ser o programador a invocar directamente alguns dos métodos de desenho. Isto porque estás a re-implementar o método que o todos os componentes Swing têm, se fosse um método teu então terias de o invocar tu manualmente, se estiveres a reutilizar os componentes que o Swing te oferece, então não precisas preocupar-te com grande parte do código de desenho, precisas saber como funciona mas não o invocas directamente.

O método repaint pede ao Swing para redesenhar um componente, a consequência de redesenhares um componente é que todos os componentes que estejam dentro desse são, também, redesenhados. Portanto, se fizeres um repaint da JFrame, então toda a aplicação é redesenhada. Se fizeres apenas de um JPanel, apenas esse JPanel e o que estiver lá dentro é redesenhado.

Naturalmente, apesar de pedires um repaint apenas a um JPanel, esse repaint pode forçar o repaint de outros componentes, por exemplo, se mudas o tamanho do JPanel de modo alterares a posição de componentes que estão ao lado, ao pedires o repaint do JPanel, os componentes que se mexeram também vão ser redesenhados.

Porque é que colocaste o método paintComponent como protected? A visibilidade dele no JPanel é public.

Link to comment
Share on other sites

Agora o que podes tu fazes em vez de tares a usares o repaint() e o PaintComponente(g).

Cria uma função que redesenha somente aquilo que tu queres e dessa forma so ira reconstruir/redesenhar novamente aquilo que prentendes 🙂 .

Algo deste genero relaciona num Jpanel é laro se for Jframe alteras 😛

public void repaintComponentsNecess(Graphics g) {
        super.paintComponents(g);
        int width = this.DrawPanel.getWidth();
        int height = this.DrawPanel.getHeight();

        //Cria a imagem novamente
        if (this.ScreenImg == null) {
            this.ScreenImg = this.createImage(width, height);
            System.out.println("img = " + this.ScreenImg.getWidth(this) + ", " + this.ScreenImg.getHeight(this));
        }
        Graphics ScreenImgGraphics = DrawPanel.getGraphics();
        ScreenImgGraphics.setColor(this.DrawPanel.getBackground());
        this.DrawPanel.setBorder(BorderFactory.createLineBorder(Color.black));

    }

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.