gpt4 book ai didi

java - 在 swing 中的 actionPerformed 中创建新线程是否安全?

转载 作者:行者123 更新时间:2023-12-01 20:05:43 24 4
gpt4 key购买 nike

我创建了在执行操作方法中执行一些操作的 swing 应用程序,但是当我创建一个显示进度条的线程时,进度条在执行操作方法期间将不可见,但最后进度条将可见,值为 100 %直接
主类:

    import javax.swing.*;
import javax.swing.plaf.ButtonUI;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class main {
public static void main(String[] args) {
JFrame win = new JFrame("Test");
FlowLayout layout = new FlowLayout();
Button b1 = new Button("Click ");
win.add(b1);
b1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
window win = new window();
win.start();
try
{
Thread.sleep(2000);
}
catch(InterruptedException e5){}
}
});
win.setLayout(layout);
win.setSize(500, 300);
win.setLocationRelativeTo(null);
win.setVisible(true);
win.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
}

窗口类别:

import javax.swing.*;
import java.awt.*;

public class window extends Thread{
public window(){

}

@Override
public void run() {
JFrame fen = new JFrame("New window");
FlowLayout layout = new FlowLayout();
fen.setLayout(layout);
Button b2 = new Button();
fen.setVisible(true);
fen.setSize(100, 100);
fen.setLocationRelativeTo(null);
fen.add(b2);
try
{
for(int i = 0; i <= 100; i++)
{
b2.setLabel("Button " + i);
Thread.sleep(10);
}
}
catch(InterruptedException e2){

}
}
}

最佳答案

是的,创建新的 Thread 是安全的actionPerformed 的内部处理程序。

但是,除了事件分派(dispatch)线程 (EDT) 之外,任何线程都不能与 Swing 组件交互。

要在 Swing 内创建动画或延迟,您必须使用 javax.swing.Timer 。执行Thread.sleep()在 EDT 上是绝对不允许的,也不会像您希望的那样。

要从生成的线程返回到 EDT,您必须使用 SwingUtilities.invokeLater() SwingUtilities.invokeAndWait() .

使用 SwingWorker 是在 Swing 中执行后台任务的首选方式。它处理从后台任务到 EDT 的部分和最终结果的通信和发布,以便在 GUI 组件中显示。

<小时/>

以下是将您的代码翻译为工作示例,使用 SwingWorker 。而不是 AWT Button的, Swing JButton用来。该程序是使用 invokeAndWait 创建的以确保主窗口构建发生在 EDT 上。使用 lambda 函数,但您可以将其替换为 new Runnable() { }内部类,如果需要的话。 “按钮 0”到“按钮 100”进度报告从 SwingWorker 发布。后台任务,用于在 EDT 中处理。在 EDT 有机会处理它们之前,后台线程可以生成多个结果;在这里,我们只使用最后一个结果来显示在按钮中。

public class Main {

public static void main(String[] args) throws Exception {
SwingUtilities.invokeAndWait(() -> {
JFrame win = new JFrame("Test");
win.setLayout(new FlowLayout());
JButton b1 = new JButton("Click");
b1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
DoWork work = new DoWork();
work.execute();
}
});
win.add(b1);
win.setSize(500, 300);
win.setLocationRelativeTo(null);
win.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
win.setVisible(true);
});
}
}

class DoWork extends SwingWorker<Void, String> {
JFrame fen;
JButton b2;

DoWork() {
fen = new JFrame("New window");
fen.setLayout(new FlowLayout());
b2 = new JButton();
fen.add(b2);
fen.setSize(100, 100);
fen.setLocationRelativeTo(null);
fen.setVisible(true);
fen.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
}

@Override
protected Void doInBackground() throws Exception {
for (int i = 0; i <= 100; i++) {
publish("Button " + i);
Thread.sleep(10);
}
return null;
}

@Override
protected void process(List<String> data) {
String last = data.get(data.size() - 1);
b2.setText(last);
}

@Override
protected void done() {
fen.dispose();
}
}

此代码仍有许多改进之处。一个JLabel而不是JButton用于显示结果, JDialog对于进度窗口,或者更好的是 ProgressMonitor 。这些留给学生作为练习。

关于java - 在 swing 中的 actionPerformed 中创建新线程是否安全?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47421860/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com