簡體   English   中英

使用按鈕退出無限循環-Java

[英]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.Timerjava.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)幾乎肯定不是您想要的。 什么,做是分配truerun每次執行循環狀態的時間,從而確保循環會一直持續下去。

您可能想說的是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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM