-2

Good Evening, i have a problem in running a progress bar, please check my code and tell me where is the problem:

/**
** @author Islam */

public class Register extends javax.swing.JFrame implements Runnable {

static final int MY_MINIMUM = 0;
static final int MY_MAXIMUM = 100;
private Pattern pattern;
private Matcher matcher;
private static final String EMAIL_PATTERN =
        "^[_A-Za-z0-9-\\+]+(\\.[_A-Za-z0-9-]+)*@"
        + "[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$";
boolean isValidPassord = true;
Thread th;

public Register() {
    initComponents();
    passwordTextF.addKeyListener(new passwordListener());
    passwordMeter = new JProgressBar();
    passwordMeter.setMinimum(MY_MINIMUM);
    passwordMeter.setMaximum(MY_MAXIMUM);
    th = new Thread(this);
    th.start();
}

public void updateBar(int newValue) {
    passwordMeter.setValue(newValue);
    passwordMeter.setStringPainted(true);
    System.out.println(newValue);
}

public void run() {
    for (int i = MY_MINIMUM; i <= MY_MAXIMUM; i++) {
        updateBar(i);
        try {
            Thread.sleep(100);

        } catch (InterruptedException ex) {
            Logger.getLogger(Register.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}

class passwordListener implements KeyListener {

    public void keyPressed(KeyEvent e) {
        passwordLabel.setForeground(Color.BLACK);

    }

    public void keyReleased(KeyEvent e) {

        //  Register.this.validatePassword(passwordTextF.getText());
        if (!isValidPassord) {
            //  new PasswordMeterHandler().start();
        }

    }

    public void keyTyped(KeyEvent e) {
    }
}

public boolean validateEmail(String mailFromForm) {

    pattern = Pattern.compile(EMAIL_PATTERN);
    matcher = pattern.matcher(mailFromForm);
    return matcher.matches();

}



// <editor-fold defaultstate="collapsed" desc="Generated Code">

private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
    int i = 0;
    this.validateEmail(nameTextF.getText());
    this.validatePassword(passwordTextF.getText());
    if (!matcher.matches()) {
        EMailLabel.setForeground(Color.red);
    }
    if (!isValidPassord) {
        passwordLabel.setForeground(Color.red);
    }


}

private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {
}

public static void main(String args[]) {


    /*
     * Create and display the form
     */
    java.awt.EventQueue.invokeLater(new Runnable() {

        public void run() {
            Register frame = new Register();
            frame.setVisible(true);




        }
    });
}
// Variables declaration - do not modify
private javax.swing.JLabel EMailLabel;
private javax.swing.JTextField EMailTextF;
private javax.swing.ButtonGroup buttonGroup1;
private javax.swing.ButtonGroup buttonGroup2;
private javax.swing.JComboBox countryCombo;
private javax.swing.JComboBox genderCombo;
private javax.swing.JButton jButton1;
private javax.swing.JButton jButton2;
private javax.swing.JLabel jLabel6;
private javax.swing.JLabel jLabel7;
private javax.swing.JPanel jPanel1;
private javax.swing.JLabel nameLabel;
private javax.swing.JTextField nameTextF;
private javax.swing.JLabel passwordLabel;
private javax.swing.JProgressBar passwordMeter;
private javax.swing.JPasswordField passwordTextF;
private javax.swing.JLabel strengthLabel;
private javax.swing.JLabel userNameLabel;
private javax.swing.JTextField userNameTextF;
// End of variables declaration
}
Eslam Hamdy
  • 7,126
  • 27
  • 105
  • 165
  • this issue were solved there a few times, including Background for JProgressBar – mKorbel Jan 07 '13 at 17:43
  • I would advice to read the [Swing concurrency tutorial](http://docs.oracle.com/javase/tutorial/uiswing/concurrency/index.html) and then compare your code with the [Swing progress bar tutorial](http://docs.oracle.com/javase/tutorial/uiswing/components/progress.html) – Robin Jan 07 '13 at 17:51
  • Possible duplicate of: http://stackoverflow.com/questions/14139298/thread-not-updating-progress-bar-on-glasspane/14139424#14139424. At the bare minimum, all conclusions stated in that answer are applicable here and will solve the issue. – Guillaume Polet Jan 07 '13 at 18:02

2 Answers2

0

Adding the JProgressBar to the JFrame, calling setVisible, starting the thread outside of the constructor (for premature end of thread).

public class Register extends JFrame {

static final int MY_MINIMUM = 0;
static final int MY_MAXIMUM = 100;
private JProgressBar passwordMeter;

public Register() {
    setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
    setLayout(new BorderLayout());
    setBounds(50, 50, 640, 100);
    passwordMeter = new JProgressBar();
    passwordMeter.setMinimum(MY_MINIMUM);
    passwordMeter.setMaximum(MY_MAXIMUM);
    add(passwordMeter, BorderLayout.CENTER);
}

public void start() {
    new PasswordMeterHandler().start();
}

class PasswordMeterHandler extends Thread {

    public void updateBar(final int newValue) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                passwordMeter.setValue(newValue);
                passwordMeter.setStringPainted(true);
            }
        });
        //passwordMeter.setValue(newValue);
        //passwordMeter.setStringPainted(true);
        System.out.println(newValue);
    }

    @Override
    public void run() {
        for (int i = MY_MINIMUM; i <= MY_MAXIMUM; i++) {
            updateBar(i);
            try {
                Thread.sleep(100);
            } catch (InterruptedException ex) {
                Logger.getLogger(Register.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }
}

/**
 * @param args the command line arguments
 */
public static void main(String args[]) {
    EventQueue.invokeLater(new Runnable() {
        public void run() {
            Register frame = new Register();
            frame.setVisible(true);
            frame.start();
        }
    });
}
}
Joop Eggen
  • 107,315
  • 7
  • 83
  • 138
  • 1
    This clearly violates the EDT when calling `passwordMeter.setValue(newValue); passwordMeter.setStringPainted(true);`. In addition to that, extending `Thread` is not recommended (rather implement a `Runnable` and use `Executors`) nor extending `JFrame` (it is unnecessary). Using a `SwingWorker` or a `javax.swing.Timer` is a much better choice. – Guillaume Polet Jan 07 '13 at 18:12
  • With me it works. That is on Linux however. I changed `updateBar` to use `invokeLater`. This was one critic of @GuillaumePolet. – Joop Eggen Jan 07 '13 at 18:49
  • @GuillaumePolet: you are right, but as the code is more a test of using a progress bar, not a realistic example. I put the setValue now on the EDT. – Joop Eggen Jan 07 '13 at 18:51
  • You still do not add `passwordMeter` to the JFrame. – Joop Eggen Jan 07 '13 at 20:28
  • iam using drag and drop not Layout Manager – Eslam Hamdy Jan 07 '13 at 21:03
  • i already added the progress bar to the jframe by dragging it, why i drag it and it's already exists? – Eslam Hamdy Jan 07 '13 at 22:23
  • @Eslam Because you did this `passwordMeter = new JProgressBar();` - You've now removed what `passwordMeter` WAS pointing to, to something else, meaning when you make changes to `passwordMeter` it is no longer referencing what is on the screen...This is why YOU MUST post ALL relevant code – MadProgrammer Jan 08 '13 at 00:24
  • @Eslam: you mean you added it already in the (NetBeans?) GUI editor in the IDE by dragging it from the palette window of components? The adding of the progress bar then occured indirectly in `initComponents()` called in `Register()`. But now `initComponents()` is no longer called in the code shown. Copy and run my code in another package to figure out what is the difference. – Joop Eggen Jan 08 '13 at 05:20
0

Let's start with the fact that, in your example, the progress bar is never added to anything, then move onto the violation of one of the most important Swing rules - NEVER, EVER create or modify ANY UI element out side of the Event Dispatching Thread.

KeyListener is not an appropriate method for tracking changes to text components, they do not take into account if the user pastes text into the field.

You should use a DocumentListener to monitor changes to the underlying document and a DocumentFilter if you want to change the content going into the field...

public class TestPasswordField {

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

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

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

    public class TestPane extends JPanel {

        private JPasswordField password;
        private JProgressBar progressBar;

        public TestPane() {
            setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridx = 0;
            gbc.gridy = 0;
            gbc.fill = GridBagConstraints.HORIZONTAL;

            password = new JPasswordField(10);
            progressBar = new JProgressBar(0, 10);
            password.getDocument().addDocumentListener(new DocumentListener() {

                protected void updateProgress() {
                    progressBar.setValue(password.getPassword().length);
                }

                @Override
                public void insertUpdate(DocumentEvent e) {
                    updateProgress();
                }

                @Override
                public void removeUpdate(DocumentEvent e) {
                    updateProgress();
                }

                @Override
                public void changedUpdate(DocumentEvent e) {
                    updateProgress();
                }
            });

            add(password, gbc);
            gbc.gridy++;
            add(progressBar, gbc);
        }

    }

}
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • i added the progress bar by dragging it directly on the frame, i'm not using layout manager – Eslam Hamdy Jan 08 '13 at 11:25
  • And the you went and did this passwordMeter = new JProgressBar whic has changed the reference from what you dragged onto the form to sorting else. Besides which, why should it make any difference? – MadProgrammer Jan 08 '13 at 19:35