Reputation: 1
In my Java code I have a while loop as shown below. I want when the end of file is reached or the pause button in the GUI is pressed, the while loop exits. How can I link the button listener from the GUI to the while loop?
Note: in the below code, the this.isPausePressed
is a flag inside the pause button listener which is true if the pause button is pressed and false otherwise
code:
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
i created three threads, each controls one of the GUI buttons with actionListener(play, pause and stop). and inside each respective buttonListener i set the according flags on/off and however the problem still exists.
please see the updated code posted below. the problem is when i click pause, the debugging statement , in onPause() method, always show that the getLastFileMarker() method reached its maximum. wich means, when the pause button is clicked and its flage isPausePressed
set to true, the while-loop
does not exit.
note:setLastFileMarker() is set inside the wile-loop in the ParseTimeStamp() method. all these methods are posted. kindly have alook at it
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 method:
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:
I deleted the three threads control the GUI buttons as suggested. and just implemented their listeners as shown below. the onPlay()
method, shown above in update_1, calls the parseTimeStamp()
which has the 'while-loop ', also posted above in update_1.
at run time, when pause
button is clicked the while-loop
does not exit.
Code
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();
}
}
}
});
Upvotes: 0
Views: 2827
Reputation: 7321
You only need to set the listener once, some place before the loop is started.
At the moment you click the button, the button's click listener will be fired asynchronously (i.e. from another thread as your loop code, a.k.a. the event dispatch thread
). So the loop will suddenly "see" the changed value for isPausePressed
and quit, just like that.
This implies that you should not do these kind of loops from inside the "event dispatch thread" as this would prevent loop and event to happen in parallel. See this document (and sub-documents) for more info on the "event dispatch thread" and concurrency in Swing in general.
update:
For an example, see below. Note that there's no need for any thread creation or other strange stuff. Swing automatically starts the notorious Event Dispatch Thread for you, and all event related code will automatically run inside that thread. This way, your main loop code will happily run in parallel with the actionListener's actionPerformed
method (as soon as you click the button). So the isPausePressed
flag will change seemingly during execution of your While loop. It's really that simple.
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
}
Upvotes: 2