我仍在学习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
不要直接在顶层容器(例如JFrameJApplet)上绘画,而要使用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(..., ...);
    }
}

10-07 22:33