invokeLater 的问题

Issues with invokeLater

我在使用 invokeLater 更新 JLabel 值时遇到问题。 我在运行 invokeLater 的主函数之外有一个单独的方法,但是当我单击搜索按钮更新值时,它不会在同一个 gui 实例中更新。 我必须在 eclipse 中重新启动 gui 才能更改值。 我不确定我做错了什么,所以非常感谢任何帮助。 我是 运行 这个方法 threadStart();在按钮的 actionListener 中。 方法如下

    private void threadStart() {
      SwingUtilities.invokeLater(new Runnable() {
        public void run() {

          testLabel.setText(CN);
        }

这里是完整的 class 作为参考。

import java.awt.EventQueue;

import javax.naming.InvalidNameException;
import javax.naming.ldap.LdapName;
import javax.swing.JFrame;
import javax.swing.JButton;

import java.awt.BorderLayout;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.GridLayout;

import javax.naming.ldap.LdapName;
import javax.swing.JTextField;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;

import java.awt.Color;
import java.awt.Font;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Inet4Address;
import java.net.UnknownHostException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.swing.JTextArea;
import javax.swing.JTable;

public class MISControlPanel {

    JFrame frame;
    static JTextField textField;
    private JTextField textField_1;
    final JTextArea textArea = new JTextArea();
    JLabel selectedComputerFromAD = new JLabel("testing");
    String sCurrentLine = null;
    String CN = null;
    JLabel testLabel = new JLabel("test");

    /**
     * Launch the application.
     */
    public static void main(String[] args) {

        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    MISControlPanel window = new MISControlPanel();
                    window.frame.setVisible(true);

                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * Create the application.
     * 
     * @throws IOException
     * 
     * @wbp.parser.entryPoint
     */
    public MISControlPanel() throws IOException {
        initialize();
    }

    /**
     * Initialize the contents of the frame.
     * 
     * @throws IOException
     */
    private void initialize() throws IOException {
        frame = new JFrame();
        frame.getContentPane().setBackground(Color.LIGHT_GRAY);
        frame.getContentPane().setForeground(Color.RED);
        frame.setBounds(100, 100, 658, 618);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().setLayout(null);
        frame.setTitle("MIS Advanced Computerers");
        frame.setResizable(false);
        FileWriter fw = new FileWriter("C:\Users\anoc5f\Desktop\Output.txt");
        File tempFile = new File("myTempFile.txt");
        JButton searchComputerButton = new JButton("Search");
        searchComputerButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                threadStart();
                String line;
                BufferedWriter bw = null;
                BufferedWriter writer = null;
                try {
                    writer = new BufferedWriter(new FileWriter(tempFile));
                } catch (IOException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }


                String s = null;

                Process p = null;
                /*
                 * try { // p = Runtime.getRuntime().exec(
                 * "cmd /c start c:\computerQuery.bat computerName"); } catch
                 * (IOException e1) { // TODO Auto-generated catch block
                 * e1.printStackTrace(); }
                 */
                try {

                    p = Runtime.getRuntime().exec("c:\computerQuery.bat");

                } catch (IOException e1) {

                    // TODO Auto-generated catch block

                    e1.printStackTrace();

                }
                StringBuffer sbuffer = new StringBuffer();
                BufferedReader in = new BufferedReader(new InputStreamReader(p
                        .getInputStream()));

                try {

                    while ((line = in.readLine()) != null) {

                        System.out.println(line);

                        // textArea.append(line);

                        String dn = "CN=FDCD111304,OU=Workstations,OU=SIM,OU=Accounts,DC=FL,DC=NET";
                        LdapName ldapName = new LdapName(dn);
                        String commonName = (String) ldapName.getRdn(
                                ldapName.size() - 1).getValue();

                    }
                    ComputerQuery.sendParam();

                } catch (IOException e1) {

                    // TODO Auto-generated catch block

                    e1.printStackTrace();

                } catch (InvalidNameException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                } finally

                {
                    try {
                        fw.close();

                    }

                    catch (IOException e1) {
                        // TODO Auto-generated catch block
                        e1.printStackTrace();
                    }
                }

                try {

                    in.close();

                } catch (IOException e1) {

                    // TODO Auto-generated catch block

                    e1.printStackTrace();

                }

                ComputerQuery.sendParam();

                   SwingUtilities.invokeLater(new Runnable() {
                        public void run() {
                          testLabel.setText(CN);
                        }
                      });
            }
        });

        try (BufferedReader br = new BufferedReader(new FileReader(
                "resultofbatch.txt"))) {

            final Pattern PATTERN = Pattern.compile("CN=([^,]+).*");
            try {
                while ((sCurrentLine = br.readLine()) != null) {

                    String[] tokens = PATTERN.split(","); // This will return
                                                            // you a array,
                                                            // containing the
                                                            // string array
                                                            // splitted by what
                                                            // you write inside
                                                            // it.
                    // should be in your case the split, since they are
                    // seperated by ","
                    // System.out.println(sCurrentLine);
                    CN = sCurrentLine.split("CN=", -1)[1].split(",", -1)[0];

                    System.out.println(CN);
                    testLabel.setText(CN);
                }

            } catch (IOException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }
        } catch (IOException e2) {
            // TODO Auto-generated catch block
            e2.printStackTrace();
        }
        // SwingUtilities.invokeLater(updateCN());
        searchComputerButton.setBounds(419, 19, 89, 20);
        frame.getContentPane().add(searchComputerButton);

        textField = new JTextField();
        textField.setBounds(285, 19, 124, 20);
        frame.getContentPane().add(textField);
        textField.setColumns(10);

        JLabel lblComputerName = new JLabel("Computer Name:");
        lblComputerName.setForeground(Color.BLACK);
        lblComputerName.setFont(new Font("Tahoma", Font.BOLD, 14));
        lblComputerName.setBounds(159, 13, 124, 29);
        frame.getContentPane().add(lblComputerName);

        JLabel lblSelectedComputer = new JLabel("Selected Computer:");
        lblSelectedComputer.setFont(new Font("Tahoma", Font.BOLD, 14));
        lblSelectedComputer.setBounds(205, 78, 143, 30);
        frame.getContentPane().add(lblSelectedComputer);
        java.net.InetAddress localMachine = null;
        try {
            localMachine = java.net.InetAddress.getLocalHost();
        } catch (UnknownHostException e2) {
            // TODO Auto-generated catch block
            e2.printStackTrace();
        }

        textArea.setBackground(Color.GRAY);
        textArea.setForeground(Color.WHITE);
        textArea.setFont(textArea.getFont().deriveFont(Font.BOLD));
        textArea.setBounds(10, 387, 632, 191);
        textArea.setEditable(false); // might cause design view not to come up
        frame.getContentPane().add(textArea);

        JButton btnNewButton = new JButton("SSO REPAIR");
        btnNewButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {

            }
        });
        btnNewButton.setBounds(36, 183, 132, 23);
        frame.getContentPane().add(btnNewButton);

        JLabel lblNewLabel = new JLabel("Batch File Fixes");
        lblNewLabel.setFont(new Font("Tahoma", Font.BOLD, 12));
        lblNewLabel.setBounds(53, 158, 115, 14);
        frame.getContentPane().add(lblNewLabel);

        JLabel lblIpAddress = new JLabel("IP Address:");
        lblIpAddress.setFont(new Font("Tahoma", Font.BOLD, 14));
        lblIpAddress.setBounds(261, 104, 102, 22);
        frame.getContentPane().add(lblIpAddress);

        JLabel label = null;
        try {
            label = new JLabel(Inet4Address.getLocalHost().getHostAddress()); // Get
                                                                                // User
                                                                                // ID
        } catch (UnknownHostException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
        label.setFont(new Font("Tahoma", Font.BOLD, 14));
        label.setForeground(Color.RED);
        label.setBounds(349, 105, 99, 21);
        frame.getContentPane().add(label);

        JLabel lblPcCommunication = new JLabel("PC Communication");
        lblPcCommunication.setFont(new Font("Tahoma", Font.BOLD, 12));
        lblPcCommunication.setBounds(279, 158, 115, 14);
        frame.getContentPane().add(lblPcCommunication);

        JButton btnPingComputer = new JButton("PING");

        btnPingComputer.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent arg0) {
            }

        });

        btnPingComputer.setBounds(306, 183, 64, 23);
        frame.getContentPane().add(btnPingComputer);

        JButton remoteAssistanceButton = new JButton(
                "Remote Assistance by PC Name");
        remoteAssistanceButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
            }
        });

        remoteAssistanceButton.setBounds(215, 251, 246, 23);
        frame.getContentPane().add(remoteAssistanceButton);

        JButton btnPingIndefinetely = new JButton("PING INDEFINETELY");
        btnPingIndefinetely.setBounds(260, 217, 156, 23);
        frame.getContentPane().add(btnPingIndefinetely);

        JButton btnRdcByIp = new JButton("RDC by IP Address");
        btnRdcByIp.setBounds(261, 353, 156, 23);
        frame.getContentPane().add(btnRdcByIp);

        JButton btnRdcByName = new JButton("RDC by PC Name");
        btnRdcByName.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
            }
        });
        btnRdcByName.setBounds(248, 319, 180, 23);
        frame.getContentPane().add(btnRdcByName);

        JLabel lblLoggedInOpid = new JLabel("Logged in OPID:");
        lblLoggedInOpid.setFont(new Font("Tahoma", Font.BOLD, 14));
        lblLoggedInOpid.setBounds(228, 127, 135, 20);
        frame.getContentPane().add(lblLoggedInOpid);

        JLabel lblNewLabel_1 = new JLabel(System.getProperty("user.name")
                .toUpperCase());
        lblNewLabel_1.setFont(new Font("Tahoma", Font.BOLD, 14));
        lblNewLabel_1.setForeground(Color.RED);
        lblNewLabel_1.setBounds(348, 130, 86, 14);
        frame.getContentPane().add(lblNewLabel_1);

        JButton btnHiddenShare = new JButton("HIDDEN SHARE");
        btnHiddenShare.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
            }
        });
        btnHiddenShare.setBounds(484, 183, 132, 23);
        frame.getContentPane().add(btnHiddenShare);

        JLabel lblAdditionalTools = new JLabel("Tools");
        lblAdditionalTools.setFont(new Font("Tahoma", Font.BOLD, 12));
        lblAdditionalTools.setBounds(526, 157, 126, 20);
        frame.getContentPane().add(lblAdditionalTools);

        JButton btnNewButton_1 = new JButton("Remote Assistance by IP Address");
        btnNewButton_1.setBounds(215, 285, 246, 23);
        frame.getContentPane().add(btnNewButton_1);

        JButton gpUpdate = new JButton("GP UPDATE");
        gpUpdate.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
            }
        });
        gpUpdate.setBounds(36, 217, 132, 23);
        frame.getContentPane().add(gpUpdate);

        JButton btnForced = new JButton("NURMED REG FIX");
        btnForced.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
            }
        });
        btnForced.setBounds(36, 251, 132, 23);
        frame.getContentPane().add(btnForced);

        JButton btnCleaConsoler = new JButton("CLEAR");
        btnCleaConsoler.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                textArea.setText("");
            }
        });
        btnCleaConsoler.setBounds(563, 353, 79, 23);
        frame.getContentPane().add(btnCleaConsoler);

        JLabel lblOpid = new JLabel("Find Computer by OPID:");
        lblOpid.setFont(new Font("Tahoma", Font.BOLD, 14));
        lblOpid.setBounds(104, 53, 180, 14);
        frame.getContentPane().add(lblOpid);

        textField_1 = new JTextField();
        textField_1.setBounds(285, 50, 124, 20);
        frame.getContentPane().add(textField_1);
        textField_1.setColumns(10);

        JButton btnNewButton_2 = new JButton("Search");
        btnNewButton_2.setBounds(419, 50, 89, 23);
        frame.getContentPane().add(btnNewButton_2);
        testLabel.setForeground(Color.RED);
        testLabel.setFont(new Font("Tahoma", Font.BOLD, 14));

        testLabel.setBounds(358, 78, 150, 24);
        frame.getContentPane().add(testLabel);

    }
    private void threadStart() {
          SwingUtilities.invokeLater(new Runnable() {
            public void run() {

              testLabel.setText(CN);
            }
          });
        }

}

我的建议再次是您应该:

  • 如果需要,将批处理文件输出到标准输出、控制台。
  • 通过从您的进程捕获 InputStream 和 ErrorStream 来捕获该输出。这些可以通过重定向错误流被困在一起。
  • 您应该在后台线程中执行所有这些操作,例如使用 SwingWorker。
  • 我将 SwingWorker 指定为 SwingWorker<Integer, String> 类型,这样它就可以 "publish" 从其 InputStream 中读取字符串,然后它最终可以 return 进程的整数退出代码以确保进程 运行 正常。

例如,假设我在用户工作目录中有一个名为 test.bat 的 bat 文件,它只是打印出传递给它的路径的目录:

test.bat

dir %1

您可以从 GUI 调用它并使用上述技术显示结果。

请注意,我下面的代码大量借鉴了 MadProgrammer's wonderful answer that can be found here: Printing a Java InputStream from a Process。请检查他的回答,包括他的描述,如果它能帮助您更好地理解正在发生的事情,请点赞。

另请务必阅读 Concurrency in Swing 以了解有关如何执行后台线程处理的所有详细信息,尤其是 SwingWorker 在 Swing GUI 中的使用。

import java.awt.BorderLayout;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.function.Consumer;

import javax.swing.*;

@SuppressWarnings("serial")
public class TestBatGui extends JPanel {
   public static final String BATCH_FILE_PATH = "test.bat";
   private JTextArea resultArea = new JTextArea(30, 80);

   public TestBatGui() {
      resultArea.setFocusable(false); // not allow user edits
      resultArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 12));
      JScrollPane scrollPane = new JScrollPane(resultArea);
      scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
      JPanel buttonPanel = new JPanel(new GridLayout(1, 0, 5, 0));
      int keyCode = KeyEvent.VK_H;
      String path = System.getProperty("user.home");
      buttonPanel.add(new JButton(new ShowDirAction("Home Dir", keyCode, path)));

      keyCode = KeyEvent.VK_W;
      path = System.getProperty("user.dir");
      buttonPanel.add(new JButton(new ShowDirAction("Working Dir", keyCode,
            path)));

      setLayout(new BorderLayout());
      add(scrollPane, BorderLayout.CENTER);
      add(buttonPanel, BorderLayout.PAGE_END);
   }

   // Action/ActionListener to be used by my buttons
   private class ShowDirAction extends AbstractAction {
      private String path;

      public ShowDirAction(String name, int keyCode, String path) {
         super(name);
         putValue(MNEMONIC_KEY, keyCode);
         this.path = path;
      }

      @Override
      public void actionPerformed(ActionEvent e) {
         // our SwingWorker
         BatchFileWorker batchFileWorker = new BatchFileWorker(
               resultArea, BATCH_FILE_PATH, path);
         // add a listener to respond when the worker is done
         batchFileWorker.addPropertyChangeListener(new BatchFileWorkerListener());
         batchFileWorker.execute(); // execute the worker
      }
   }

   // class to listen for when the worker has completed its work
   // and then this class extracts the SwingWorker's results via .get()
   // and does house cleaning if need be.
   private class BatchFileWorkerListener implements PropertyChangeListener {
      @Override
      public void propertyChange(PropertyChangeEvent evt) {
         if (evt.getNewValue() == SwingWorker.StateValue.DONE) {
            BatchFileWorker worker = (BatchFileWorker) evt.getSource();
            try {
               // extract the result returned from the worker's doInBackground() method
               // and most importantly, trap any exceptions thrown
               int exitValue = worker.get();
               String displayText = "";
               if (exitValue != 0) {
                  displayText = String.format("Error when running batch, Exit Value: %d", exitValue);
               } else {
                  displayText = "Batch file ran without error";
               }
               ((Consumer<String>) worker).accept(displayText);
               ((Consumer<String>) worker).accept("\n");
            } catch (InterruptedException e) {
               e.printStackTrace();
            } catch (ExecutionException e) {
               e.printStackTrace();
            }
         }
      }
   }

   // Our SwingWorker. It's also a Consumer so that outside classes, namely the InputConsumer
   // can pass the strings that it reads back into the worker via the accept(...) method
   private class BatchFileWorker extends SwingWorker<Integer, String> implements Consumer<String> {
      private JTextArea resultArea;
      private String batchFilePath;
      private String dirPath;

      public BatchFileWorker(JTextArea resultArea, String batchFilePath,
            String dirPath) {
         this.resultArea = resultArea;
         this.batchFilePath = batchFilePath;
         this.dirPath = dirPath;
      }

      @Override
      protected Integer doInBackground() throws Exception {
         // command list to load into the process builder
         List<String> commandList = new ArrayList<>();
         int exitCode = 0;
         publish("Getting dir for " + dirPath);
         commandList.add("cmd");
         commandList.add("/c");
         commandList.add(batchFilePath);
         commandList.add(dirPath);

         // create the process builder
         ProcessBuilder pBuilder = new ProcessBuilder(commandList);

         // add the error stream to the input stream so now we have only one stream to handle 
         pBuilder.redirectErrorStream();  
         Process p = pBuilder.start(); // create our process
         InputStream is = p.getInputStream();  // get its InputStream and use it 
         InputStreamReader isr = new InputStreamReader(is);  // to create a 
         BufferedReader br = new BufferedReader(isr);  // BufferedReader
         InputConsumer consumer = new InputConsumer(br, this); // pass into our consumer object
         Thread thread = new Thread(consumer); // start this in a background thread
         thread.start();
         exitCode = p.waitFor(); // wait in this thread for the error code
         thread.join(); // join two threads
         br.close();  // close the BufferedReader
         return exitCode;
      }

      @Override // this allows our InputConsumer to pass Strings read back into the SwingWorker
      public void accept(String text) {
         publish(text);
      }

      @Override // published text will be sent here on the EDT, to be placed into the JTextArea
      protected void process(List<String> chunks) {
         for (String chunk : chunks) {
            resultArea.append(chunk + "\n"); 
         }
      }
   }

   // to read in from the BufferedReader, passing text back into its consumer
   private class InputConsumer implements Runnable {
      private BufferedReader br;
      private Consumer<String> consumer;

      public InputConsumer(BufferedReader br, Consumer<String> consumer) {
         this.br = br;
         this.consumer = consumer;
      }

      @Override
      public void run() {
         String line = null;
         try {
            while ((line = br.readLine()) != null) {
               consumer.accept(line);
            }
         } catch (IOException e) {
            e.printStackTrace();
         }
      }
   }

   private static void createAndShowGui() {
      TestBatGui mainPanel = new TestBatGui();

      JFrame frame = new JFrame("TestBatGui");
      frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}