Return 从 SwingWorker 线程到主线程的数组
Return Array From SwingWorker Thread to Main Thread
我有一个 Swing GUI,当它打开时会在后台执行一个线程。为此,我使用了 SwingWorker
线程。问题是我在主线程中声明了一个字符串数组,它应该从 swing 工作线程和 return 收集信息,但是在线程完成后数组仍然是空的。我想一旦线程完成,即使数组是在主线程中声明的,数组也会丢失它的值。
如何return将数组的值传给主线程?
ArrayList<String> allnets = new ArrayList();
new SwingWorker<Object, Void>() {
@Override
public Object doInBackground() throws SocketException, UnknownHostException {
System.out.println("interfaces");
netAdapter = new NetInterface();
System.out.println(Thread.currentThread().getName());
for(int i = 0; i < allnets.length; i++) {
allnets.add("interface number");
}
return null;
}
@Override
public void done() {
}
}.execute();
System.out.println(Thread.currentThread().getName());
// String[] inetfaces = {"eth0", "eth1", "wlan1", "wlan2", "wlan3"};
JComboBox comboBox = new JComboBox(allnets);
comboBox.setToolTipText("Interfaces");
comboBox.setBounds(444, 51, 137, 22);
frame.getContentPane().add(comboBox);
要获取所有接口名称的列表,请调用 class java.net.NetworkInterface
的 [static] 方法 getNetworkInterfaces()
。我假设您想从 SwingWorker
内部调用该方法。另外,根据您发布的代码,我假设您想要在 class SwingWorker
的 done()
方法中填充 JComboBox
。由于所有工作都在 SwingWorker
class 中完成,方法 doInBackground()
不需要 return 任何东西。
当谈到使用 SwingWorker
时,我更喜欢制作一个完全独立的 class 来扩展 SwingWorker
而不是匿名内部 class.
这是 Swing 应用程序的代码。 JFrame
显示一个 JLabel
和一个 JComboBox
。 JcomboBox
包含所有网络接口名称的列表。
请注意,在我的 Windows 10(64 位)机器 运行 JDK 13 上,填充 JComboBox
几乎不需要任何时间,因此 SwingWorker
并不是真正需要的。我猜你只是想练习使用 SwingWorker
,对吗?
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.net.NetworkInterface;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingWorker;
import javax.swing.WindowConstants;
public class SwngWrkr implements Runnable {
private JComboBox<Object> combo;
private JFrame frame;
public void run() {
showGui();
}
private JPanel createMainPanel() {
JPanel mainPanel = new JPanel();
mainPanel.add(new JLabel("Interfaces"));
DefaultComboBoxModel<Object> model = new DefaultComboBoxModel<Object>();
model.addElement("Loading...");
combo = new JComboBox<Object>(model);
mainPanel.add(combo);
return mainPanel;
}
private void showGui() {
frame = new JFrame("SW");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.add(createMainPanel(), BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
new GetIfTsk(combo).execute();
}
public static void main(String[] args) {
SwngWrkr instance = new SwngWrkr();
EventQueue.invokeLater(instance);
}
}
class GetIfTsk extends SwingWorker<Void, Void> {
private JComboBox<Object> combo;
private List<Object> netIfNames;
public GetIfTsk(JComboBox<Object> combo) {
this.combo = combo;
netIfNames = new ArrayList<>();
}
protected Void doInBackground() throws Exception {
Enumeration<NetworkInterface> ifs = NetworkInterface.getNetworkInterfaces();
int ndx = 0;
while (ifs.hasMoreElements()) {
NetworkInterface ni = ifs.nextElement();
String name = ni.getName();
System.out.printf("%2d. %s%n", ++ndx, name);
netIfNames.add(name);
}
return null;
}
protected void done() {
DefaultComboBoxModel<Object> model = (DefaultComboBoxModel<Object>) combo.getModel();
model.removeAllElements();
model.addAll(netIfNames);
model.setSelectedItem(netIfNames.get(0));
}
}
我有一个 Swing GUI,当它打开时会在后台执行一个线程。为此,我使用了 SwingWorker
线程。问题是我在主线程中声明了一个字符串数组,它应该从 swing 工作线程和 return 收集信息,但是在线程完成后数组仍然是空的。我想一旦线程完成,即使数组是在主线程中声明的,数组也会丢失它的值。
如何return将数组的值传给主线程?
ArrayList<String> allnets = new ArrayList();
new SwingWorker<Object, Void>() {
@Override
public Object doInBackground() throws SocketException, UnknownHostException {
System.out.println("interfaces");
netAdapter = new NetInterface();
System.out.println(Thread.currentThread().getName());
for(int i = 0; i < allnets.length; i++) {
allnets.add("interface number");
}
return null;
}
@Override
public void done() {
}
}.execute();
System.out.println(Thread.currentThread().getName());
// String[] inetfaces = {"eth0", "eth1", "wlan1", "wlan2", "wlan3"};
JComboBox comboBox = new JComboBox(allnets);
comboBox.setToolTipText("Interfaces");
comboBox.setBounds(444, 51, 137, 22);
frame.getContentPane().add(comboBox);
要获取所有接口名称的列表,请调用 class java.net.NetworkInterface
的 [static] 方法 getNetworkInterfaces()
。我假设您想从 SwingWorker
内部调用该方法。另外,根据您发布的代码,我假设您想要在 class SwingWorker
的 done()
方法中填充 JComboBox
。由于所有工作都在 SwingWorker
class 中完成,方法 doInBackground()
不需要 return 任何东西。
当谈到使用 SwingWorker
时,我更喜欢制作一个完全独立的 class 来扩展 SwingWorker
而不是匿名内部 class.
这是 Swing 应用程序的代码。 JFrame
显示一个 JLabel
和一个 JComboBox
。 JcomboBox
包含所有网络接口名称的列表。
请注意,在我的 Windows 10(64 位)机器 运行 JDK 13 上,填充 JComboBox
几乎不需要任何时间,因此 SwingWorker
并不是真正需要的。我猜你只是想练习使用 SwingWorker
,对吗?
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.net.NetworkInterface;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingWorker;
import javax.swing.WindowConstants;
public class SwngWrkr implements Runnable {
private JComboBox<Object> combo;
private JFrame frame;
public void run() {
showGui();
}
private JPanel createMainPanel() {
JPanel mainPanel = new JPanel();
mainPanel.add(new JLabel("Interfaces"));
DefaultComboBoxModel<Object> model = new DefaultComboBoxModel<Object>();
model.addElement("Loading...");
combo = new JComboBox<Object>(model);
mainPanel.add(combo);
return mainPanel;
}
private void showGui() {
frame = new JFrame("SW");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.add(createMainPanel(), BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
new GetIfTsk(combo).execute();
}
public static void main(String[] args) {
SwngWrkr instance = new SwngWrkr();
EventQueue.invokeLater(instance);
}
}
class GetIfTsk extends SwingWorker<Void, Void> {
private JComboBox<Object> combo;
private List<Object> netIfNames;
public GetIfTsk(JComboBox<Object> combo) {
this.combo = combo;
netIfNames = new ArrayList<>();
}
protected Void doInBackground() throws Exception {
Enumeration<NetworkInterface> ifs = NetworkInterface.getNetworkInterfaces();
int ndx = 0;
while (ifs.hasMoreElements()) {
NetworkInterface ni = ifs.nextElement();
String name = ni.getName();
System.out.printf("%2d. %s%n", ++ndx, name);
netIfNames.add(name);
}
return null;
}
protected void done() {
DefaultComboBoxModel<Object> model = (DefaultComboBoxModel<Object>) combo.getModel();
model.removeAllElements();
model.addAll(netIfNames);
model.setSelectedItem(netIfNames.get(0));
}
}