GUI 停止工作,即使它在自己的线程中并且没有调用 Thread.sleep()



我有问题。当我按下链接到使用其他类别的方法

的JButton时,我的GUI停止工作
Thread.sleep();

我不知道为什么考虑到我的GUI在其自己的线程中。请查看我的代码,告诉我为什么会发生!

这是我的GUI类:

package com.robot;
import java.awt.AWTException;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.ScrollPaneConstants;
public class GUI extends JFrame implements Runnable {
//defines the panels
JPanel mainPanel;
JPanel labelPanel;
JPanel buttonPanel1;
JPanel buttonPanel2;
JPanel consolePanel;
//defines the label
JLabel title;
//defines the buttons
JButton runDemo;
JButton runLive;
JButton scan;
JButton findPatterns;
JButton cleanFolder;
JButton configureSettings;
//defines the console
JTextArea console;
//defines the line break
String newline = System.getProperty("line.separator");
//start of the constructor method for GUI
public GUI() {
}
public void run() {
    //makes the program unable to be resized
            this.setResizable(false);
            //allows the user to close the program with the x button
            this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            //sets the title of the program
            this.setTitle("ROBOT Alpha Alfred Version 3.0");
            //creates panels to hold the elements of the GUI
            mainPanel = new JPanel();
            labelPanel = new JPanel();
            buttonPanel1 = new JPanel();
            buttonPanel2 = new JPanel();
            consolePanel = new JPanel();
            //creates label
            title = new JLabel("Robotically Operated Binary Options Trader");
            //creates buttons
            runDemo = new JButton("Run Demo");
            runLive = new JButton("Run Live");
            scan = new JButton("Scan Market");
            findPatterns = new JButton("Find Patterns");
            cleanFolder = new JButton("Clean Up Folder");
            configureSettings = new JButton("Configure Settings");
            //defines button listener objects
            ButtonListener buttonListener = new ButtonListener();
            //adds buttons to button listeners
            runDemo.addActionListener(buttonListener);    
            runLive.addActionListener(buttonListener);
            scan.addActionListener(buttonListener);
            findPatterns.addActionListener(buttonListener);
            cleanFolder.addActionListener(buttonListener);
            configureSettings.addActionListener(buttonListener);
            //creates the console
            console = new JTextArea(6, 40);
            //sets the default text of the console
            console.setText("----------------------- ROBOT Console -----------------------" + newline);
            //makes the console unable to be edited
            console.setEditable(false);
            //sets the line wrapping of the console
            console.setLineWrap(true);
            console.setWrapStyleWord(true);
            //creates scroll bars
            JScrollPane scrollBar = new JScrollPane(console);
            scrollBar.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
            scrollBar.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
            //adds label to the label panel
            labelPanel.add(title);
            //adds buttons to the button panel
            buttonPanel1.add(runDemo);
            buttonPanel1.add(runLive);
            buttonPanel2.add(scan);
            buttonPanel2.add(findPatterns);
            buttonPanel2.add(cleanFolder);
            buttonPanel2.add(configureSettings);
            //adds the console to the console panel
            consolePanel.add(scrollBar);
            //adds panels to the main panel
            mainPanel.add(labelPanel);
            mainPanel.add(buttonPanel1);
            mainPanel.add(buttonPanel2);
            mainPanel.add(consolePanel);
            //adds the main panel to the frame
            this.add(mainPanel);
            //packs the GUI
            this.pack();
            //sizes the GUI
            this.setSize(600, 400);
            //centers the GUI
            this.setLocationRelativeTo(null);
            //sets the GUI to be visible
            this.setVisible(true);
}
public void add(String string) {
    console.append(string + newline);
}
//implement listeners
private class ButtonListener implements ActionListener {
    public void actionPerformed(ActionEvent e) {
        if(e.getSource() == runDemo) {

        } else if(e.getSource() == runLive) {

        } else if(e.getSource() == scan) {
            try {
                ScanMarket.scanMarket();
            } catch (IOException e1) {
                e1.printStackTrace();
            } catch (InterruptedException e1) {
                e1.printStackTrace();
            } catch (AWTException e1) {
                e1.printStackTrace();
            }
        } else if(e.getSource() == findPatterns) {
            try {
                FindPattern.findPattern("Images");
            } catch (AWTException e1) {
                e1.printStackTrace();
            } catch (IOException e1) {
                e1.printStackTrace();
            } catch (InterruptedException e1) {
                e1.printStackTrace();
            }
        } else if(e.getSource() == cleanFolder) {
            AddNeededFiles.addNeededFiles();
        } else if(e.getSource() == configureSettings) {

        }
    }
}
}

这是调用GUI类的地方:

//main method start
public static void main(String[] args) throws InterruptedException, IOException, AWTException {
    //opens up the GUI
    (new Thread(new GUI())).start();
    //possible methods
    //ScanMarket.scanMarket(); //scans market for data
    //FindPattern("Images"); //finds pattern among images in image folder labeled Images
}//end of main method

这是链接到使用thread.sleep();

的类方法
package com.robot;
import java.awt.AWTException;
import java.awt.Robot;
import java.io.IOException;
public class ScanMarket extends Main{
//define objects
RenameFile renameFile = new RenameFile();
IsGraphFull isGraphFull = new IsGraphFull();
NumberOfImagesInFolder numberOfImagesInFolder = new NumberOfImagesInFolder();
TakePicColumn takePicColumn = new TakePicColumn();
HasGraphCrashed hasGraphCrashed = new HasGraphCrashed();
RefreshPage refreshPage = new RefreshPage();
/*scanMarket is used to basically "scan" the market and will record captured images 
of all of the columns for many hours. This method will save the images in order, 
has crash protection and will run continuously for hours*/
public static void scanMarket() throws IOException, InterruptedException, AWTException {
    //tells number of images to scan
    float wantedImages = 700;
    //counts the number of images in the folder
    NumberOfImagesInFolder.numberOfImagesInFolder("Images");
    //creates the Number that is assigned to all images
    float nameCounter = NumberOfImagesInFolder.numberOfImagesInFolder;
    //saves the columns until we have 1000 images of different columns
    while (NumberOfImagesInFolder.numberOfImagesInFolder <= wantedImages) {
        //first check if the graph has crashed
        HasGraphCrashed.hasGraphCrashed();
        //if the graph has crashed then refresh the page
        if(HasGraphCrashed.hasGraphCrashed == true){
            //refresh the page
            RefreshPage.refreshPage();
            //alert the system it updated the page and the page is no longer down
            HasGraphCrashed.hasGraphCrashed=false;
        }
        //update the amount of images in the folder again
        NumberOfImagesInFolder.numberOfImagesInFolder("Images");
        //check if the graph is full 
        IsGraphFull.isGraphFull();
        //if the graph is full
        if (match == true) {
            //takes a picture of every single column
            TakePicColumn.takePicColumn();
            //sets up the 2 image locations for the first column
                //temporary first column image
                String file1 = imageLocation + "1" + end;
                //permanent first column image
                String file2 = imageLocation + "real" + nameCounter + end;
                //increases the value of the number assigned to each image so that the next image has a different value than the first image
                nameCounter++;
                //rename the temporary file to the permanent file name
                RenameFile.renameFile(file1, file2);
                //sets up the 2 image locations for the second column
                    //temporary second column image
                    file1 = imageLocation + "2" + end;
                    //permanent second column image
                    file2 = imageLocation + "real" + nameCounter + end;
                //increases the value of the number assigned to each image so that the next image has a different value than the second image
                nameCounter++;
                //rename the temporary file to the permanent file name
                RenameFile.renameFile(file1, file2);
                //sets up the 2 image locations for the third column
                    //temporary third column image
                    file1 = imageLocation + "3" + end;
                    //permanent third column image
                    file2 = imageLocation + "real" + nameCounter + end;
                //increases the value of the number assigned to each image so that the next image has a different value than the third image
                nameCounter++;
                //rename the temporary file to the permanent file name
                RenameFile.renameFile(file1, file2);
                //sets up the 2 image locations for the fourth column
                    //temporary fourth column image
                    file1 = imageLocation + "4" + end;
                    //permanent fourth column image
                    file2 = imageLocation + "real" + nameCounter + end;
                //increases the value of the number assigned to each image so that the next image has a different value than the fourth image
                nameCounter++;
                //rename the temporary file to the permanent file name
                RenameFile.renameFile(file1, file2);
                //sets up the 2 image locations for the fifth column
                    //temporary fifth column image
                    file1 = imageLocation + "5" + end;
                    //permanent fifth column image
                    file2 = imageLocation + "real" + nameCounter + end;
                    //increases the value of the number assigned to each image so that the next image has a different value than the fifth image
                    nameCounter++;
                //rename the temporary file to the permanent file name
                RenameFile.renameFile(file1, file2);
                //waits for graph to shift
                Thread.sleep(90000);
            }
            //create a temporary robot
            Robot test = new Robot();
            //move the mouse to the top left side of the screen to alert the person 
            //you can move the mouse for 90 seconds
            test.mouseMove(0,0);
            //give some time to let the user check what they need to check
            Thread.sleep(90000);
        }//end of if the graph is full statement
    }//end of capturing images
}

我不知道我是否需要给该课程自己的线程,然后在我通过构造函数调用该方法或什么时在GUI类中调用该线程!请帮助我!

您需要将操作关闭到秋千UI线程的其他线程。

Swing有一个特殊的课程可以帮助您 - 摇摆人

按下按钮时,将在事件调度线程(EDT)上调用Action Perverfermed方法,该方法负责处理事件并绘制GUI。由于您调用从ActionPerformed()执行thread.sleep()的方法,因此您仍在EDT上,因此阻止EDT重新绘制GUI。

您需要使用一个单独的线程来运行ScanMarket()方法。

任何摇摆/GUI读/写操作都应在事件调度线程上运行。你应该使用swingutilities.invokelater()确保在秋千线上运行GUI突变/读取。

您要在后台运行的任何操作都应在单独的线程上运行。

您可能需要使用Swingworker类来运行背景任务。(http://docs.oracle.com/javase/tutorial/uiswing/concurrency/worker.html)

问题:

  1. 您正在通过不将其放入背景线程中来调用ScanMarket.scanMarket(),这是一个非常长的代码,在摇摆事件线程上。
  2. 当应该在秋千事件线程中排队时,您正在在背景线程中调用秋千GUI。

解决方案:

  • 使用Swingworker创建您的背景线程,并以doInBackground()方法运行长期运行的代码。
  • 通过将运行可运行的可运行到SwingUtilities.invokeLater(...)方法。
  • 阅读Swing的线程模型以及您通过阅读Swing教程中的并发性而遇到的问题。

最新更新