【问题标题】:How to reference button listener in a while loop?如何在while循环中引用按钮监听器?
【发布时间】:2015-01-02 21:13:25
【问题描述】:

在我的 Java 代码中,我有一个 while 循环,如下所示。我希望当到达文件末尾或按下 GUI 中的暂停按钮时,while 循环退出。如何将按钮侦听器从 GUI 链接到 while 循环?

注意:在下面的代码中,this.isPausePressed 是暂停按钮监听器中的一个标志,如果按下暂停按钮则为 true,否则为 false

代码

while ( ((line = this.logFileBuffer.readLine()) != null) && (!this.isPausePressed) ) {
    statusarea.append(Log.d(TAG, "parseTimeStamp", "isPauseButtonPressed: " + this.isPausePressed) + "\n");
    String timeStamp = line.split(this.VALUE_SEPARATOR)[0];
    Thread timeStampThread = new Thread(new TimeStampTimerThread(++this.markCounter, timeStamp), "TimeStampThread_" + this.markCounter);
    timeStampThread.start();
    this.setLastFileMarker(this.markCounter);
}

Update_1

我创建了三个线程,每个线程控制一个带有 actionListener 的 GUI 按钮(播放、暂停和停止)。在每个相应的 buttonListener 中,我将相应的标志设置为开/关,但是问题仍然存在。

请参阅下面发布的更新代码。问题是当我单击暂停时,onPause() 方法中的调试语句总是显示 getLastFileMarker() 方法达到了最大值。这意味着,当单击暂停按钮并将其标志 isPausePressed 设置为 true 时,while-loop 不会退出。

注意:setLastFileMarker() 在 ParseTimeStamp() 方法的 wile-loop 内设置。所有这些方法都已发布。请看一下

createGUI {
this.playButtonThread = new Thread(this.playButtonRunnable, "playButtonThread");
    this.pauseButtonThread = new Thread(this.pauseButtonRunnable, "pauseButtonThread");
    this.stopButtonThread = new Thread(this.stopButtonRunnable, "stopButtonThread");

    this.playButtonThread.start();
    this.pauseButtonThread.start();
    this.stopButtonThread.start();
  }//CreateGui

 Runnable playButtonRunnable = new Runnable() {

    @Override
    public void run() {
        // TODO Auto-generated method stub
        playButtonListener();
    }
};

Runnable pauseButtonRunnable = new Runnable() {

    @Override
    public void run() {
        // TODO Auto-generated method stub
        pauseButtonListener();
    }
};

Runnable stopButtonRunnable = new Runnable() {

    @Override
    public void run() {
        // TODO Auto-generated method stub
        stopButtonListener();
    }
};

protected void playButtonListener() {
    // TODO Auto-generated method stub
    Bplay.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent arg0) {
            // TODO Auto-generated method stub
            if (isPausePressed) {
                isPlayPressed = true;
                isPausePressed = false;
                continueReading();
            }else if (!isPlayPressed) {
                isPlayPressed = true;
                try {
                    onPlay();
                } catch (IOException
                        | InterruptedException | MqttException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    });
}

protected void pauseButtonListener() {
    // TODO Auto-generated method stub
    Bpause.addActionListener(new ActionListener() {

        @Override
        public void actionPerformed(ActionEvent arg0) {
            // TODO Auto-generated method stub
            if (isPlayPressed) {
                isPlayPressed = false;
                isPausePressed = true;
                try {
                    onPause();
                } catch (IOException | MqttException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    });
}

protected void stopButtonListener() {
    // TODO Auto-generated method stub
    Bstop.addActionListener(new ActionListener() {

        @Override
        public void actionPerformed(ActionEvent arg0) {
            // TODO Auto-generated method stub
            if (isPlayPressed) {
                isStopPressed = true;
                try {
                    onStop();
                } catch (MqttException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    });
}

    protected void continueReading() {
    // TODO Auto-generated method stub

}

  private void onPause() throws IOException, MqttException {
    // TODO Auto-generated method stub
    statusarea.append(Log.w(TAG, "onPause", "onPause() is called") + "\n");

    if (!this.logFileBuffer.markSupported()) {
        statusarea.append(Log.w(TAG, "onPause", "stream does not support .mark() and .reset()   
    operations.") + "\n");
    }else {
        this.logFileBuffer.mark(this.getLastFileMarker());
        statusarea.append(Log.i(TAG, "onPause", "last mark set in line#: " + 
  this.getLastFileMarker()) + "\n");
        this.timer.cancel();
        //this.getClient().disconnect();
    }
    simulationarea.append(Log.w(TAG, "onPause", "PAUSE") + "\n");
}

ParseTimeStamp 方法

 while ( ((line = this.logFileBuffer.readLine()) != null) && (!isPausePressed) ) {
                statusarea.append(Log.d(TAG, "parseTimeStamp", "isPauseButtonPressed: " +   
 isPausePressed) + "\n");
                String timeStamp = line.split(this.VALUE_SEPARATOR)[0];
                Thread timeStampThread = new Thread(new TimeStampTimerThread(++this.markCounter,   
 timeStamp), "TimeStampThread_" + this.markCounter);
                timeStampThread.start();
                this.setLastFileMarker(this.markCounter);
            }

Update_2

我按照建议删除了控制 GUI 按钮的三个线程。并且刚刚实现了他们的监听器,如下所示。 onPlay() 方法,如上面 update_1 所示,调用具有“while-loop”的parseTimeStamp(),也发布在上面的 update_1 中。 在运行时,当点击pause 按钮时,while-loop 不会退出。

代码

Bplay.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent arg0) {
            // TODO Auto-generated method stub
            if (isPausePressed) {
                isPlayPressed = true;
                isPausePressed = false;
                continueReading();
            }else if (!isPlayPressed) {
                isPlayPressed = true;
                try {
                    onPlay();
                } catch (IOException
                        | InterruptedException | MqttException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    });

    Bpause.addActionListener(new ActionListener() {

        @Override
        public void actionPerformed(ActionEvent arg0) {
            // TODO Auto-generated method stub
            if (isPlayPressed) {
                isPlayPressed = false;
                isPausePressed = true;
                try {
                    onPause();
                } catch (IOException | MqttException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    });

    Bstop.addActionListener(new ActionListener() {

        @Override
        public void actionPerformed(ActionEvent arg0) {
            // TODO Auto-generated method stub
            if (isPlayPressed) {
                isStopPressed = true;
                try {
                    onStop();
                } catch (MqttException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    });

【问题讨论】:

    标签: java swing while-loop actionlistener onclicklistener


    【解决方案1】:

    你只需要设置一次监听器,在循环开始之前的某个地方。

    在您单击按钮的那一刻,按钮的单击侦听器将被异步触发(即从另一个线程作为您的循环代码,又名event dispatch thread)。所以循环会突然“看到”isPausePressed 的更改值并退出,就像那样。

    这意味着您不应该从“事件调度线程”内部执行此类循环,因为这会阻止循环和事件并行发生。请参阅this 文档(和子文档)以获取有关 Swing 中“事件调度线程”和并发性的更多信息。

    更新:

    例如,见下文。请注意,不需要任何线程创建或其他奇怪的东西。 Swing 会自动为您启动臭名昭著的 Event Dispatch Thread,所有与事件相关的代码将自动在该线程内运行。这样,您的主循环代码将愉快地与 actionListener 的 actionPerformed 方法并行运行(只要您单击按钮)。因此,isPausePressed 标志会在您的 While 循环执行期间看似发生变化。就是这么简单。

        private boolean isPausePressed = false;
    
        JButton b = new JButton("Pause!");
        b.addActionListener(new ActionListener()
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                isPausePressed = true;
            }
        });
    
        // ....
    
        while (!isPausePressed)
        {
            // do some work
        }
    

    【讨论】:

    • 感谢您的回答,但我的班级实现了 ActionListener。我可以将 actionPerformed() 放在另一个线程中
    • 这不是问题。线程运行的地方是 Swing 运行时的东西,您的代码不需要担心这一点。因此,您只需致电 button.addActionListener(myClass); 即可。
    • 请查看更新后的代码。问题是当我点击暂停时,onPause() 方法中的调试语句总是显示 getLastFileMarker() 方法达到了最大值。注意:setLastFileMarker() 在 ParseTimeStamp() 方法的 wile-loop 内设置。所有这些方法都已发布。请看一下
    • 请参阅 update_1 部分中添加的 sme 说明
    • @LetAmrit 比这容易得多,请参阅我的更新答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-05-05
    • 1970-01-01
    • 1970-01-01
    • 2013-12-24
    • 1970-01-01
    • 1970-01-01
    • 2021-02-15
    相关资源
    最近更新 更多