3

Java で、Go と Pause の 2 つのボタンを備えた GUI があるとします。

Go を押すと、「Hello」が何度も出力されます。一時停止を押すと、「こんにちは」が画面に出力されなくなりました。

例: ユーザーが [Go] ボタンを押します。ユーザーが「一時停止」を押すまでの 1 分間、「Hello」が出力されます。

このアプローチをJavaで表現する適切な方法は何ですか? goButton ソース内のコメント付き疑似コードと同等ですか?

public void actionPerformed(ActionEvent e) {
    if(e.getSource() == goButton)
    {
        // while user has not pressed the pause button
        printHello();
    }
    else if(e.getSource() == pauseButton)
    {
        pause();
    }
}

ありがとう

4

7 に答える 7

3

これを機能させるには、合理的な方法で、Thread. これは、キャンセル/一時停止するまでバックグラウンドで実行されます。

これは非常に基本的な例です。通常、静的参照にアクセスするのではなく、タスクと GUI を適切なクラスにラップしますが、基本的な考え方が得られます。

public class TestHello {

    private static HelloTask task;

    public static void main(String[] args) {

        Thread thread = new Thread((task = new HelloTask()));
        thread.setDaemon(true);
        thread.start();

        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLayout(new GridBagLayout());
        frame.setSize(200, 200);
        frame.setLocationRelativeTo(null);

        JButton goButton = new JButton("Go");
        JButton stopButton = new JButton("Stop");

        goButton.setActionCommand("Go");
        stopButton.setActionCommand("Stop");

        ActionHandler handler = new ActionHandler();

        goButton.addActionListener(handler);
        stopButton.addActionListener(handler);

        frame.add(goButton);
        frame.add(stopButton);

        frame.setVisible(true);

    }

    public static class ActionHandler implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent e) {

            if (e.getActionCommand().equals("Go")) {
                task.start();
            } else if (e.getActionCommand().equals("Stop")) {
                task.pause();
            }

        }

    }

    public static class HelloTask implements Runnable {

        private static final Object WAIT_LOCK = new Object();
        private boolean dump = false;

        public void start() {
            synchronized (WAIT_LOCK) {
                dump = true;
                WAIT_LOCK.notify();
            }
        }

        public void pause() {
            synchronized (WAIT_LOCK) {
                dump = false;
                WAIT_LOCK.notify();
            }
        }

        @Override
        public void run() {
            while (true) {
                while (dump) {
                    System.out.println("Hello");
                }
                try {
                    synchronized (WAIT_LOCK) {
                        WAIT_LOCK.wait();
                    }
                } catch (Exception e) {
                }
            }
        }
    }
}

さらに読む人もいます:

注意事項

イベントディスパッチスレッド以外のスレッドから GUI を変更しようとしないでください。

于 2012-09-24T03:49:29.660 に答える
3

printHello()レスポンシブ UI を使用するには、通常、別のスレッドで実行する必要があります。次に、このスレッドで処理を行うときに、たとえばすべての print ステートメントの後、フラグをチェックしboolean isPaused;、それが true の場合は実行を停止します。pauseボタンをクリックすると、このフラグの値が に設定されますtrue

于 2012-09-24T03:42:05.600 に答える
0

ただのプリントアウト以上のことをしたいと思います。SwingWorkerを見てください。

これにより、AWTイベントスレッドで実行されるGUI関連のコードと、他のスレッドで長時間実行されるコードを非常に簡単に記述し、値をやり取りすることができます。これにより、発生する可能性のあるGUIロックアップの問題を防ぐことができます。

于 2012-09-24T04:44:11.367 に答える
0

基本的に、UIの応答性を維持するには、このようなタスクを他のスレッドで実行する必要があります。

このメカニズムをJavaで実装するにはさまざまな方法があります。メソッドを呼び出すときにスレッドが存在することを保証するフラグRunnalbeとフラグの単純なメカニズムを使用しましたvolatilecancelPrint()

public void actionPerformed(ActionEvent e) {
if(e.getSource() == goButton)
{
  //start the thread here 
}
else if(e.getSource() == pauseButton)
{
    //call cancel here
}
}

public class HelloPrinter implements Runnable {

volatile boolean cancel = false;

@Override
public void run() {

    while (!cancel) {
        printHello();
    }
}

public void cancelPrint() {
    cancel = true;
}
}
于 2012-09-24T03:57:51.927 に答える
0

ループを別のスレッドに実装する必要があります。そうしないと、GUI が無反応になり、ユーザーが [一時停止] ボタンをクリックできなくなる可能性があります。

このスレッド化されたアプローチでは、メッセージを出力するかどうかを示すフラグも必要です。フラグがもはや印刷しないように設定されている場合、印刷ループは単にスレッドの実行を停止できます。

于 2012-09-24T03:41:05.523 に答える
0

最も簡単ないくつかの方法でこれを行うことができます。

ブール値のフラグがkeepPrintingあり、[Go] ボタンを押したときに true に設定し、[一時停止] を押したときに false に設定します。次に、keepPrinting が false の場合に何も出力しない while ループを実行するスレッドがどこかにあります。

ここでのスレッド化は非常に重要です。そうしないと、ユーザーがボタンを押すと、プログラムが hello を出力し、それ以外は喜んで無視するため、GUI がフリーズすることになります。

疑似コード

//GUI
public ThreadedPrinter greeter;

void ButtonGoPushed(args){
    greeter.keepPrinting = true;
}

void ButtonPausePushed(args){
    greeter.keepPrinting = false;
}

//ThreadedPrinter

boolean keepPrinting
void run(){
    while(true){
        if(keepPrinting){
           print("Hello");
        }
        sleep(5); //Make sure that this thread yields if the system doesn't do it automatically
}

Java の同時実行性と C++ の比較についての良いニュースは、これが機能することです。Java では変数セットがアトミックであるため、ブール値がクレイジーで矛盾していることを心配する必要はありません。変数を設定する以上のことをしたい場合はsynchronized、変数を設定し、他の必要なことを行うメソッドを作成します。

于 2012-09-24T03:42:12.543 に答える
0

htisはどうですか:

 boolean flag=true;
    public void actionPerformed(ActionEvent e) {
        if(e.getSource() == goButton)
        {
            while(true)
       {
            printHello();
       }
        }
        else if(e.getSource() == pauseButton)
        {

            pause();
        }
    }
于 2012-09-24T03:42:40.977 に答える