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