Java Scoping with ActionListeners
I have an application that needs to scan for bluetooth devices every 10 minutes for a duration set by the user.
I have two javax.swing.Timer (not java.util.Timer) - one controls invoking the Scanning method every 10 minutes, the other is stopping the first timer (therfore stopping the scanning) once the duration limit has been hit.
The durationTimer is created and started within an actionListener.
My problem is that because durationTimer is created within an ActionListener, i cannot stop the timer from another ActionListener, as the program cannot "see" the variable name "durationTimer".
The reduced code is shown below....
public class mainGui extends JFrame
{
public mainGui()
{
final ActionListener timerActionEvent = new ActionListener(){
public void actionPerformed(ActionEvent evt){
//start a task here
Timer myTimer2 = (Timer) evt.getSource();
//Invoke BluetoothScan method
BluetoothScan(myTimer2);
}
};
final Timer timerDuration;
final Timer myTimer = new Timer(5000, timerActionEvent);
final ActionListener timerDurationActionEvent = new ActionListener(){
public void actionPerformed(ActionEvent evt){
//Stops myTimer, so that Bluetooth Stops scanning every 10mins.
myTimer.stop();
}
};
ActionListener btnScanAction = new ActionListener(){
//Action listener for reading data from db
public void actionPerformed(ActionEvent e){
int roomID = 0;
int lecturer = 0;
int unit;
int roomIDIndex;
int lectIDIndex;
int yearIDIndex;
int unitIDIndex;
String[] roomArray;
String[] lecturerArray;
String[] unitArray = null;
int durationIndex;
String DURATION;
int durationInt;
//System.out.println(unitArray.length);
durationIndex = durCB.getSelectedIndex();
DURATION = itemDuration[durationIndex];
durationInt = Integer.parseInt(DURATION);
//User Selected Duration converted to Milliseconds
int durationMilliSec = (int)(durationInt*60000);
ArrayList<String[]> unitYear = null;
//Store the index ID of the JComboBox Selections
roomIDIndex = roomCB.getSelectedIndex();
lectIDIndex = lectCB.getSelectedIndex();
unitIDIndex = unitCB.getSelectedIndex();
yearIDIndex = yearCB.getSelectedIndex();
switch(yearIDIndex)
{
case 1: unitYear = Units1; break;
case 2: unitYear = Units2; break;
case 3: unitYear = Units3; break;
case 4: unitYear = UnitsMasters; break;
}
//Get the Array contents at index location
roomArray = rooms.get(roomIDIndex);
lecturerArray = Lecturers.get(lectIDIndex);
unitArray = unitYear.get(unitIDIndex);
if(unitArray==null){
System.out.println("Please select a unit");
System.exit(0);
}
roomID = Integer.parseInt(roomArray[0]);
lecturer = Integer.parseInt(lecturerArray[0]);
unit = Integer.parseInt(unitArray[0]);
populateComboBoxes pcb = new populateComboBoxes();
pcb.LabSessionInfo(roomID, lecturer, unit);
myTimer.start();
Timer timerDuration = new Timer(durationMilliSec, timerDurationAct开发者_运维技巧ionEvent);
timerDuration.start();
}
};
public void BluetoothScan(Timer myTimer) {
BluetoothDeviceDiscovery scan = new BluetoothDeviceDiscovery();
try {
myTimer.stop();
scan.main();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
myTimer.start();
};
}
Thankyou in advance for any help
You can declare the durationTimer at the class level and still construct it in the ActionListener. This way it should be visible throughout the class. Just be sure to check that it's not null before trying to call stop() on it.
Another option is to have it stop itself:
final ActionListener timerDurationActionEvent = new ActionListener(){
public void actionPerformed(ActionEvent evt){
//Stops myTimer, so that Bluetooth Stops scanning every 10mins.
myTimer.stop();
((Timer)evt.getSource()).stop();
}
};
And another (and perhaps the best) option is to simply make it non-repeating:
Timer timerDuration = new Timer(durationMilliSec, timerDurationActionEvent);
timerDuration.setRepeats(false);
timerDuration.start();
This last one is the way to go.
Since you start the blue tooth scan on the Event Dispatch thread, you're second Timer will not fire until the blue tooth scan is complete.
You need to start a new thread for the blue tooth scan.
I suggest you use a SwingWorker.
I don't know when btnScanAction
is triggered (probably often since it is an ActionListener
), but it creates a new
timerDuration
at each call. You'll probably end up with multiple duration timers, which (I guess...) is not what you want.
精彩评论