#java #swing #timer
#java #swing #таймер
Вопрос:
У меня есть приложение, которому необходимо сканировать устройства Bluetooth каждые 10 минут в течение продолжительности, установленной пользователем.
У меня есть два javax.swing.Таймер (не java.util.Таймер) — один управляет вызовом метода сканирования каждые 10 минут, другой останавливает первый таймер (следовательно, останавливает сканирование) после достижения предела продолжительности.
durationTimer создается и запускается в ActionListener.
Моя проблема в том, что, поскольку durationTimer создается в ActionListener, я не могу остановить таймер из другого ActionListener, поскольку программа не может «видеть» имя переменной «durationTimer».
Сокращенный код показан ниже….
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, timerDurationActionEvent);
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();
};
}
Заранее благодарю вас за любую помощь
Комментарии:
1. Возможно ли урезать код, который вы нам предоставляете? Сложно проанализировать все это и найти соответствующие биты.
2. Кроме того, форматирование кода является своего рода сбоем. Если вы можете потратить время на то, чтобы красиво отформатировать код в своих вопросах, это всегда очень ценится.
3. ах, извините, я сильно урезал это, поскольку думал, что все это необходимо, но, полагаю, я мог бы сократить это немного больше. Спасибо за отзыв
Ответ №1:
Вы можете объявить durationTimer на уровне класса и по-прежнему создавать его в ActionListener. Таким образом, это должно быть видно во всем классе. Просто убедитесь, что оно не равно null, прежде чем пытаться вызвать stop() для него.
Другой вариант — заставить его остановить себя:
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();
}
};
И другой (и, возможно, лучший) вариант — просто сделать его неповторяющимся:
Timer timerDuration = new Timer(durationMilliSec, timerDurationActionEvent);
timerDuration.setRepeats(false);
timerDuration.start();
Этот последний вариант — правильный.
Ответ №2:
Поскольку вы запускаете сканирование синего зуба в потоке отправки событий, ваш второй таймер не сработает до завершения сканирования синего зуба.
Вам нужно запустить новый поток для сканирования синего зуба.
Я предлагаю вам использовать SwingWorker.
Ответ №3:
Я не знаю, когда btnScanAction
запускается (вероятно, часто, поскольку это ActionListener
), но при каждом вызове создается новый timerDuration
. Вероятно, в итоге у вас будет несколько таймеров продолжительности, что (я думаю …) не то, что вы хотите.