0

我创建了一个非常简单的计算器用于学习目的,我希望“播音员”在 JTextArea 中宣布操作结果。该计划的目的是利用我们在大学中学到的东西。我有一个自己的公告类,它实现了可运行并同步我的 calc 对象,它应该附加结果但没有任何反应。

该程序运行良好,因此我已将代码剥离到相关部分:

播音员类中的 run 方法:

    public void run()
{
    calc.getAnnouncementJTF().append("Announcer thread has been initialized...\n");
    calc.getAnnouncementJTF().append("Hi. My name is " + this.getName() + " and my purpose is to " +
            "announce the results of your operations as soon as they are ready. \r\n");
    while(true){
        synchronized(calc){
            try
            {
                calc.wait();
            }
            catch(InterruptedException e)
            {
                e.printStackTrace();
            }
        }
        calc.getAnnouncementJTF().append(String.valueOf(calc.getResult() + "\n"));
    }

}

这是执行计算并通知所有等待对象的条件:

            else if(e.getSource() == sumButton && Numbers.size() != 0)
        {
            if(!actualNumber.getText().equals("")){
                Numbers.add(new Double(actualNumber.getText()));
                addToResults = previousNumbers.getText() + " " + actualNumber.getText();
            } else {
                addToResults = previousNumbers.getText().substring(0, previousNumbers.getText().length() - 2);
            }
            currentResult = performCalculation(Numbers, Operators);
            previousCalcs.append(addToResults + " = " + String.valueOf(currentResult) + "\r\n");
            // Clear both lists and add the result to a cleared
            // list for further calculation on it.
            Operators.clear();
            Numbers.clear();
            actualNumber.setText(String.valueOf(currentResult));
            previousNumbers.setText("");
            resultExist = true;
            synchronized(this){
                notifyAll();
            }
        }

主要方法

public static void main(String[] args){
    Announcer announcer = new Announcer();
    Calculator calc = new Calculator(announcer);

    calc.setTitle("Calculator");
    calc.setSize(360, 900);
    calc.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    calc.setLocationRelativeTo(null);
    calc.setVisible(true);
    calc.setResizable(false);

    announcer.setCalculator(calc); announcer.setName("Sam");
    announcer.setAge(28); announcer.setLength(182.5);

    Thread announcerThread = new Thread(announcer);
    announcerThread.start();
}

正如我之前提到的,代码运行良好。我唯一的问题是播音员类中的这部分运行方法没有运行:

calc.getAnnouncementJTF().append(String.valueOf(calc.getResult() + "\n"));
4

1 回答 1

0

As already pointed out in the comments, the code modifying the UI state must be executed in the event dispatch thread. But I guess, you are already doing the update in the EDT. In this case the problem is that you are running an infinite loop polling for new results and appending them to the JTextField. That works, but you are blocking the event dispatch thread with your infinite loop so it has no chance to ever repaint the affected UI area.

A simple solution is to let the calculation thread schedule Runnables using EventQueue.invokeLater which will just perform a single update and return. Another way is to let a Swing Timer execute a Runnable periodically which will synchronize on the calc object and ask for the current result. Note that in the latter case, like in the code you have now, you might miss updates as notifyAll is not guaranteed to be paired with wait calls of other threads.

Further, it is not enough to synchronize just for the wait and notify calls. The code which modifies the result and the code which retrieves the result (the calc.getResult() invocation) must be inside the synchronized block as well.

于 2013-10-08T09:59:18.207 回答