Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java中的GUI线程(和SwingUtilities)_Java_Multithreading_Swing_User Interface_Freeze - Fatal编程技术网

Java中的GUI线程(和SwingUtilities)

Java中的GUI线程(和SwingUtilities),java,multithreading,swing,user-interface,freeze,Java,Multithreading,Swing,User Interface,Freeze,我正在用swing用Java制作一个简单的游戏,在按下按钮触发JPanels中的一个开关后,我的GUI偶尔会冻结(很可能是由于线程问题) 我发布了一个相关的帖子,其中有关于我当前使用的实际代码的更多细节(尽管我确实更新了倒计时并使其正常工作)。从对该线程的回答来看,似乎使用了SwingUtilities。invokeLater()或invokeAndWait()可能是我解决问题所需要的,但我不确定在我的代码中哪里需要它,或者确切地说如何实现它 我对线程不太了解,可能需要我能得到的任何帮助(最好有

我正在用swing用Java制作一个简单的游戏,在按下按钮触发JPanels中的一个开关后,我的GUI偶尔会冻结(很可能是由于线程问题)

我发布了一个相关的帖子,其中有关于我当前使用的实际代码的更多细节(尽管我确实更新了倒计时并使其正常工作)。从对该线程的回答来看,似乎使用了
SwingUtilities。invokeLater()
invokeAndWait()
可能是我解决问题所需要的,但我不确定在我的代码中哪里需要它,或者确切地说如何实现它

我对线程不太了解,可能需要我能得到的任何帮助(最好有点详细,并带有一些示例代码)。请告诉我是否有其他有用的详细信息。

请参阅:

一般来说,事件调度线程是一个单独的线程,通过事件队列,一次处理一个

SwingUtilities.invokeLater(..) 
在此队列上放置可运行的。因此,当EDT在它之前完成队列上的所有事情时,它将由EDT处理(这就是为什么在队列上睡眠会阻止其他事件,如重新绘制)。从EDT本身调用invokeLater(..)是相对不常见的,尽管在某些情况下它是有用的(通常作为一个黑客)。我认为我在过去6年中没有合法使用SwingUtilities.invokeAndWait(..)。也许一次


javax.swing.Timer
可以配置为一次或定期触发。当它触发时,它会将一个事件放入EDT队列。如果您需要进行计算密集型处理,请考虑使用<代码> javax .Swing .Swing Works/COD>在另一个线程上进行计算,并以线程安全的方式返回结果(这也是比较少见的)。在您的案例中,这说明了
SwingUtilities.invokeLater()
如何工作以及在何处使用它:

导致在AWT事件上异步执行doRun.run() 调度线程应用程序启动时应使用此方法 线程需要更新GUI

因此,在修改GUI的操作中,必须使用
invokeLater
方法来确保GUI不会冻结


另一个很好的资源是Java教程。它们包括。

如果您在GUI代码中定义了一些类似的工作

Runnable doWorkRunnable = new Runnable() {
    @Override
    public void run() { 
        doWork(); 
    }
};
通过将其附加到新的
线程

Thread t = new Thread(doWorkRunnable);
t.start();
您正在GUI线程中执行工作,这将导致Swing应用程序出现问题

相反,试试这个(让我提一下,这只是一个用法示例)

这会将您的
Runnable
worker放入AWT事件队列,并在以前的事件完成时执行它

编辑:下面是一个完整的示例,它执行从3到0的倒计时,然后在倒计时后执行您想要执行的任何操作

public class TestFrame extends JFrame {

    private JPanel contentPane;
    private final Timer timer;
    private TimerTask[] tasks;

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    TestFrame frame = new TestFrame();
                    frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    public TestFrame() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 450, 300);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        contentPane.setLayout(new BorderLayout(0, 0));
        final JLabel lblCountdown = new JLabel();
        contentPane.add(lblCountdown, BorderLayout.NORTH);
        JButton btnStart = new JButton("Start");
        contentPane.add(btnStart, BorderLayout.SOUTH);

        timer = new Timer();
        tasks = new TimerTask[4];

        setContentPane(contentPane);

        for (int i = 0; i < 4; i++) {
            final int count = i;
            tasks[i] = new TimerTask() {
                public void run() {
                    EventQueue.invokeLater(new Runnable() {
                        @Override
                        public void run() {
                            lblCountdown.setText(count + "");
                        }
                    });
                }
            };
        }

        btnStart.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {

                for (int i = 0; i < 4; i++) {
                    timer.schedule(tasks[4 - i - 1], (1000 * i), (1000 * (i + 1)));
                }
                // add another timer.schedule(TimerTask)
                // to execute that "move to game screen" task
                TimerTask taskGotoGame = new TimerTask() {
                    public void run() {
                        timer.cancel();
                        JOptionPane.showMessageDialog(null, "Go to game", "Will now", JOptionPane.INFORMATION_MESSAGE);
                        System.exit(0);
                    }
                };
                // and schedule it to happen after ROUGHLY 3 seconds
                timer.schedule(taskGotoGame, 3000);
            }
        });

    }

}
公共类TestFrame扩展了JFrame{
私有JPanel内容窗格;
私人最终定时器;
专用TimerTask[]任务;
公共静态void main(字符串[]args){
invokeLater(新的Runnable(){
公开募捐{
试一试{
TestFrame=新的TestFrame();
frame.setVisible(true);
}捕获(例外e){
e、 printStackTrace();
}
}
});
}
公共测试框架(){
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
立根(100100450300);
contentPane=newjpanel();
setboorder(新的EmptyBorder(5,5,5,5));
setLayout(新的BorderLayout(0,0));
最终JLabel lblCountdown=新JLabel();
添加(lblCountdown,BorderLayout.NORTH);
JButton btnStart=新JButton(“开始”);
添加(btnStart,BorderLayout.SOUTH);
定时器=新定时器();
任务=新时间任务[4];
setContentPane(contentPane);
对于(int i=0;i<4;i++){
最终整数计数=i;
任务[i]=新的TimerTask(){
公开募捐{
invokeLater(新的Runnable(){
@凌驾
公开募捐{
lblCountdown.setText(计数+“”);
}
});
}
};
}
btnStart.addActionListener(新ActionListener(){
已执行的公共无效操作(操作事件e){
对于(int i=0;i<4;i++){
时间表(任务[4-i-1],(1000*i),(1000*(i+1));
}
//添加另一个计时器。计划(TimerTask)
//执行“移动到游戏屏幕”任务
TimerTask task gotogame=新TimerTask(){
公开募捐{
timer.cancel();
showMessageDialog(null,“进入游戏”,“现在将”,JOptionPane.INFORMATION\u消息);
系统出口(0);
}
};
//并计划在大约3秒钟后进行
时间表(taskGotoGame,3000);
}
});
}
}

我创建了一个WorkerThread类,负责线程和GUI当前/主线程。我已经将我的GUI应用程序放在WorkerThread的construct()方法中,当一个事件触发启动XXXServer时,所有线程都被激活,GUI在不冻结的情况下顺利工作。看一看。 /** *动作事件 * *@see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) */ 已执行的公共无效行动(行动事件ae){ log.info(“actionPerformed begin…”+ae.getActionCommand())


为了在现有WorkerThread中调用操作,
public class TestFrame extends JFrame {

    private JPanel contentPane;
    private final Timer timer;
    private TimerTask[] tasks;

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    TestFrame frame = new TestFrame();
                    frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    public TestFrame() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 450, 300);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        contentPane.setLayout(new BorderLayout(0, 0));
        final JLabel lblCountdown = new JLabel();
        contentPane.add(lblCountdown, BorderLayout.NORTH);
        JButton btnStart = new JButton("Start");
        contentPane.add(btnStart, BorderLayout.SOUTH);

        timer = new Timer();
        tasks = new TimerTask[4];

        setContentPane(contentPane);

        for (int i = 0; i < 4; i++) {
            final int count = i;
            tasks[i] = new TimerTask() {
                public void run() {
                    EventQueue.invokeLater(new Runnable() {
                        @Override
                        public void run() {
                            lblCountdown.setText(count + "");
                        }
                    });
                }
            };
        }

        btnStart.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {

                for (int i = 0; i < 4; i++) {
                    timer.schedule(tasks[4 - i - 1], (1000 * i), (1000 * (i + 1)));
                }
                // add another timer.schedule(TimerTask)
                // to execute that "move to game screen" task
                TimerTask taskGotoGame = new TimerTask() {
                    public void run() {
                        timer.cancel();
                        JOptionPane.showMessageDialog(null, "Go to game", "Will now", JOptionPane.INFORMATION_MESSAGE);
                        System.exit(0);
                    }
                };
                // and schedule it to happen after ROUGHLY 3 seconds
                timer.schedule(taskGotoGame, 3000);
            }
        });

    }

}
    try {
        if (ae.getActionCommand().equals(btnStart.getText())) {
             final int portNumber = 9990;
             try {

                 WorkerThread workerThread = new WorkerThread(){
                    public Object construct(){

                        log.info("Initializing the XXXServer ...");
                        // initializing the Socket Server
                         try {
                            XXXServer xxxServer = new XXXServer(portNumber);
                            xxxServer.start();
                            btnStart.setEnabled(false);                             
                        } catch (IOException e) {
                            // TODO Auto-generated catch block
                            log.info("actionPerformed() Start button ERROR IOEXCEPTION..." + e.getMessage());
                            e.printStackTrace();
                        }
                        return null;
                    }
                };workerThread.start();
                } catch (Exception e) {
                    log.info("actionPerformed() Start button ERROR..." + e.getMessage());
                    e.printStackTrace();
             }


        } else if (ae.getActionCommand().equals(btnStop.getText())) {
            log.info("Exit..." + btnStop.getText());
            closeWindow();
        }

    } catch (Exception e) {
        log
            .info("Error in ServerGUI actionPerformed==="
                + e.getMessage());
    }

}
class TestFrame extends JFrame implements ActionListener
{
...

    private class Performer implements Runnable
    {
        ActionEvent event;

        Performer(ActionEvent event)
        {
            this.event = event;
        }

        @Override
        public void run()
        {
            actionPerformed(event);
        }

    }

    synchronized protected void invokeLater(ActionEvent event)
    {
        SwingUtilities.invokeLater(new Performer(event));
    }

    public void actionPerformed(ActionEvent event)
    {
        ...
    }

}