Search code examples
javaswingpaintcomponent

Java Swing with event Handling


I am new in Java Programming and its my first time that i am developing a swing application in java Swing. i want to implement a simple paint editor that has few buttons to add simple shapes like rectangle,square and etc. The problem is that i cant print the shapes without actionListener but i want to use buttons to do the action for me. I want to print or draw the shape whenever i clicked the button on the same frame that i have the buttons.

I have a DrawingPanel.java file which i got it from internet and i wrote these two other classes:

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

public class addRect extends JPanel {
    public void paintComponent(Graphics g){
        super.paintComponent(g);
        g.fillRect(50, 30, 200, 100);
        g.setColor(Color.BLUE);

    }
}

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

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

        public JFrame frame;
        private JButton button1;
        private JButton button2;
        private JButton button3;
        private JButton button4;

    public test() {

        frame = new JFrame("Paint Program");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(new Dimension(350, 100));
        button1=new JButton("AddRectangle");
        button2=new JButton("AddSquare");
        button3=new JButton("AddCircle");
        button4=new JButton("Clear");

        frame.setVisible(true);
        button1.addActionListener(new VerifyListener());


        frame.setLayout(new FlowLayout());
        frame.add(button1);
        frame.add(button2);
        frame.add(button3);
        frame.add(button4);
    }
    public class VerifyListener implements ActionListener {
        public void actionPerformed(ActionEvent event) {
            addRect panel=new addRect();
            frame.add(panel);
            panel.setVisible(true);
        }
    }
}

Solution

  • You've got several problems with the code above:

    • Your addRect JPanel's preferred size is 0, 0, and so if and when it is added to the GUI, it will never show.
    • You add a component to a container (the JFrame's contentPane) during program run, but haven't called revalidate() and repaint() on the container, and so the container's layout managers won't layout the new component.
    • You shouldn't swap images by adding JPanels. Instead you should have one drawing JPanel, and have it change what it draws by calling public methods on it.
    • Don't call setVisible(true) on your JFrame until after adding components to it, else some components might not possibly show.
    • Avoid setting the size of any Swing component and instead let the components and layout managers size themselves.
    • As an aside, you will want to learn and use Java naming conventions. Variable names should all begin with a lower letter while class names with an upper case letter. Learning this and following this will allow us to better understand your code, and would allow you to better understand the code of others.

    For example in the code below, I've create several buttons and passed them anonymous ActionListeners, most of them with un-implemented code, and one of them, the listener that calls addRectangle(), with implemented code. In the implementation, I simply have the method call a method on the DrawingPanel object: drawingPanel.setDrawRect(true);. This method changes the state of the drawRect boolean held in the DrawingPanel class, and then calls repaint() on this JPanel. The JPanel's paintComponent method uses the boolean to decide whether it should draw a rectangle or not:

    import java.awt.*;
    import java.awt.event.*;
    
    import javax.swing.*;
    
    public class TestDrawingPanel extends JPanel {
        private JButton addRectButton = new JButton("Add Rectangle");
        private JButton addSquareButton = new JButton("Add Square");
        private JButton addCircleButton = new JButton("Add Circle");
        private JButton clearButton = new JButton("Clear");
    
        private DrawingPanel drawingPanel = new DrawingPanel();
    
        public TestDrawingPanel() {
            // add ActionListeners
            addRectButton.addActionListener(evt -> addRectangle());
            addSquareButton.addActionListener(evt -> addSquare());
            addCircleButton.addActionListener(evt -> addCircle());
            clearButton.addActionListener(evt -> clear());
            JButton[] btns = { addRectButton, addSquareButton, addCircleButton, clearButton };
    
            // jpanel uses grid layout with one row and variable number of columns
            // and add all buttons to it
            JPanel buttonPanel = new JPanel(new GridLayout(1, 0, 3, 3));
            for (JButton btn : btns) {
                buttonPanel.add(btn);
            }
    
            setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3)); // blank border
            setLayout(new BorderLayout());
            add(buttonPanel, BorderLayout.PAGE_START); // add button panel to the top
            add(drawingPanel, BorderLayout.CENTER);  // add drawing panel to the center
        }
    
        private void addRectangle() {
            drawingPanel.setDrawRect(true);  // tell the drawing panel to draw the rectangle
        }
    
        private void addSquare() {
            // TODO: implement        
        }
    
        private void addCircle() {
            // TODO: implement
        }
    
        private void clear() {
            drawingPanel.setDrawRect(false);
            // TODO: complete
        }
    
        private static void createAndShowGui() {
            TestDrawingPanel mainPanel = new TestDrawingPanel();
    
            JFrame frame = new JFrame("Paint Program");
            frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
            frame.getContentPane().add(mainPanel);
            frame.pack();
            frame.setLocationByPlatform(true);
            frame.setVisible(true);
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(() -> createAndShowGui());
        }
    
    }
    
    // class addRect extends JPanel {
    class DrawingPanel extends JPanel {
        // size information
        private static final int PREF_W = 300;
        private static final int PREF_H = PREF_W;
        private boolean drawRect = false;  // use this to decide if should draw rectangle or not
    
        public DrawingPanel() {
            setBorder(BorderFactory.createTitledBorder("Drawing Panel"));
        }
    
        // allow outside classes to set the drawRect field
        public void setDrawRect(boolean drawRect) {
            this.drawRect = drawRect;
            repaint();
        }
    
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
    
            // if true, draw the rectang.e
            if (drawRect) {
                g.setColor(Color.BLUE);
                g.fillRect(50, 30, 200, 100);
            }
    
            // TODO: complete rest
        }
    
        // So that the drawing JPanel will size appropriately
        @Override
        public Dimension getPreferredSize() {
            if (isPreferredSizeSet()) {
                return super.getPreferredSize();
            }
            return new Dimension(PREF_W, PREF_H);
        }
    }