【问题标题】:Java GUI is not modified/updated when called from thread从线程调用时,Java GUI 不会被修改/更新
【发布时间】:2019-05-03 16:24:37
【问题描述】:

我有一个项目,我必须使用 Java Swing 创建一个roulette wheel。当轮子“旋转”时,轮子上的数字是randomly highlighted,然后落在最终数字上。

我必须创建一个提供上述布局中的 JLabels 的 GUI 类。在这个 GUI 类中也需要旋转轮子的方法,我们必须明确地使用线程和 Runnable 接口来处理。

教授为我提供了一个驱动程序类,它在添加 GUI 类 (RouletteWheel) 之前创建了一个 JFrame 和按钮:

public WheelTest()
{
    theWindow = new JFrame("WheelTest Program");
    theWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    ActionListener listen = new ButtonListener();

    setButton = new JButton("Set Wheel");  
    setButton.setFont(myFont);
    setButton.addActionListener(listen);

    ........

    theWheel = new RouletteWheel();   //GUI class
    theWindow.add(theWheel, BorderLayout.CENTER);
}

这是我的 GUI 类的样子:

final RouletteSquare [] squareArray = new RouletteSquare[37];  //Array of JLabels
private Boolean spun;

public RouletteWheel(){
    createGUI();
}

private void createGUI(){  //Creates a RouletteSquare object for each place in the array
    this.setLayout(new GridLayout(6, 6));
    for(int i = 0; i <= 36; i++){
        squareArray[i] = new RouletteSquare(i);
        this.add(squareArray[i]);
        squareArray[i].choose();
    }
}

public void spin(){
    Runnable wheel = new RouletteWheel();
    new Thread(wheel).start();
}

public void run(){
    Random rand = new Random();
    long startTime = System.nanoTime();
    long endTime = System.nanoTime();
    long elapsedTime = endTime - startTime;
    long nanoTime = 10000;
    while(elapsedTime <= nanoTime)
    {
        i = rand.nextInt(37);
        System.out.println("i = " + i);
        squareArray[i].choose();  //Highlights square CYAN color
        try {Thread.sleep(500);}  //Adds a delay between selections
        catch (InterruptedException e){}
        squareArray[i].unChoose();  //Un-highlights square
        endTime = System.nanoTime();
        elapsedTime = endTime - startTime;
    }
    i = rand.nextInt(37);
    squareArray[i].choose();
}

作为记录,这个 GUI 类利用了之前项目中的另一个类 RouletteSquare,它只是创建了一个单独的 JLabel 并提供了突出显示该 JLabel 的方法。我使用一组 RouletteSquares 来创建 RouletteWheel(这也是该项目所必需的)。 RouletteSquare 类如下所示:

private boolean cvar;
private int value;
public RouletteSquare(int val)
{
    value = val;
    this.setLayout(new GridLayout(1, 1));

    number2 = new JLabel();
    number2.setText(String.valueOf(value));
    number2.setFont(new Font("Serif", Font.BOLD, 50));
    number2.setForeground(getColorType(getColor()));
    number2.setHorizontalAlignment(CENTER);
    number2.setOpaque(true);
    number2.setBackground(Color.WHITE);

    this.setPreferredSize(new Dimension(75, 75));
    this.add(number2);
}

public boolean isChosen() {
    return cVar;
}

public void unChoose() {
    cVar = false;
    number2.setBackground(Color.WHITE);
}

public void choose() {
    cVar = true;
    number2.setBackground(Color.CYAN);
}

GUI 已正确创建和初始化,我可以在线程方法调用之外对其进行更改。

我遇到的问题是,据我通过打印语句可以看出,我的代码可以正确执行,但是通过线程调用时 GUI 不会更新。我曾尝试使用 SwingUtilities.InvokeLater(Runnable),但这未能成功解决我的问题。我也不能使用 javax.swing.timer,因为我必须使用线程。

我的想法已经不多了,并且开始变得非常沮丧。任何帮助将不胜感激,谢谢!

【问题讨论】:

    标签: java multithreading swing user-interface


    【解决方案1】:

    您创建自己的 RouletteWheel 类:

    theWheel = new RouletteWheel();  
    

    然后在您的 spin() 方法中创建另一个 RouletteWheel 实例:

    public void spin(){
        Runnable wheel = new RouletteWheel();
        new Thread(wheel).start();
    }
    

    您只需要 RouletteWheel 类的单个实例。

    我猜代码应该是:

    //new Thread(wheel).start();
    new Thread(this).start();
    

    【讨论】:

    • 天哪,这行得通。非常感谢,非常感谢。我已经盯着这个看了大约 5 个小时,但还是无法破解它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-12
    • 1970-01-01
    • 2011-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多