I'm having a problem..
In my code I have it so that text should output to a JTextField. when I run the program, it doesn't. However, if I directy after my code for putting text into the JTextField put a JOptionPane then it works...
Anyone have an solution to make the JTextField update without having the JOptionPane after?
My code:
// Works:
JTextField.setText("String");
JOptionPane.showMessageDialog(null, "String");
// Doesn't Work:
JTextField.setText("String");
//JOptionPane.showMessageDialog(null, "String");
There are two reasons why this might fail:
You're calling setText() from outside the main (Swing) thread
You're calling setText() from in the main (Swing) thread
In the first case, wrap the call in SwingUtilities.invokeLater().
In the latter case, you set the text but you're blocking the Swing thread, so the change can't be rendered. You will need to create a background worker to do the work and use SwingUtilities.invokeLater() to update the text field from your worker thread.
[EDIT] See the Swing tutorial for an example how to use background thread and how to update the UI from there: http://download.oracle.com/javase/tutorial/uiswing/concurrency/interim.html
Why not just use repaint() after the text update?
If memory serves me right that should address the issue of the text not appending.
Related
I'm wanting to get rid of the text that is already set in my JTextField when I click inside the JTextField (focus on the JTextField).
Here's my code:
if (newSerial.isFocusOwner())
{
newSerial.setText("");
}
How do I get this code to run whilst I still have my JOptionPane.showMessageDialog running?
I'm not sure if I understand exactly what you are trying to do, but based on my interpretation of your question, you have a text field that you want to update while a JOptionPage message dialog is displayed.
JOptionPane dialogs block the Swing Event Dispatch Thread (EDT), so you can't update the UI while they are being displayed, unless you do it from a different thread (but that's not great - Swing components should be updated on the EDT). If I read your question correctly, the easiest option might be to replace your JOptionPane.showMessageDialog(...) can with a JDialog that isn't a modal dialog, and therefore, won't block the EDT.
Inside the actionPerformed method of a jButton, I have the following code:
btnLogin.setText("Logging In...");
btnLogin.setPreferredSize(new Dimension(110, 29));
btnLogin.setEnabled(false);
//more stuff here, irrelevant to this
This works, however it only takes visual effect (is repainted) once the method is complete.
If in the //more stuff here area I have code that takes a long time to complete, the effects of the btnLogin changes do not take effect until that code is complete.
I have tried typing:
this.revalidate();
this.repaint();
Directly after the first 3 lines, and multiple other solutions, to try to force the damn thing to repaint DURING the method, but no matter what, it only happens at the end!
Another thing I've noticed is that if I call a JOptionPane in the middle of the method, the frame WILL repaint (in the background), so that's interesting.
What is is that's automatically happening in the end of the method that I need to call to make it happen during the method?
Thanks in advance!
You're blocking the Swing event thread with the long-running code, and this prevents Swing from drawing the text changes. The solution:
Do the long-running code in a background thread such as in a SwingWorker's doInBackground method.
But make sure to make most all Swing calls on the Swing event thread.
Read the Concurrency in Swing tutorial to learn the details on the Swing event thread and threading issues.
I had this question while setting a JLabel visible when a button is clicked it is like a loading icon. The p.make() method is executed but the Label is still invisible after the Method returns the Label is visible.
Can someone explain what is happening?
ActionPerformed:
String[] args = {jTextFieldDrgzusatzVariable.getText(),jTextFieldAusgabe.getText(),"C:\\CPOracle",jTextFieldKatalog.getText()};
this.jLblLoading.setVisible(true);
if(jLblLoading.isVisible()){
try{
new P21Make(args[0],args[1],args[2],args[3]).make();
}catch(Exception e){
e.printStackTrace();
}
}
The reason is very simple: Swing is single threaded (see the Swing concurrency tutorial for more information).
What happens is that the actionPerformed method is called on the Swing thread (the E(vent)D(ispatch)T(hread)). When the
this.jLblLoading.setVisible(true);
statement is reached, it will immediately mark the jLblLoading as visible. However, this has no effect yet on the UI. The UI needs to be repainted before the change in visibility has any effect. This repaint is scheduled on the EDT (which is not the same as immediately executed).
This explains why your
if(jLblLoading.isVisible()){
check succeeds, and you still do not see the difference in the UI. The component is marked as visible, but the repaint is still pending. The repaint will remain pending until the EDT becomes available again. Since the thing that is currently occupying the EDT is your actionPerformed call, the rest of the code in that actionPerformed method will be executed before the repaint (meaning before you see a change in the UI).
Your solution using a different thread can indeed fix this. You can however only use that if the new P21Make(...).make() does not affect the UI. If that statement interacts with Swing components in any way, it should be executed on the EDT. In that case, an alternative is to wrap the statement in a SwingUtilities#invokeLater call.
You should probably look at using SwingUtilities.invokeLater to allow actions which modify the gui to complete.
http://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html
I am writing a socket programming. It has GUI for server and client. In the server GUI there is a textfield which shows the word requested by user.
But I am having problem in showing the word.
I have tried
txtWord.setText(sentword);
It is not showing the word in the textfield. But when I write this
txtWord.setText(sentword);
JOptionPane.showMessageDialog(null, "the requesed word is: "+sentword);
then it shows the word in textfield and also shows it in the messagebox.
I have tried repaint() but it dint work.
Please suggest me some solution as soon as possible
as #Binyamin Sharet correctly commented, you have a Concurrency in Swing issue.
your Swing GUI doesn't care about long and hard tasks you're running in the background
even JTextField#setText() is declared as thread safe, output from Socket (i.e.) by default never notified Event Dispatch Thread
correct way could be to use a SwingWorker that has been created specifically to run long and hard tasks background to the Swing GUI and output to the GUI on event thread or EDT
or even easier is to use a Runnable in a Thread but making sure that all output to the Swing GUI is queued on the Swing event thread by placing it in a Runnable and calling it with invokeLater()
A dirty hack is to wrap code lines like so:
txtWord.setText(sentword);
JOptionPane.showMessageDialog(null, "the requesed word is: "+sentword);
into invokeLater(), but in this case your GUI will be unresponsive to Mouse or Keyboard events until Socket (in your case) ended
txtWord.requestFocus();
textField does not show up until the window is over the textField and back or it gains focus, until Clicking on it. So... just request focus.
Also if check the text size if you had set while creation.Sometimes text not displayed if there is mismatch in size
eg: txtWord.setSize(200, 24);
I am currently making this text-based rpg game with a simple GUI. I was happy to find the good start at it but then there is something I stumbled upon that made me stop coding for a while.
If you are making this in console, you could easily use this code to pause the movements of the characters for a while, like:
System.out.println("[enemy]");
Thread.sleep(1000);
System.out.println("The local guard waves his sword and tries to stab you in the back, but you quickly parried and tried for a counterattack but you failed.");
If you are doing this on a JTextArea, you'd use the setText but
if you use Thread.sleep it doesnt work and coding setText again, would erase the old text and replace it with the new text, so the records of the fight will not be fully displayed on the game. Is there a way to fix this?
You can use append to append instead of replace. That is the easy part.
The hard part: You have to change your program flow. In Swing there exists a single thread for dispatching GUI events, the event dispatching thread. You should not set the EDT to sleep or do any other long-running operations in it. This will freeze the GUI, it can't respond to anything and will not repaint.
Instead you should either start a new thread for the logic flow and dispatch operations that have to be executed on the EDT (everything that manipulates the GUI) with SwingUtilities.invokeLater or, in this case maybe better, SwingUtilities.invokeAndWait.
Or you should embrace an event driven control flow, e.g. you could use a Timer to output the second text later.
A program flow that works well with single-threaded console programs is not the right approach for multi-threaded GUI applications (and every GUI application is automatically multi-threaded).
for the setText part, you should have a variable which will hold the text and when you want to add a string, you append it and set the text again:
String text ="[enemy]";
textfield.setText(text);
text+= "\nblablabla ..";
textfield.setText(text);
UPDATE:
Some are suggesting to use the append method which is relatively good. Sometimes in the game you would like to append and sometimes replace the whole text (a new character talks), I would recommend something like this:
textfield.setText("[enemy]\n");
textfield.append("blablabla");
//When someone else wanna talk:
thread.Sleep(1000);
textfield.setText("[me]\n");
textfield.append("moreblablabla");
You could also use append() function. See JavaDoc.
jTextField.append("Foo\n");
jTextField.append("Bar\n");
You can use append() instead of setText(). Method append() will append new text at the end of the old text.