我仍在学习GUI,但仍难以理解线程:/
我在制作这个有2个圆圈的GUI,一个大(100x100)和一个小(50x50)。小圆圈将移到大圆圈的边缘,在0.5秒内,小圆圈将移至中心,当用户必须单击时将移至小圆圈。每当用户单击圆圈中间的位置时,用户就会得分。我唯一遇到的麻烦是,圆环没有移动,因为我怀疑它与我的线程有关,因此,我之所以使用线程,是为了了解如何使用它们。
图形用户界面
public class gui extends JPanel implements MouseListener,
Runnable {
Thread t = new Thread();
int score = 0;
int rnd;
static final int smallcircleposx = 75;
static final int smallcircleposy = 75;
int circleposx = 75;
int circleposy = 75;
int mousex, mousey;
Random random = new Random();
public gui() {
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.BLUE);
g.fillOval(50, 50, 100, 100);
g.setColor(Color.RED);
g.fillOval(circleposx, circleposy, 50, 50);
}
// THREAD FOR MOVING THE CIRCLE
public void run() {
rnd = random.nextInt(999);
if (rnd % 5 == 0) {
circleposx = circleposx + 25;
} else if (rnd % 4 == 0) {
circleposx = circleposx - 25;
} else if (rnd % 3 == 0) {
circleposy = circleposy + 25;
} else {
circleposy = circleposy - 25;
}
try {
Thread.sleep(500);
circleposx = smallcircleposx;
circleposy = smallcircleposy;
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void mouseClicked(MouseEvent m) {
if (circleposx == smallcircleposx && circleposy == smallcircleposy) {
score++;
}
}
主要
public class main {
public static void main(String[] args) {
JFrame frame = new JFrame("Circle enlarger");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400,400);
frame.setVisible(true);
gui co = new gui();
frame.add(co);
frame.addMouseListener(co);
Thread x = new Thread(new gui());
x.start();
}
}
我知道我没有使用所有
mouselistener
方法。 最佳答案
需要记住的几点:
如果不覆盖所有方法,请使用MouseAdaptor
代替MouseListener
。
不要直接在顶层容器(例如JFrame
,JApplet
)上绘画,而要使用JPanel
不要使用有时会挂起整个Swing应用程序的Thread.sleep()
,而是尝试最适合Swing应用程序的Swing Timer。
阅读更多How to Use Swing Timers
不要忘记在覆盖的super.paintComponent()
方法中调用paintComponent()
。
添加所有组件后,最后调用frame.setVisible(true)
。
根据组件的首选大小,使用frame.pack()
代替适合组件的frame.setSize()
。
在自定义绘画的情况下,覆盖getPreferredSize()
以设置JPanel
的首选大小。
使用SwingUtilities.invokeLater()或EventQueue.invokeLater()确保EDT正确初始化。
阅读更多
Why to use SwingUtilities.invokeLater in main method?
SwingUtilities.invokeLater
Should we use EventQueue.invokeLater for any GUI update in a Java desktop application?
值得阅读Lesson: Performing Custom Painting
示例代码:(根据您的自定义绘画进行更改)
private Timer timer;
...
// 500 Milli-seconds
timer = new javax.swing.Timer(500, new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
// change the coordinate
panel.repaint();
if (condition) {
timer.stop(); // you can stop the timer anytime
}
}
});
timer.setRepeats(true); // you can turn-off the repeatation
timer.start();
public static void main(String args[]) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
// Initialize the UI
}
});
}
class MyJPanel extends JPanel {
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
...
}
@Override
public Dimension getPreferredSize() {
return new Dimension(..., ...);
}
}