Repaint method not working on JComponent java swing

68 Views Asked by At

I want to have a text field to input an integer, then select 1) Grow or 2) Shrink, and then click the button so that the circle gets redrawn on the screen based on the selected options.

I don't know why it isn't repaining. (Don't worry about the layout, just want to get it to work first)

My Frame:

public class Main {
    public static void main(String[] args) {
        var frame = new JFrame();
        frame.setSize(400,400);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
        var circleComp = new circleComponent();
        var panel1 = new JPanel();
        var multiplierLabel = new JLabel("Grow Multiplier");
        var multiplierField = new JTextField(20);
        var radio1 = new JRadioButton("Grow Circle");
        var radio2 = new JRadioButton("Shrink Circle");
        var bg = new ButtonGroup();
        bg.add(radio1);
        bg.add(radio2);
        JButton button = new JButton("Rivizato");
        button.addActionListener(
                new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        if(radio1.isSelected()){
                         rrComp.repaint(0,0,Integer.parseInt(multiplierField.getText())*rrComp.getWidth(), Integer.parseInt(multiplierField.getText())*rrComp.getHeight());
                        }
                        else if(radio2.isSelected()){
                            rrComp.repaint(0,0,Integer.parseInt(multiplierField.getText())/rrComp.getWidth(), Integer.parseInt(multiplierField.getText())/rrComp.getHeight());
                        }
                    }
                }
        );


        panel1.add(multiplierLabel);
        panel1.add(multiplierField);
        panel1.add(button);
        panel1.add(radio1);
        panel1.add(radio2);
        frame.add(panel1);
        frame.add(circleComp);
    }
}

My CircleComponent class:

public class CircleComponent extends JComponent {
    public void paintComponent(Graphics g){
        super.paintComponent(g);
        var g2 = (Graphics2D) g;
        var circle = new Ellipse2D.Double(0,0,100,100);
        g2.draw(circle);
    }
}

1

There are 1 best solutions below

0
MadProgrammer On

var circle = new Ellipse2D.Double(0,0,100,100); means that your circle will never change size.

You should also be careful with repaint(x, y, width, height) as it could leave regions of your component "dirty". Better to just use repaint.

As a conceptual example...

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public final class Main {
    public static void main(String[] args) {
        new Main();
    }

    public Main() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new MainPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class MainPane extends JPanel {
        private CirclePane circlePane;
        public MainPane() {
            setLayout(new BorderLayout());

            JPanel actionsPane = new JPanel(new GridBagLayout());
            JButton growButton = new JButton("Grow");
            growButton.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    circlePane.grow();
                }
            });
            JButton shrinkButton = new JButton("Shrink");
            shrinkButton.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    circlePane.shrink();
                }
            });
            actionsPane.add(growButton);
            actionsPane.add(shrinkButton);

            circlePane = new CirclePane();
            add(circlePane);
            add(actionsPane, BorderLayout.SOUTH);
        }
    }

    public class CirclePane extends JPanel {

        private Ellipse2D circle;

        public CirclePane() {
            circle = new Ellipse2D.Double(0, 0, 100, 100);
        }

        public void grow() {
            double width = circle.getWidth() + 10;
            double height = circle.getHeight() + 10;
            circle.setFrame(0, 0, width, height);
            repaint();
        }

        public void shrink() {
            double width = Math.max(0, circle.getWidth() - 10);
            double height = Math.max(0, circle.getHeight() - 10);
            circle.setFrame(0, 0, width, height);
            repaint();
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(400, 400);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            double x = (getWidth() - circle.getWidth()) / 2d;
            double y = (getHeight() - circle.getHeight()) / 2d;            
            g2d.translate(x, y);
            g2d.draw(circle);            
            g2d.dispose();
        }

    }
}

nb: I know I've not used JTextField to specify the size of the circle, that's on purpose. You will need to adapt your requirements to work in a similar way - can you see where you might pass parameters to the CirclePane?