This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 7 years ago.
I'm relatively new to Java and I am trying to make a login page for my desktop application. I have a thread called "listen" that should be called when the application first opens, its job is to check weather the username and password fields are not blank.
public class Login extends JFrame implements Runnable {
private JPanel contentPane;
private JTextField txtUsername;
private JPasswordField pwdPassword;
private JLabel lblUsername;
private JButton btnLogin;
private JLabel lblPassword;
private JCheckBox cboxRemember;
private Thread run, listen;
private boolean running = true;
public Login() {
createWindow();
run = new Thread(this, "Running");
running = true;
run.start();
}
private void createWindow() {
//application layout and actionListener for login button
}
public void run() {
listen();
}
public void listen() {
listen = new Thread("Listen") {
public void run() {
while (running) {
if (txtUsername.getText().equals("") || pwdPassword.getText().equals("")) btnLogin.setEnabled(false);
else btnLogin.setEnabled(true);
}
}
};
listen.start();
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Login frame = new Login();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
}
Whenever i try to execute my code the 'listen' thread throws a NullPointerException on this line if (txtUsername.getText().equals("") || pwdPassword.getText().equals("")) btnLogin.setEnabled(false); I'm not sure what am I doing wrong, any help will be appreciated, thanks.
Initialize your txtUserName and pwdPassword:
txtUsername = new JTextField();
pwdPassword = new JPasswordField();
Hope this helps.
I think you're if{} block gets executed before any initialization. Add
if (txtUsername.getText()!=null &&( txtUsername.getText().equals("") || pwdPassword.getText().equals("")))
Since txtUsername and pwdPassword have not been initialized, you will get a NPE in your IF{} statement.
Related
public class Worker extends SwingWorker<Integer, String> {
private JLabel screen;
public Worker(JLabel screen) {
this.screen = screen;
}
#Override
protected Integer doInBackground() throws Exception {
for (; ; ) {
publish(String.valueOf(Calendar.getInstance().getTimeInMillis()));
}
}
#Override
protected void process(List<String> chunks) {
screen.setText(chunks.get(0));
}
}
And in Form:
public class Form extends JPanel{
private JButton startButton;
private JPanel rootPanel;
private JButton stopButton;
private JLabel screen;
private Worker worker;
public Form() {
startButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
worker = new Worker(screen);
worker.execute();
}
});
stopButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
worker.cancel(true);
System.out.println(worker.isDone());
System.out.println(worker.isCancelled());
}
});
}
private void createUIComponents() {
rootPanel = this;
}
}
I tried to write same code with Tread, but it doesn't work too. And console output after click on stopButton:
true
true
So, worker have done, but program still continue show milliseconds. What is a post-death life? And in case of using Thread same thing: method isAlive() return "false".
Based on your code, it looks like you need a worker with a loop to keep running until the master thread tells it to stop running, which is done with worker.cancel(true);. The problem is that you are canceling it, but doing nothing to signal the loop itself to stop iterating. To fix this, you should change
for (; ; ) {
publish(String.valueOf(Calendar.getInstance().getTimeInMillis()));
}
to
while(!isCancelled()){
publish(String.valueOf(Calendar.getInstance().getTimeInMillis()));
}
Note the phrasing of 'isCancelled' from the java docs:
isCancelled()
Returns true if this task was canceled before it completed normally.
Since the loop never closes on its' own, it will never complete normally.
sorry to bother everyone.
Overall problem: I'm trying to open a dialogue box let the user enter something then close it
Issue: - A function is not being called (i think)
- The main problem is when i use debug it works fine so Its difficult for me to track down the problem
I'm having trouble with JButtons,
it works in debug but not in normal run. this was probably because i was using an infinite loop. someone online suggested i used SwingUtilities but that didn't work (at least i don't think.
/**
*
* #author Deep_Net_Backup
*/
public class butonTest extends JFrame {
String name;
boolean hasValue;
//name things
private JLabel m_nameLabel;
private JTextField m_name;
//panel
private JPanel pane;
//button
private JButton m_submit;
//action listener for the button submit
class submitListen implements ActionListener {
public void actionPerformed(ActionEvent e) {
submit();
System.out.println("Test");
}
}
//constructor
public butonTest(){
//normal values
name = null;
hasValue = false;
//create the defauts
m_nameLabel = new JLabel("Name:");
m_name = new JTextField(25);
pane = new JPanel();
m_submit = new JButton("Submit");
m_submit.addActionListener(new submitListen());
//
setTitle("Create Cat");
setSize(300,200);
setResizable(false);
//add components
pane.add(m_nameLabel);
pane.add(m_name);
pane.add(m_submit);
add(pane);
//last things
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
//submit
private void submit()
{
System.out.println("submit");
name = m_name.getText();
hasValue = true;
}
//hasValue
public boolean hasValue()
{
return(hasValue);
}
//get the text name
public String getName()
{
return(name);
}
public void close()
{
setVisible(false);
dispose();
}
public static void main(String[] args)
{
/* Test 1
boolean run = true;
String ret = new String();
butonTest lol = new butonTest();
while(run)
{
if(lol.hasValue())
{
System.out.println("Done");
run = false;
ret = new String(lol.getName());
lol.close();
}
}
System.out.println(ret);*/
//Tset 2
/*
SwingUtilities.invokeLater(new Runnable(){
#Override
public void run() {
butonTest lol = new butonTest();
if(lol.hasValue())
{
System.out.println(lol.getName());
}
}
});*/
}
}
Edit:
How its not working: When i run Test the program will print test and submit then it should change the hasValue to true. this will (hopefully) allow the if statement to run to print done. This does not happen.
Edit 2:
I have just added a few more lines for further testing 2 prints and this seems to have solved the issue (but this is bad)
System.out.println("hasValue " + hasValue); -> to the hasValue() function
System.out.println("set to true"); -> submit() function
You are doing something far too complicated than is necessary. Instead of having the listener as a seperate class, you could have it as an anonymous class. That way you can get a handle on the outer class (butonTest.this), and call any method you want on it.
m_submit.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
submit();
System.out.println("Test");
butonTest.this.close();
}
});
I'm not sure what you are trying to do with the infinite loop. It would have run to completion before you show the dialog anyway.
It would help to read up a bit on how Event-Handling works in Swing :)
I am afraid your constructor butonTest() and submit() method are out of your
class (public class butonTest extends JFrame).
you need to get them inside your class:
This question already has an answer here:
Loop doesn't see value changed by other thread without a print statement
(1 answer)
Closed 7 years ago.
Why this code do not stop when the while loop is empty. If I add an instruction the code work fine. Normally after the the user clicked an button the test variable will be changed so the loop will ends. Is there another way to test that the JDialog was disposed.
public class FenetreAjoutClass extends JDialog {
private JPanel pan = new JPanel();
private JPanel buttPan = new JPanel();
private JTextField schoolLevl = new JTextField();
private JButton valide = new JButton("OK");
private static String infos = null;
private static boolean test = false;
private JButton cancel = new JButton("CANCEL");
FenetreAjoutClass(JFrame parent, Boolean modal) {
valide.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
infos = schoolLevl.getText();
test = true;
dispose();
}
});
cancel.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
test = true;
dispose();
}
});
this.setLocationRelativeTo(null);
this.setResizable(true);
this.setLayout(new BorderLayout());
pan.setLayout(new GridLayout(1, 1));
pan.add(schoolLevl);
this.add(pan, BorderLayout.NORTH);
buttPan.add(valide);
buttPan.add(cancel);
this.add(buttPan, BorderLayout.SOUTH);
pack();
setVisible(true);
}
public static void main(String[] args) {
System.out.println(get());
}
public static String get() {
new FenetreAjoutClass(null, false);
while (!test) {
//System.out.println(test);
}
return infos;
}
}
The dispose will free up your memory. All data for the dialog are gone. If you want to show the window later again you have to work with visibility. This can be checked with isVisible().
You can replace the dispose() in your code with this.setVisible(false)
public static String get() {
FenetreAjoutClass dialog = new FenetreAjoutClass(null, false);
while (dialog.isVisible()) {
System.out.println("is Visible");
}
System.out.println("is not Visible");
return infos;
}
Mind that the console will still print "is Visible" over a short time after the dialog is closed. But this is because the console can does not print as quick as the while loop restarts.
I'm trying to figure out why the text field isn't updating. I'm aware that using SwingWorker will probably fix this problem, but I can't understand why it doesn't work in the first place.
public class waitExample {
private JFrame frame;
private JTextField txtLeadingText;
private String one = "update string 1";
private String two = "update string 2";
private String three = "update string 3";
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
waitExample window = new waitExample();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public waitExample() {
initialize();
}
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 450, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
txtLeadingText = new JTextField();
txtLeadingText.setHorizontalAlignment(SwingConstants.CENTER);
txtLeadingText.setText("leading text");
frame.getContentPane().add(txtLeadingText, BorderLayout.SOUTH);
txtLeadingText.setColumns(10);
JButton btnClickMeTo = new JButton("CLICK ME TO UPDATE TEXT");
btnClickMeTo.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent arg0) {
try {
updateOne();
Thread.sleep(1000);
updateTwo();
Thread.sleep(1000);
updateThree();
Thread.sleep(1000);
updateLast();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
frame.getContentPane().add(btnClickMeTo, BorderLayout.CENTER);
}
private void updateOne() {
txtLeadingText.setText(one);
}
private void updateTwo() {
txtLeadingText.setText(two);
}
private void updateThree() {
txtLeadingText.setText(three);
}
private void updateLast() {
txtLeadingText.setText("default text");
}
}
From what I understand, the default Thread will prevent any GUI updates. That shouldn't matter because I am setting the textField BEFORE the Thread.sleep.
Why doesn't the text field update? Shouldn't the text be set, then the Thread wait?
EDIT: As per the answers, the above code has been updated.
You are invoking Thread.sleep(1000); on EDT. This means that when your method will end - only then the repaint() will fire (at some point in time later).
Until then your GUI is freezed.
Consider that this is going on one thread (so processing is straightforward):
txtLeadingText.setText(one);
Thread.sleep(1000);
txtLeadingText.setText(two);
Thread.sleep(1000);
txtLeadingText.setText(three);
Thread.sleep(1000);
...
<returning from updateText()>
<processing other events on button click>
...
// some time later
<Swing finds out that GUI needs repaint: calls rapaint()>
This is what you should do (I didn't compile or test it):
public class MyRunnable implements Runnable {
private List<String> strsToSet;
public MyRunnable(List<String> strsToSet) {
this.strsToSet = strsToSet;
}
#Override
public void run() {
try {
if(strsToSet.size() > 0) {
final String str = strsToSet.get(0);
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
txtLeadingText.setText(str);
}
});
Thread.sleep(1000);
List<String> newList = new LinkedList<String>(strsToSet);
newList.remove(0);
new Thread(new MyRunnable(newList)).start();
}
}
catch(InterruptedException e) {
e.printStackTrace();
}
}
}
new Thread(new MyRunnable(Arrays.asList(one, two, three))).start();
It is hard to do in Swing but in contrast in dynamically languages (like Groovy) it would go as simple as that (you'll get a better grasp of what is going on):
edt {
textField.setText(one)
doOutside {
Thread.sleep(1000);
edt {
textField.setText(two)
doOutside {
Thread.sleep(1000);
edt {
textField.setText(three)
}
}
}
}
}
The GUI event loop updates the screen, but it can't update the screen until you return.
I suggest you avoid doing any blocking operations in the GUI event thread.
public class checkUsernames extends JFrame {
private static JTextArea textArea1;
private static JButton button1;
private static JScrollPane scrollPane1;
private static JTextField textField1;
private static JPasswordField passwordField1;
private static JLabel label3;
private static JButton button2;
private static JLabel label1;
private static JLabel label2;
public checkUsernames() {
initComponents();
}
public static void main(String[] args) throws IOException {
try {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
} catch (Exception e) {
JOptionPane.showMessageDialog(null, "Nimbus isn't available");
}
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
checkUsernames GUI = new checkUsernames();
GUI.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
GUI.setVisible(true);
}
});
String username = textField1.toString();
String password = passwordField1.toString();
Exception in thread "main" java.lang.NullPointerException
checkUsernames is the only class. When I try to run the application the program executes further (proceeding without String username & String password) without waiting for input. How can I fix this?
If you want the code execution to stop while waiting for input, make the JFrame a modal JDialog or JOptionPane instead.
Well invokeLater will invoke the code later. It dosent gurantee textfield1.toString() to execute after checkUserNames()
None of your private static members appear to be initialized at all. You won't get past the NullPointerException until you initialize each and every object you create before you use it.
I have no idea what you're talking about. You have to do something like this for all those objects:
private static JTextArea textArea1 = new JTextArea();
You aren't entering a username or password; you're creating a text area UI element that can accept them when you do enter them.
Why dont you use SwingUtilities.invokeAndWait() instead? This seems to solve your problem immediately.
Here is the simple example:
import javax.swing.SwingUtilities;
public class InvokeAndWaitExample {
public static void main (String[] args) {
try {
SwingUtilities.invokeAndWait(new Runnable () {
public void run () {
System.out.println("Hello World on " + Thread.currentThread());
}
});
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("Finished on " + Thread.currentThread());
}
}