0

「アナウンサー」に JTextArea での操作の結果をアナウンスしてもらいたいという学習目的で、非常に単純な電卓を作成しました。このプログラムの目的は、大学で学んだことを活用することです。runnable を実装して 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();
}

前に述べたように、コードは正常に実行されています。唯一の問題は、アナウンサー クラスの run メソッドのこの部分が実行されないことです。

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

1 に答える 1

0

コメントで既に指摘したように、UI 状態を変更するコードは、イベント ディスパッチ スレッドで実行する必要があります。しかし、あなたはすでに EDT で更新を行っていると思います。この場合の問題は、新しい結果を求めて無限ループ ポーリングを実行し、JTextField. それは機能しますが、無限ループでイベント ディスパッチ スレッドをブロックしているため、影響を受ける UI 領域を再描画する機会がありません。

簡単な解決策は、計算スレッドがRunnables を使用してスケジュールを設定EventQueue.invokeLaterできるようにすることです。もう 1 つの方法は、Swingに定期的にTimer実行させることです。これにより、オブジェクトRunnableが同期され、現在の結果が要求されます。calc後者の場合、現在のコードのように、他のスレッドの呼び出しnotifyAllとペアになることが保証されていないため、更新を見逃す可能性があることに注意してください。wait

waitさらに、とのnotify呼び出しだけを同期するだけでは不十分です。結果を変更するコードと結果を取得するコード (呼び出し)もブロックcalc.getResult()内にある必要があります。synchronized

于 2013-10-08T09:59:18.207 に答える