[英]Java - Varargs|While(true)|Scanner - exiting infinite while loop
[英]Exiting an infinite loop with a button - Java
我一直在尋找解決方案,但找不到任何合適的解決方案。 這是我的問題:我剛剛開始學習Java中的Swing,並且我有一個應用程序會在最短和最長時間之間隨機單擊。 用戶輸入最短和最長時間,然后單擊啟動此代碼的按鈕:
class CalcButtonListener implements ActionListener{
@Override
public void actionPerformed(ActionEvent arg0) {
//get data from text fields and store as integers in milliseconds.
//create a robot and random number between min and max
while(run == true){
robot.mousePress(InputEvent.BUTTON1_MASK);
robot.mouseRelease(InputEvent.BUTTON1_MASK);
robot.delay(num.nextInt(max-min+1)+min);
}
}
}
}
我刪除了一些代碼,因為它與問題無關。 問題是我還有另一個按鈕將變量run設置為false,但是一旦單擊第一個按鈕,就無法再單擊第二個按鈕或頂部的退出按鈕。
我確定我的錯誤是一個非常基本的錯誤,但我看不到它。 感謝您的答復,這有助於我更好地理解該主題。
編輯:將while循環從“ while(run = true)”更改為“ while(run == true)”。
while(run == true){
“ =”將run設置為true“ ==”比較run的值為true
你也可以用
while(run){
看看SwingWorker 。 然后做while(run)
每個事件將由稱為事件調度線程(EDT)的單個線程處理。 如果您在一個事件中進行了無限調用,則EDT無法處理事件隊列中的下一個事件。
更新此答案已更新,因為@uckelman指出,在條件run = true
的情況下,停止按鈕不會中斷while循環,因為需要在循環內將其更改為run = false。 然后,我發布了一個解決此邏輯問題的簡單替代方法,以使用計時器重復計划任務。 有關詳細信息,請檢查此 SO問題。
關於按鈕的事件:如果有兩個按鈕,一個開始循環,一個結束循環,只需嘗試以下代碼:
class CalcButtonListener implements ActionListener{
private boolean run = true;
private java.util.Timer timer = new java.util.Timer();
private JButton start_loop, end_loop;
//here the buttons initialization
@Override
public void actionPerformed(ActionEvent ae){
if(ae.getSource()==start_loop){
java.util.TimerTask task = new java.util.TimerTask() {
@Override
public void run() {
doStuff();
}
};
timer.schedule(task, java.util.Calendar.getInstance().getTime(), 500);//here the '500' means the time, 500 ms,
the task is repeatedly executed.
}
if(ae.getSource()==end_loop){
timer.cancel();//cancel the tasks scheduled
System.out.println("Task cancelled!");
}
}
private void doStuff(){
robot.mousePress(InputEvent.BUTTON1_MASK);
robot.mouseRelease(InputEvent.BUTTON1_MASK);
robot.delay(num.nextInt(max-min+1)+min);
}
}
現在,任務doStuff()
計划每500毫秒執行一次。
有關java.util.Timer和java.util.TimerTask的其他信息。
關於您的問題:
問題是我還有另一個按鈕將變量run設置為false,但是一旦單擊第一個按鈕,就無法再單擊第二個按鈕或頂部的退出按鈕。
Swing的單線程規則說Swing組件只能由一個線程訪問。 該規則適用於獲取和設置,並且單個線程稱為事件調度線程。
單線程規則非常適合UI組件,因為它們無論如何都傾向於以單線程方式使用,並且大多數操作都是由用戶啟動的。 此外,構建線程安全組件既困難又乏味:如果可以避免的話,最好不要做。 但是,盡管具有所有好處,但是單線程規則具有深遠的意義。
除非所有組件的事件都是在事件調度線程上發送和接收的,否則Swing組件通常將不符合單線程規則。 例如,屬性更改事件應在事件調度線程上發送,而模型更改事件應在事件調度線程上接收。
對於諸如JTable和JTree之類的基於模型的組件,單線程規則意味着該模型本身只能由事件調度線程訪問。 因此,模型的方法必須快速執行,並且絕不能阻塞,否則整個用戶界面將無響應。
然后,如果您使用單個線程開發GUI,則在執行按鈕事件時,GUI將凍結,等待相關按鈕事件的完整執行。 就您而言,在無限循環中,您的GUI始終會凍結。
我的建議是為您的GUI使用SwingWorker ,或擴展Thread類(然后在單獨的線程中開發GUI),或實現Runnable接口。 另一種選擇是使用javax.swing.Timer
包中的Timer 。
您可以閱讀有關SwingWorker的SO的舊問題: 如何在Java中使用SwingWorker?
SwingWorker的教程: http : //docs.oracle.com/javase/tutorial/uiswing/concurrency/worker.html
創建線程的教程: http : //docs.oracle.com/javase/tutorial/essential/concurrency/
有關Timer
的問題: 使用用戶指定的計時器更新gui中的JPanel和屬性?
有關計時器的教程: http : //docs.oracle.com/javase/tutorial/uiswing/misc/timer.html
您應該閱讀有關Swing計時器的信息:
http://java.sun.com/products/jfc/tsc/articles/timer/
也就是說,使程序受事件驅動。 Swing應用程序已經一直在其中運行一個循環,稱為事件循環。 如果再啟動一個也無濟於事。
請注意while(something)
類的方法,這可能會使程序陷入僵局,我建議您實現事件偵聽器以避免此問題...
run=true;
while(run == true){
...
while (run = true)
幾乎肯定不是您想要的。 什么,做是分配true
到run
每次執行循環狀態的時間,從而確保循環會一直持續下去。
您可能想說的是while (run == true)
,它僅測試run
是否為true。 更好的是只說while (run)
,它做同樣的事情。
如果您要從另一個線程run
,請注意,您應該使run
成為類的volatile
成員。 如果您不打算run
其他地方run
,那么您將遇到邏輯錯誤,因為沒有辦法打破循環。 在這種情況下,您需要在循環內添加一個測試,並在希望循環停止時將run
設置為false。 (或者,您可以使用while (true)
並在循環內使用break
。)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.