-3

Feel free to make suggestions how should I use propertychangeListener in this code(TextArea and ProgressBar), because I want update the GUI outside of background thread. It's a simple "portscanner" with three function.

This is my code:

package main;

import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import javax.swing.JOptionPane;
import javax.swing.SwingWorker;

public class PortScanner extends javax.swing.JFrame {

    private doSomeStuff taskPortScanner;
    private boolean breakPoint;

    public PortScanner() {
        initComponents();
    }

    private void portScan() {

        int currentPort = 1;

        try {

            String hostname = hostNameTextField.getText();
            int timeOut = (Integer) timeOutSpinner.getValue();
            int minPort = Integer.parseInt(portMinTextField.getText());
            int maxPort = Integer.parseInt(portMaxTextField.getText());

            //set min and max value of progress bar
            jProgressBar1.setMinimum(minPort);
            jProgressBar1.setMaximum(maxPort);

            //print out the address
            InetAddress theAddress = InetAddress.getByName(hostname);
            resultTextArea.append("IP adress: " + theAddress + "\n\n");

            //check if port is open
            for (currentPort = minPort; currentPort <= maxPort; currentPort++) {

                //stop for loop
                if (breakPoint == true) {
                    System.out.println("Portscanning stopped: " + breakPoint);
                    break;
                }

                try {

                    Socket socket = new Socket();
                    socket.connect(new InetSocketAddress(hostname, currentPort), timeOut);

                    //update textarea
                    resultTextArea.append("Service running on port " + currentPort + "\n");
                    socket.close();

                } catch (Exception ex) {
                    System.out.println(currentPort);
                }

                //update progressbar
                jProgressBar1.setValue(currentPort);
                jProgressBar1.repaint();
            }

        } catch (UnknownHostException ex) {
            JOptionPane.showMessageDialog(PortScanner.this, "Unknown hostname: " + ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
        } catch (NumberFormatException ex) {
            JOptionPane.showMessageDialog(PortScanner.this, "Invalid format. " + ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
        } catch (Exception ex) {
            JOptionPane.showMessageDialog(PortScanner.this, "Error: " + ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
        }
    }

    private class doSomeStuff extends SwingWorker<Void, Void> {

        @Override
        public Void doInBackground() throws Exception {
            portScan();
            return null;
        }

        @Override
        public void done() {
            //if thread is done enable start and clear buttons
            clearButton.setEnabled(true);
            startButton.setEnabled(true);
        }

    }

    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
    private void initComponents() {

        jLabel1 = new javax.swing.JLabel();
        jLabel2 = new javax.swing.JLabel();
        jLabel3 = new javax.swing.JLabel();
        jLabel4 = new javax.swing.JLabel();
        hostNameTextField = new javax.swing.JTextField();
        timeOutSpinner = new javax.swing.JSpinner();
        portMinTextField = new javax.swing.JTextField();
        portMaxTextField = new javax.swing.JTextField();
        jScrollPane1 = new javax.swing.JScrollPane();
        resultTextArea = new javax.swing.JTextArea();
        jProgressBar1 = new javax.swing.JProgressBar();
        startButton = new javax.swing.JButton();
        clearButton = new javax.swing.JButton();
        stopButton = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("Simple port scanner");
        setResizable(false);

        jLabel1.setText("Hostname");

        jLabel2.setText("Timeout");

        jLabel3.setText("Port range");

        jLabel4.setText("-");

        hostNameTextField.setToolTipText("Type a hostname like www.google.com");

        timeOutSpinner.setModel(new javax.swing.SpinnerNumberModel(15, 0, 999999, 1));

        portMinTextField.setText("1");

        portMaxTextField.setText("1000");

        resultTextArea.setColumns(20);
        resultTextArea.setRows(5);
        jScrollPane1.setViewportView(resultTextArea);

        jProgressBar1.setStringPainted(true);
        jProgressBar1.addPropertyChangeListener(new java.beans.PropertyChangeListener() {
            public void propertyChange(java.beans.PropertyChangeEvent evt) {
                jProgressBar1PropertyChange(evt);
            }
        });

        startButton.setText("Scan");
        startButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                startButtonActionPerformed(evt);
            }
        });

        clearButton.setText("Clear");
        clearButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                clearButtonActionPerformed(evt);
            }
        });

        stopButton.setText("Stop");
        stopButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                stopButtonActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                        .addContainerGap()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addGroup(layout.createSequentialGroup()
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                    .addComponent(jLabel2)
                                    .addComponent(jLabel1))
                                .addGap(21, 21, 21)
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                                    .addComponent(hostNameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 112, javax.swing.GroupLayout.PREFERRED_SIZE)
                                    .addGroup(layout.createSequentialGroup()
                                        .addComponent(timeOutSpinner)
                                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))))
                            .addGroup(layout.createSequentialGroup()
                                .addComponent(jLabel3)
                                .addGap(18, 18, 18)
                                .addComponent(portMinTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 62, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                                .addComponent(jLabel4)
                                .addGap(12, 12, 12)
                                .addComponent(portMaxTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 62, javax.swing.GroupLayout.PREFERRED_SIZE)))
                        .addGap(0, 0, Short.MAX_VALUE))
                    .addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(jProgressBar1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addContainerGap())
            .addGroup(layout.createSequentialGroup()
                .addGap(30, 30, 30)
                .addComponent(startButton)
                .addGap(18, 18, 18)
                .addComponent(stopButton)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 46, Short.MAX_VALUE)
                .addComponent(clearButton)
                .addGap(32, 32, 32))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel1)
                    .addComponent(hostNameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel2)
                    .addComponent(timeOutSpinner, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel3)
                    .addComponent(portMinTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(portMaxTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel4))
                .addGap(18, 18, 18)
                .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 157, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(18, 18, 18)
                .addComponent(jProgressBar1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 23, Short.MAX_VALUE)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(startButton)
                    .addComponent(clearButton)
                    .addComponent(stopButton))
                .addContainerGap())
        );

        pack();
    }// </editor-fold>                        

    private void startButtonActionPerformed(java.awt.event.ActionEvent evt) {                                            
        // TODO add your handling code here:
        breakPoint = false;
        taskPortScanner = new doSomeStuff();
        taskPortScanner.execute();
        startButton.setEnabled(false);
        clearButton.setEnabled(false);
        System.out.println("Starting portscanner...");

    }                                           

    private void clearButtonActionPerformed(java.awt.event.ActionEvent evt) {                                            
        // TODO add your handling code here:
        resultTextArea.setText(null);
        jProgressBar1.setValue(0);
        System.out.println("Clearing results...");
    }                                           

    private void stopButtonActionPerformed(java.awt.event.ActionEvent evt) {                                           
        // TODO add your handling code here:
        breakPoint = true;
        startButton.setEnabled(true);
        clearButton.setEnabled(true);
    }                                          

    private void jProgressBar1PropertyChange(java.beans.PropertyChangeEvent evt) {                                             
        // TODO add your handling code here:



    }                                            

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        /* Set the Nimbus look and feel */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
         * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(PortScanner.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(PortScanner.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(PortScanner.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(PortScanner.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        /* Create and display the form */
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new PortScanner().setVisible(true);
            }
        });
    }

    // Variables declaration - do not modify                     
    private javax.swing.JButton clearButton;
    private javax.swing.JTextField hostNameTextField;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JProgressBar jProgressBar1;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JTextField portMaxTextField;
    private javax.swing.JTextField portMinTextField;
    private javax.swing.JTextArea resultTextArea;
    private javax.swing.JButton startButton;
    private javax.swing.JButton stopButton;
    private javax.swing.JSpinner timeOutSpinner;
    // End of variables declaration                   
}
mKorbel
  • 109,525
  • 20
  • 134
  • 319
enkeyz
  • 43
  • 1
  • 7
  • 1) Do we really need more then 300 lines of code to help you 2) What is your actual question. You do not state what you want to achieve nor where you actually got stuck – Robin Oct 19 '14 at 16:30
  • 1
    Sorry to be blunt, but yours is a lazy question as it's little more than a statement of requirements and a code dump. I'd love to help you, but first need help from you before being able to do so. Please tell more of the specifics of your problem, what you've tried, where **exactly** you are stuck. When asking questions here it's always a good idea to follow what I call "the questioner's golden rule": please put in as much effort into asking your question as you'd like a volunteer to expend in answering it. Good luck. – Hovercraft Full Of Eels Oct 19 '14 at 16:31
  • @HovercraftFullOfEels: I want create propertchangeListener methods to change TextArea and ProgressBar values, because right now, its in the background thread, and that's not a good idea. – enkeyz Oct 19 '14 at 16:33
  • Again, you're posting just requirements. I'm asking you to edit your question, to update it, but to put some more real effort into your question. After all, you're asking us, all volunteers, to put in effort to help you. – Hovercraft Full Of Eels Oct 19 '14 at 16:37
  • `right now, its in the background thread, and that's not a good idea.` Why do you say that? All long running tasks should execute in a background Thread so the code does not block the Event Dispatch Thread. If you want to update the GUI from within the background Thread, then you need to wrap the update code in a SwingUtilities.invokeLater(...). – camickr Oct 19 '14 at 16:42
  • @camickr I want update the GUI outside of the background thread. – enkeyz Oct 19 '14 at 16:45
  • [For example](http://stackoverflow.com/a/15729267/522444) – Hovercraft Full Of Eels Oct 19 '14 at 17:01
  • The basic concept is [demonstrated here](http://stackoverflow.com/questions/26444175/how-to-use-jprogress-bar-for-processbuilder-process/26445184#26445184) – MadProgrammer Oct 19 '14 at 23:47
  • `SwingWorker#setProgress`, then listen for a `progress` property change event...pretty simple really... – MadProgrammer Oct 19 '14 at 23:48

1 Answers1

1

Remove ALL references of Swing components from the SwingWorker, in fact, the more you can decouple the worker from the UI the better, it should have NO idea of how your UI might work, it should simply know that it might need to provide information back in some way.

SwingWorker provides progress updates via the setProgress method and PropertyChangeListener support, you can also monitor the state of the Worker and make changes as you see fit, for example...

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class SwingWorkerProgress {

    public static void main(String[] args) {
        new SwingWorkerProgress();
    }

    public SwingWorkerProgress() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private JProgressBar pb;
        private JButton startButton;

        public TestPane() {

            setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridwidth = GridBagConstraints.REMAINDER;

            pb = new JProgressBar();
            startButton = new JButton("Make it so");

            add(pb, gbc);
            add(startButton, gbc);

            startButton.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    startButton.setEnabled(false);
                    ProgressWorker worker = new ProgressWorker();
                    worker.addPropertyChangeListener(new PropertyChangeListener() {
                        @Override
                        public void propertyChange(PropertyChangeEvent evt) {
                            if ("state".equals(evt.getPropertyName())) {

                                SwingWorker.StateValue state = (SwingWorker.StateValue) evt.getNewValue();
                                switch (state) {
                                    case DONE:
                                        startButton.setEnabled(true);
                                        break;
                                    case STARTED:
                                        pb.setValue(0);
                                        break;
                                }

                            } else if ("progress".equals(evt.getPropertyName())) {

                                int progress = (Integer)evt.getNewValue();
                                pb.setValue(progress);

                            }
                        }
                    });
                    worker.execute();
                }
            });

        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

    }

    public class ProgressWorker extends SwingWorker {

        @Override
        protected Object doInBackground() throws Exception {

            int max = 1000;
            for (int index = 0; index < max; index++) {

                int progress = Math.round(((float)index / (float)max) * 100f);
                setProgress(progress);
                Thread.sleep(16);

            }
            return null;
        }

    }

}
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366