Java Swing 与事件处理

Java Swing with event Handling

我是 Java 编程的新手,这是我第一次在 java Swing 中开发 swing 应用程序。 我想实现一个简单的绘图编辑器,它有几个按钮来添加简单的形状,如矩形、正方形等。 问题是我无法在没有 actionListener 的情况下打印形状,但我想使用按钮为我执行操作。 每当我单击具有按钮的同一帧上的按钮时,我都想打印或绘制形状。

我有一个 DrawingPanel.java 文件,我从互联网上得到它,我写了另外两个 类:

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);
        }
    }
}

上面的代码有几个问题:

  • 您的 addRect JPanel 的首选大小是 0、0,因此如果将其添加到 GUI 中,它将永远不会显示。
  • 您在程序 运行 期间将组件添加到容器(JFrame 的 contentPane),但没有在容器上调用 revalidate()repaint(),因此容器的布局经理不会布置新组件。
  • 您不应通过添加 JPanel 来交换图像。相反,您应该有一个绘图 JPanel,并通过调用其上的 public 方法让它改变它所绘制的内容。
  • 向其添加组件之前,不要在您的 JFrame 上调用 setVisible(true),否则某些组件可能无法显示。
  • 避免设置任何 Swing 组件的大小,而是让组件和布局管理器自行调整大小。
  • 顺便说一句,您会想要学习和使用 Java naming conventions。变量名称应全部以小写字母开头,而 class 名称应以大写字母开头。了解并遵循这一点将使我们能够更好地理解您的代码,并使您能够更好地理解其他人的代码。

例如,在下面的代码中,我创建了几个按钮并向它们传递了匿名 ActionListeners,其中大部分都带有未实现的代码,其中之一是调用 addRectangle() 的侦听器,带有已实现的代码代码。在实现中,我只是让方法调用 DrawingPanel 对象上的方法:drawingPanel.setDrawRect(true);。此方法更改 DrawingPanel class 中保存的 drawRect 布尔值的状态,然后在此 JPanel 上调用 repaint()。 JPanel 的 paintComponent 方法使用布尔值来决定它是否应该绘制一个矩形:

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);
    }
}