javamultithreadingswinginvokelater

Issues with invokeLater


I'm having issues updating a JLabel value using invokeLater. I have a separate method outside of the main function that runs invokeLater, but when I click the search button to update the value, it's not updating in the same instance of the gui. I have to relaunch the gui in eclipse to get the value to change. I'm not sure what I'm doing wrong so any help is greatly appreciated. I'm running this method threadStart(); in the actionListener of the button. Here's the method

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

          testLabel.setText(CN);
        }

Here's the full class as a reference.

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);
            }
          });
        }

}

enter image description here


Solution

  • My recommendations are again that you should:


    For instance, say I had a bat file in the user working directory called test.bat that simply printed out the directory of the path passed into it:

    test.bat

    dir %1
    

    You could call this from a GUI and display the results using the techniques described above.

    Note that my code below borrows heavily from MadProgrammer's wonderful answer that can be found here: Printing a Java InputStream from a Process. Please check his answer including his description and up-vote it if it helps you to better understand what's going on.

    Also be sure to read Concurrency in Swing for all the details on how to do background threading and in particular SwingWorker use in Swing GUI's.

    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();
             }
          });
       }
    }