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 SwingWorkerdone() 方法中填充 JComboBox。由于所有工作都在 SwingWorker class 中完成,方法 doInBackground() 不需要 return 任何东西。

当谈到使用 SwingWorker 时,我更喜欢制作一个完全独立的 class 来扩展 SwingWorker 而不是匿名内部 class.

这是 Swing 应用程序的代码。 JFrame 显示一个 JLabel 和一个 JComboBoxJcomboBox 包含所有网络接口名称的列表。

请注意,在我的 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));
    }
}