Draw is not made when a button event is triggered

Viewed 35

I'm trying to make a silly program. I got this JPanel called Canvas which is supposed to draw lines with some given specific directions, as you cas see here, for the moment I'm just creating the button action, and that button is supposed to draw a line from the first point of the first column to the last point (fourth) of the second column. Right now those text fields don't get into this because those have no functionality for the moment.

public class Canvas extends JPanel {
    static final int SCREEN_WIDTH = 300;
    static final int SCREEN_HEIGHT = 300;
    private Graphics g2d;
    
    public Canvas() {
        this.setPreferredSize(new Dimension(SCREEN_WIDTH,SCREEN_HEIGHT));
        this.setBackground(new Color(66, 64, 64));
    }
    
    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        g2d = g;
        trazarLinea('a', 1, new Color(75, 201, 201));  // This draw the lines seen in the  
        trazarLinea('b', 3, new Color(240, 20, 255));  // image as example.
        trazarLinea('c', 1, new Color(235, 64, 52));
        trazarLinea('d', 2  , new Color(128, 64, 123));
        dibujarCirculos(); // This draw the orange circles seen in the image when the program is 
                           // executed.
    }
    
    public void dibujarCirculos() {
        g2d.setColor(new Color(230, 160, 30));
        g2d.fillOval(20, 20, 20, 20);
        g2d.fillOval(20, 97, 20, 20);
        g2d.fillOval(20, 182, 20, 20);
        g2d.fillOval(20, 255, 20, 20);
        g2d.fillOval(270, 20, 20, 20);
        g2d.fillOval(270, 97, 20, 20);
        g2d.fillOval(270, 182, 20, 20);
        g2d.fillOval(270, 255, 20, 20);
    }
    
    /* This method makes lines with an initial and final position,
       but it just work when the program is executed the first time,
       so I'm using another method that makes one line.
    */
    public void trazarLinea(char posi, int posf, Color c) {
        final int X1 = 27;
        final int Y2 = 275;
        int y1 = 0, y2 = 0;
        ((Graphics2D) g2d).setStroke(new BasicStroke(6));
        g2d.setColor(c);
        
        switch (posi) {
            case 'a':
                y1 = 30;
            break;
            case 'b':
                y1 = 109;
            break;
            case 'c':
                y1 = 194;
            break;
            case 'd':
                y1 = 264;
            break;
            default:
                y1 = 30;
        }

        switch (posf) {
            case 1:
                y2 = 30;
            break;
            case 2:
                y2 = 109;
            break;
            case 3:
                y2 = 194;
            break;
            case 4:
                y2 = 264;
            break;
            default:
                y2 = 30;
        }
        
        g2d.drawLine(X1, y1, Y2, y2);
    }
    
    /* The revalidate and repaint are here because I had them in the other Window class
       but that doesn't seem to work.
    */
    public void drawL() {
        final int X1 = 27;
        final int Y2 = 275;
        ((Graphics2D) g2d).setStroke(new BasicStroke(6));
        g2d.setColor(new Color(240, 20, 255));
        g2d.drawLine(X1, 30, Y2, 264);
        revalidate();
        repaint();
    }
}

In the class that is below I have a button which is supposed to draw that line once I clicked it. Some people told me to revalidate and repaint the canvas but that doesn't work.

public class Window extends JFrame {
    
    private JTextField txt_ubicacion;
    private JTextField txt_color;
    private JPanel panel_1;
    private Canvas canva;

    Ventana() { 
        this.setPreferredSize(new Dimension(575, 330));
        this.setTitle("Relación de puntos - canvas");
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setVisible(true);
        setResizable(true);
        panel_1 = new JPanel();
        getContentPane().add(panel_1, BorderLayout.NORTH);
        iniciarComponentes();
        this.pack();
        this.setLocationRelativeTo(null);
    }

    public void iniciarComponentes() {
    // I've cut some things here.

        canva = new Canvas();
        canva.setLayout(null);
        GroupLayout gl_panel_1 = new GroupLayout(panel_1);
        panel_1.setLayout(gl_panel_1);
        
        JButton boton_dibujar = new JButton("Dibujar");
        boton_dibujar.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                canva.drawL();
            }
        });
        boton_dibujar.setFocusPainted(false);
        boton_dibujar.setBackground(new Color(0, 139, 139));
        boton_dibujar.setFont(new Font("JetBrains Mono Medium", Font.PLAIN, 11));
        boton_dibujar.setBounds(10, 207, 104, 23);
        panel_izquierdo.add(boton_dibujar);
    }
    
    @Override
    public void paint(Graphics g) {
        super.paint(g); // I read that those repaints should be made in the same class, but I 
                        // don't really know how could I do that here or somewhere.
    }
    
    public static void main(String[] args) {
        new Window();
    }
}

Summary: When I clicked a button it should appear a line in the JPanel, but doesn't happen and no error is shown neither.

1 Answers
  1. Don't call your class Canvas. There is an AWT class with that name.
  2. Don't call your class Window. There is an AWT class with that name.

Class names should be more descriptive.

All painting must be done in the paintComponent(...) method. So you need to:

  1. get rid of the "g2d" instance variable. You can pass the Graphics object of the paintComponent() method to any method you create to do your painting.

  2. create an instance variable like "isButtonPressed". Then you also need a method like setButtonPressed(boolean) so you can change the property of this variable. This method will simply set the value of the instance variable and then invoke repaint().

Then in the paintComponent() method you add logic like:

if (isButtonPressed)
    trazarLinea(g);

In the ActionListener of your button you then have code like:

canva.setButtonPressed(true);

Read the Swing tutorial on Custom Painting. It demonstrates how to change the state of the component on a mouse click. In your case you do this with a JButton.

Related