plu*_*ava 1 java swing awt actionlistener
这是我直接从“Head First Java”获得的来源,但无论我做什么,我似乎都无法使其工作,而且我不知道我可能会错过什么
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class SimpleGui3C implements ActionListener {
JFrame frame;
public static void main(String[] args) {
SimpleGui3C gui = new SimpleGui3C();
gui.go();
}
public void go() {
MyDrawPanel drawPanel = new MyDrawPanel();
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton button = new JButton("Change colors");
button.addActionListener(this);
frame.getContentPane().add(BorderLayout.SOUTH, button);
frame.getContentPane().add(BorderLayout.CENTER, drawPanel);
frame.setSize(300, 300);
frame.setVisible(true);
}
public void actionPerformed(ActionEvent event) {
frame.repaint();
}
}
class MyDrawPanel extends JPanel {
public void paintComponent(Graphics g) {
g.setColor(Color.white);
g.fillRect(0, 0, 300, 300);
int red = (int) (Math.random() * 255);
int green = (int) (Math.random() * 255);
int blue = (int) (Math.random() * 255);
Color randomColor = new Color(red, green, blue);
g.setColor(randomColor);
g.fillOval(70, 70, 100, 100);
}
}
Run Code Online (Sandbox Code Playgroud)
我试图找到另一种方法来做到这一点,它不涉及重新绘制,而是在事件发生时创建 MyDrawPanel 的新实例,但它仍然不起作用,因为我没有找到正确清除面板的方法,到目前为止我发现的唯一黑客就是这样做,但这不是我想要实现的......
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class SimpleGui3C implements ActionListener {
JFrame frame;
public static void main(String[] args) {
SimpleGui3C gui = new SimpleGui3C();
gui.go();
}
public void go() {
MyDrawPanel drawPanel = new MyDrawPanel();
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton button = new JButton("Change colors");
button.addActionListener(this);
frame.getContentPane().add(BorderLayout.SOUTH, button);
frame.getContentPane().add(BorderLayout.CENTER, drawPanel);
frame.setSize(300, 300);
frame.setVisible(true);
}
public void actionPerformed(ActionEvent event) {
go();
}
}
class MyDrawPanel extends JPanel {
int red;
int green;
int blue;
public MyDrawPanel() {
this.red = (int) (Math.random() * 255);
this.green = (int) (Math.random() * 255);
this.blue = (int) (Math.random() * 255);
}
public void paintComponent(Graphics g) {
g.setColor(Color.white);
g.fillRect(0, 0, 300, 300);
Color randomColor = new Color(this.red, this.green, this.blue);
g.setColor(randomColor);
g.fillOval(70, 70, 100, 100);
}
}
Run Code Online (Sandbox Code Playgroud)
在处理事情的时候Swing,人们应该记住一些事情。当我查看您使用的代码时,我想向您指出,以使其走上正确的道路。
Swing基于应用程序的应用程序从它们自己各自的线程(称为 )启动,EventDispatcherThread ( EDT )而不是直接从 main 启动。有关该主题的更多信息可以在Swing 中的并发上找到
paintComponent ( ...
)方法内部执行任何计算,而是在其他地方执行这些计算,然后简单地调用repaint ()paintComponent ( ... )isprotected和 not的访问说明符public,因此在重写超类的方法时,尽量不要更改方法访问权限,除非不必要。JPanel调用,而不是顶层容器的repaint ()JPanelJComponenet/JPanel,总是尝试覆盖上述的布局JComponent/JPanel,如果没有指定,getPreferredSize ()将返回尽可能多的布局0,因此不会进行任何绘制。super.paintComponent ( g ),作为里面的第一行paintComponent ( ... )。为了更加清晰,添加了评论。JFrame,而是尝试调用pack (),如Java 文档中所述,以获得附带的好处。pack 方法调整框架的大小,以便其所有内容都等于或大于其首选大小。pack 的替代方法是通过调用 setSize 或 setBounds(这也设置帧位置)显式建立帧大小。一般来说,使用 pack 比调用 setSize 更好,因为 pack 让框架布局管理器负责框架大小,而布局管理器擅长调整平台依赖性和影响组件大小的其他因素。这是修改后的代码(只是在里面添加了一个方法DrawPanel,称为setValues (),在其中完成计算并被repaint ()调用),基于以上几点:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class SimpleGui implements ActionListener {
private MyDrawPanel drawPanel;
public static void main(String[] args) {
Runnable r = new Runnable () {
@Override
public void run () {
new SimpleGui ().go ();
}
};
EventQueue.invokeLater ( r );
}
public void go() {
drawPanel = new MyDrawPanel();
JFrame frame = new JFrame();
frame.setDefaultCloseOperation( JFrame.DISPOSE_ON_CLOSE );
JButton button = new JButton( "Change colors" );
button.addActionListener( this );
frame.add( drawPanel, BorderLayout.CENTER );
frame.add( button, BorderLayout.PAGE_END );
frame.pack ();
frame.setLocationByPlatform ( true );
frame.setVisible(true);
}
public void actionPerformed(ActionEvent event) {
drawPanel.setValues ();
}
}
class MyDrawPanel extends JPanel {
private int width = 300;
private int height = 300;
private int red;
private int green;
private int blue;
private Color randomColor;
/*
* Make this one customary habbit,
* of overriding this method, when
* you extends a JPanel/JComponent,
* to define it's Preferred Size.
* Now in this case we want it to be
* as big as the Image itself.
*/
@Override
public Dimension getPreferredSize () {
return new Dimension ( width, height );
}
public void setValues () {
red = ( int ) ( Math.random() * 255 );
green = ( int) ( Math.random() * 255 );
blue = ( int ) ( Math.random() * 255 );
randomColor = new Color( red, green, blue );
repaint ();
}
/*
* This is where the actual Painting
* Code for the JPanel/JComponent goes.
* Here the first line super.paintComponent(...),
* means we want the JPanel to be drawn the usual
* Java way first (this usually depends on the opaque
* property of the said JComponent, if it's true, then
* it becomes the responsibility on the part of the
* programmer to fill the content area with a fully
* opaque color. If it is false, then the programmer
* is free to leave it untouched. So in order to
* overcome the hassle assoicated with this contract,
* super.paintComponent(g) is used, since it adheres
* to the rules, and performs the same task, depending
* upon whether the opaque property is true or false),
* then later on we will add our image to it, by
* writing the other line, g.drawImage(...).
*/
@Override
protected void paintComponent(Graphics g) {
super.paintComponent ( g );
g.setColor(randomColor);
g.fillOval(70, 70, 100, 100);
}
}
Run Code Online (Sandbox Code Playgroud)