Why is it that when I change the size of the window, the components are gone?

Asked

Viewed 99 times

2

I built an application using windowbuilder eclipse. In it, when clicking with the mouse, a picture is drawn according to the last selected button.

However, when I change the window size, all the drawings disappear.

After reading this question, that tutorial, and that article; I suppose I should override the method paint(Graphics g) and add fields to a class that stores the drawings.

But it’s not clear to me where I would do this. Because I really don’t understand what’s going on behind the scenes in the code.

Class created with windowbuilder

public class PintarFiguras {

    private JFrame frame;

    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    PintarFiguras window = new PintarFiguras();
                    window.frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * Create the application.
     */
    public PintarFiguras() {
        initialize();
    }

    /**
     * Initialize the contents of the frame.
     */
    private void initialize() {
        frame = new JFrame();
        frame.setBackground(Color.GRAY);
        frame.getContentPane().setBackground(Color.GRAY);
        frame.setBounds(100, 100, 450, 300);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JPanel canvas = new JPanel();
        canvas.setBackground(Color.WHITE);
        canvas.setForeground(Color.BLACK);
        canvas.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                // pegar coordenadas
                int x = e.getX();
                int y = e.getY();

                Graphics g = canvas.getGraphics(); 

                Artista.desenhar(g,x,y);
            }
        });
        frame.getContentPane().add(canvas, BorderLayout.CENTER);
        canvas.setLayout(new CardLayout(0, 0));

        JToolBar toolBar = new JToolBar();
        frame.getContentPane().add(toolBar, BorderLayout.NORTH);

        JButton btnQuadrado = new JButton("quadrado");
        btnQuadrado.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                Artista.setModo(MODOS.QUADRADO);
            }
        });
        toolBar.add(btnQuadrado);

        Component horizontalStrut = Box.createHorizontalStrut(20);
        toolBar.add(horizontalStrut);

        JButton btnCirculo = new JButton("circulo");
        btnCirculo.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                Artista.setModo(MODOS.CIRCULO);
            }
        });
        toolBar.add(btnCirculo);

        Component horizontalStrut_1 = Box.createHorizontalStrut(20);
        toolBar.add(horizontalStrut_1);

        JButton btnNada = new JButton("nada");
        btnNada.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                Artista.setModo(MODOS.NADA);
            }
        });
        toolBar.add(btnNada);

        Component horizontalStrut_2 = Box.createHorizontalStrut(20);
        toolBar.add(horizontalStrut_2);

        JButton btnLimpar = new JButton("limpar");
        btnLimpar.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                Graphics g = canvas.getGraphics();
                g.clearRect(0, 0, canvas.getWidth(), canvas.getHeight());
                frame.setBackground(Color.WHITE);
            }
        });
        toolBar.add(btnLimpar);
    }

}

Enum of the figures to draw

public enum MODOS {
QUADRADO, CIRCULO, NADA}

Artist class, who makes the drawings

public abstract class Artista {
    private static MODOS modo = MODOS.NADA;

    public static MODOS getModo() {
        return modo;
    }

    public static void setModo(MODOS modo) {
        Artista.modo = modo;
    }

    /**
     * pinta um objeto de acordo com o modo
     * https://docs.oracle.com/javase/tutorial/2d/basic2d/index.html
     */
    public static void desenhar(Graphics g, int x, int y) {     
        switch(modo){   

        case QUADRADO:
            pintarQuadrado(g,x,y);
            break;

        case CIRCULO:
            pintarCirculo(g,x,y);
            break;

        case NADA:
            break;
        }       
    }

    private static void pintarQuadrado(Graphics g, int x, int y) {
        g.fillRect(x, y, 20, 10);
    }

    private static void pintarCirculo(Graphics g, int x, int y) {
        g.drawOval(x, y, 20, 20);
    }

}

1 answer

4


The components are disappearing as they are only being added and painted once on Jpanel, but there is the callback of the method paint(Graphics g), which is always called when it is necessary to paint the canvas again, as in your case in a resize. So when you change the screen size, the objects will only appear again when you, by what I saw in the method, click somewhere on the screen.

Practically Java does all the dirty work through the Paint method and it makes sure that the objects will be drawn after some change in the panel.

One solution would be to make your class PintarFiguras Jpanel extender and so override the Paint method and place the method desenhar(Graphics g, int x, int y) within.

Thus, in the Mouselistener in mouseClicked just call the repaint.

For Jpanel reference, you don’t need to create a new object, just call this (in the scope of the class, of course)

Now, the variables x and y that were created within the mouseClicked, just do them in the scope of the class and assign the values normally.

The class PintarFiguras would look like this:

public class PintarFiguras extends JPanel {

private int x, y;

/**
 * Launch the application.
 */
public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
        public void run() {
            try {
                new PintarFiguras();

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });
}

/**
 * Create the application.
 */
public PintarFiguras() {
    initialize();
}

/**
 * Initialize the contents of the frame.
 */
private void initialize() {

    final JFrame frame = new JFrame();
    frame.setBackground(Color.GRAY);
    frame.getContentPane().setBackground(Color.GRAY);
    frame.setBounds(100, 100, 450, 300);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);


    this.setBackground(Color.WHITE);
    this.setForeground(Color.BLACK);
    this.addMouseListener(new MouseAdapter() {
        @Override
        public void mouseClicked(MouseEvent e) {
            // pegar coordenadas
            PintarFiguras.this.x = e.getX();
            PintarFiguras.this.y = e.getY();

            repaint();
        }
    });
    frame.getContentPane().add(this, BorderLayout.CENTER);
    this.setLayout(new CardLayout(0, 0));

    JToolBar toolBar = new JToolBar();
    frame.getContentPane().add(toolBar, BorderLayout.NORTH);

    JButton btnQuadrado = new JButton("quadrado");
    btnQuadrado.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            Artista.setModo(MODOS.QUADRADO);
        }
    });
    toolBar.add(btnQuadrado);

    Component horizontalStrut = Box.createHorizontalStrut(20);
    toolBar.add(horizontalStrut);

    JButton btnCirculo = new JButton("circulo");
    btnCirculo.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            Artista.setModo(MODOS.CIRCULO);
        }
    });
    toolBar.add(btnCirculo);

    Component horizontalStrut_1 = Box.createHorizontalStrut(20);
    toolBar.add(horizontalStrut_1);

    JButton btnNada = new JButton("nada");
    btnNada.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            Artista.setModo(MODOS.NADA);
        }
    });
    toolBar.add(btnNada);

    Component horizontalStrut_2 = Box.createHorizontalStrut(20);
    toolBar.add(horizontalStrut_2);

    JButton btnLimpar = new JButton("limpar");
    btnLimpar.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            limparTela();
        }
    });
    toolBar.add(btnLimpar);

    frame.setVisible(true);
}

public void paint(Graphics g){
    super.paint(g);
    Artista.desenhar(g, this.x, this.y);
}

public void limparTela(){
    Graphics g = this.getGraphics();
    g.setColor(Color.white);
    g.fillRect(0, 0, getWidth(), getHeight());
}

EDIT: as @diegofm indicated, I declared Jframe as final within the scope of the method, so it can be called normally within anonymous classes, as used by OP.

  • 1

    There’s a little error in the code, something easy to fix, frame It needs to be final in order to be called inside the actionlistener. Anonymous classes only access class parameters or local variables that are final.

  • 1

    I tidied it up, thank you. Jframe was declared private, but it wasn’t necessary, so I went to the scope of the method and made it final.

  • 1

    Very good answer, +1

  • I wish the new drawing doesn’t erase the old ones. How can I store the drawings already made to be repainted as well? What class they are, Graphics?

  • 1

    You can save the coordinates and attributes (x, y, width, height) of the drawings, and then draw them. In the case of the rectangle has up to class representing the shape (Rectangle). And if I am not mistaken has to the circle also (Ellipse2d)

Browser other questions tagged

You are not signed in. Login or sign up in order to post.