I am wanting my error messages to display in a JLabel temporarily, then set the text back to "". But instead it looks like it just skips over setting the message. I've stepped through the code and found it's setting the text, but it isn't displaying for some reason. I've even tried the repaint() method, but still nothing. Any help would be greatly appreciated.
Here's what I have:
public void displayError(String msg){
int ctr = 0;
while(ctr<2){
try {
lblError.setText(msg);
lblError.repaint();
Thread.sleep(500);
} catch (Exception e) {}
ctr++;
}
lblError.setText("");
}
I'm assuming that you're calling this method on the event dispatch thread. (If not, you should be, since almost all Swing calls should be made there.)
You need to allow the thread to retake control, which it's not able to do because of your Thread.sleep(). Look instead at invoking a Timer or SwingWorker background thread which, after two seconds, will reset the text.
http://download.oracle.com/javase/tutorial/uiswing/concurrency/dispatch.html
Related
In a swing application, I have a popup jDialog which pops up with a jlabel that says "Hang on 5 seconds."
After 5 Seconds, the label should change to "Okay, now I'm done." And a button should appear allowing the user to click continue.
In the example action below (linked to a button which causes the popup), the popup appears as it should but it is blank instead of saying "Hang on 5 seconds." Then after 5 seconds everything updates and the labels are there and the button too. So what's going on? Is the thread sleeping before a repaint or something?
#Action
public void popUp() {
popUpDialog.setSize(300,200);
popUpDialog.setLocationRelativeTo(null);
popUpDialog.setVisible(true);
popUpLabel.setVisible(true);
popUpLabel.setText("Working, hang on a sec....");
try {
Thread.sleep(5000);
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
popUpLabel.setText("Okay Now I'm Done.");
popUpBut.setVisible(true);
}
EDIT: So I tried this, in an effort to use a swing timer in place of thread sleeping:
#Action
public void popUp() {
popUpDialog.setSize(300,200);
popUpDialog.setLocationRelativeTo(null);
popUpDialog.setVisible(true);
popUpLabel.setVisible(true);
popUpLabel.setText("Working, hang on a sec....");
Timer timer = new Timer(speed, this);
timer.setInitialDelay(pause);
timer.start();
popUpLabel.setText("Okay Now I'm Done.");
popUpBut.setVisible(true);
}
Obviously I'll need more code to finish the timer, but right off the bat I get a symbol not found, variable: timer error. What's that all about? Am I doing it wrong?
Edit 2: I changed the timer declaration and solved one problem but created another. Now I am getting the symbol not found error in regards to speed. I have never used a swing timer before and don't know how to use them. The java tutorial on the topic is convoluted and difficult to understand. Can any of you point me to a simple, clear example of a timer so I can learn from that and figure out what I need to do?
If your code modifying your Swing component's state is on the EDT here (it should be), then no repainting of the label with the first text will take place even if you do call repaint(), because all other EDT requests queued before the last repaint need to complete before you reach that repaint, and your code here is one of those queued EDT events.
If you call repaint, it adds a repaint to the queue, it doesn't repaint right away. Your actions here will result in a 5 second wait, with the label before the next repaint having only the text you last set it to (as code queued on the EDT is executed fully before going to what next is queued).
Try using a Swing Timer, events fired from the Swing Timer are already executing on the EDT, so it's pretty much what you need, one event here where you set the text initially, and another event fired by the Swing Timer to change the text after 5 seconds.
Edit, example of Swing Timer firing once, after 5 seconds as requested by author:
// set first jlabel text here
ActionListener task = new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("This is on the EDT after 5 seconds, " +
"well depending on if I'm used with a Timer, and if " +
"the right options are set to that Timer");
// set second jlabel text here
}
};
Timer timer = new Timer(5000 , task);
timer.setRepeats(false);
timer.start();
I have a popup jDialog which pops up with a jlabel that says "Hang on 5 seconds."
You have a dialog that is visible BEFORE:
you set the text on the label
the Thread.sleep()
The code following popupDialog.setVisible(true) is not executed until the dialog is closed. Reorder your code.
Also, you need to use a Swing Timer to schedule the changing of the text.
popUpLabel.setVisible(true);
popUpLabel.setText("Working, hang on a sec....");
should be
popUpLabel.setText("Working, hang on a sec....");
popUpLabel.setVisible(true);
and AFTER this you should set the dialog to visible.
You could also keep the order of your code as you have it now - and force the label / panel to update. Though this seems like less of a logical choice in this scenario
I have two basic questions.
I have a GUI project with Java Swing. When I put buttons on the frame and I double clicked them, I had the code of the actionPerformed, but it is blocked.
How can I put there a button and then use it on a actionListener?
My Project is about Server-client (multithread and sockets)
I call one method to reiceve one string that we can write on a JtextField and it stays on a while cicle with PrintWriter and a getOutputStream.
Something like:
do{
...
}while(thisstring!=null || thisstring!="exit")
So.. when I write something and press the button to send it, it stays on the cicle and the button blocks. How can I unblock the button to write something else?
Edit:
I understood the EDT problem, but I can't solve it.
I tried use the Timer but without success, something like that:
int delay = 1000; //milliseconds
ActionListener listener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
//My action calling the Thread class with the while cicle that has the PrintWriter
}
};
new Timer(delay, listener).start();
How can I handle this to do the timer when I press the button?
How can I stay on the that cicle (read the comment line) to send the information by OutputStream every time that one user enter something on the text field?
I know that for example for a console application I use a BufferedReader and then I use the ReadLine() to wait for anything sent from the console, but with GUI interface it freezes all time..
There is a fundamental concept in Java GUI development surrounding which thread in which the developer implements user-interaction processing such as button clicks.
In short, you need to perform your processing outside of the thread that calls your action handling method. This single thread is known as the Event Dispatch Thread (EDT), and if you have logic that runs much more than a few milliseconds, it will prevent the UI from continuing to draw things like the button releasing, etc.
You'll want to move your long-running, socket code off the EDT. Doing so will allow the button to release and let the user interact with other controls (or even the same button).
To avoid duplicating other discussions on the topic, I direct you to this pretty good one. Additionally, this article gives a short overview of threading concepts in Swing.
Regards,
ScottH
According to your comment you have some naming issues there. You need a class that implements the ActionListener-interface like so: class YourListenerClass implements ActionListener, but you could also do that via an anonymous class like new ActionListener {
public void actionPerformed(ActionEvent e) {
//your code for your button here
}
});
when you set your ActionListener.
The crucial thing is that you need to name your method the correct way. It MUST be public void actionPerformed(ActionEvent e) and you definitely have to implement the ActionListener-interface.
The next thing is that you have to register your listener in your button like:
yourButton.addActionListener(new YourListenerClass);
or
insert an anonymous class like I showed to you before.
The 2nd thing sounds like an multithreading issue like I mentioned in my comment. I didnt follow scotth's link, but according to his description this might be a source you want to read to solve any further blocking issues.
EDIT:
Well, at first I didn't want to explain it, because it's quite a chunk of code, but as the problem persists I want to add something about SwingWorkers in my answer.
If you have long running code, it wont help to use a Timer as the code invoked by it will also be on the EDT as it's triggered by an event.
Instead of that you could use a SwingWorker to solve this. This needs some extra code, though.
Here's a simple approach you could follow:
public class WorkingHard{
SwingWorker<String, String> worker;
JButton yourButton = ...;
...
//do some cool stuff, as register those listeners!
...
public void actionPerformed(ActionEvent evt){
if(evt.getSource().equals(yourButton);
// Construct a new SwingWorker
worker = new SwingWorker<String, Void>(){
#Override
protected String doInBackground(){
//do your reading in this method, it will be executed in an own thread
String readText = "i will be read".
/*your reading algorithm, you could also call publish(...) to post your results,
e.g. likewise), then you also have to override process(...). this process will be
thread save, too*/
readText += ... ;
...
return readText;
}
#Override
protected void done(){
try {
//do sth. with your result, now thread safe.
someGuiElement.setText(get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
};
// Execute the SwingWorker; the GUI will not freeze
worker.execute();
}
}
If you want to know more about those workers... there several threads dealing about it, e.g. this one.
I'm trying to accomplish something very simple. First, load my layout (main.xml). Then wait 1 second, modify an image, wait 1 second and modify it to a third image. (My end goal is more complex, of course, but I can't even get this to work).
Basically, I get a black screen when the app loads. It stays that way until all the waiting is over, then it shows the final image. Here's my code:
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ImageCard[0] = (ImageView)findViewById(R.id.imageView11);
Thread.sleep(1000);
ImageCard[0].setImageDrawable(getResources().getDrawable(R.drawable.secondimage));
Thread.sleep(1000);
ImageCard[0].setImageDrawable(getResources().getDrawable(R.drawable.thirdimage));
ImageCard[0] is the image I'm trying to change. It loads in main.xml and shows fine if I remove the rest of the code.
If I change the sleep time to 5000, it then takes 10 seconds before it finally comes away from the black screen and shows the third image. This is how I know it's not just loading slow, but that it's actually waiting.
It's like it's not running sequentially. I'm no java expert, so I'm assuming I'm doing something dumb...
Thanks for any help!
I think you are blocking the UI Thead. Try Handler.postDelayed on a static Handler object.
Ok heres your problem, you can never do a sleep(...) when you are in the UIThread. The UIThread is never suppose to be locked up, it causes a lot of very bad things to happen in android. But there is a very easy way around it, just get off the UIThread and hop back on it when you need to. Heres what i would recommend:
public void onCreate(...)
{
super.onCreate(...);
myActivity.setContentView(R.layout.main);
new Thread(this).start();
}
public void run()
{
try
{
changeLayout(R.layout.main2);
Thread.sleep(5000);
changeLayout(R.layout.main3);
Thread.sleep(10000)
changeLayout(R.layout.main4);
}catch(Exception e){}
}
public void changeLayout(int id)
{
this.id = id;
myActivity.post(new Runnable()
{
public void run()
{
myActivity.setContentView(id);
}
});
}
private int id;
Of course with this example your class must implement Runnable to work. Only the UIThread can access the UI, no other thread can. Thats why you have to hop on and off the UIThread. Hope this worked!
Try adding ImageCard[0].invalidate() when you want it to draw.
I think Hovercraft Full of Eels is pointing you in the right direction. Essentially, you're not doing any multi-threading, you're telling the main thread to wait which means that it never completes the drawing. I'm not sure about Android, but Swing uses double-buffering by default (to avoid screen flashes), but that means that what is drawn, is actually drawn on to a buffer, not the window itself which is why you don't see anything. You could try disabling the double buffering (which Android is likely using) but that could cause other issues.
You might want to actually do multi-threading, or, I'm sure Android likely has a Timer component. If it does, I'd suggest you use it over Thread.sleep or actual multi-threading. Using a Timer you can have it fire an event after one second. That event will execute the other code.
do you have that code in constructor or in init() function? if yes, draw just the first picture and the Thread.sleep() function move after the place which the constructor or the init() function was called from.
then call repaint() function or something.
I have function like this in Java Swing app. I need after click on button call many function in intervals and in cycles. Function must be called inside jbutton because I have some global parameters in View that are used in jbutton function. Can you please help me how can I create time delay between calling functions and how to display remaining time in jLabel?
private void jButton1MouseClicked(java.awt.event.MouseEvent evt) {
statusMessageLabel.setText("Proccess started.");
for(int i=0;i< cycles;i++) {
//display remaining time
jLabelTimer.setText("00:09:59");
// after time call many functions and then go again
manyFunctions();
} catch (Exception e) {
System.out.println(e);
}
statusMessageLabel.setText("Proccess ended.");
}
}
I agree with Howard's recommendation that a Swing Timer could work well here (1+), but my other concern with your code is here:
manyFunctions();
What exactly is going on at this spot? Are you calling lots of code that is time/cpu-consuming? If so, you will need to take care not to call this on the main Swing thread, the EDT, but rather call it in a background thread, but at the same time taking are to update Swing components only on the EDT. This can be simplified by using a SwingWorker, and you can read up more on this here: Concurrency in Swing
It sounds like you want to have a look at swing timers. With those you can schedule single calls or do them periodically.
This way you can also add a timer which resets your label text periodically.
Since I'm not a CS major, I'm having some difficulties translating my programming wishes into an actual program.
What it basically boils down to is the following: how can I alternate an image on a label, showing each image for an amount of tim specific for each image.
So: say I've images A and B; I'd like the user to see A for 1000ms and B for 200ms. This keeps on looping until a user presses a certain key.
Now, I'm able to load an image onto a panel, quite easily even, and I've managed to catch user input using KeyListener and stuff, which all works quite nicely and alot easier then I had expected. I also know how to use looping constructs like while, for and do..while, but this timer business is shady.
I see all kinds of stuff using threads and what not, I really don't need that. This is not about efficient programming or good code, it's simply about demonstrating something.
Any help would be greatly appreciated!
Use a SwingWorker<Void, Void>. The doInBackground method of the SwingWorker should look like this :
#Override
protected Void doInBackground() {
try {
while (true) {
displayImage(imageA);
Thread.sleep(1000L);
if (isCancelled()) {
return null;
}
displayImage(imageB);
Thread.sleep(200L);
if (isCancelled()) {
return null;
}
}
}
catch (InterruptedException e) {
// ignore
}
return null;
}
private void displayImage(final Icon image) {
SwingUtilituies.invokeLater(new Runnable() {
#Override
public void run() {
// display the image in the panel
}
});
}
The keylistener should simply cancel the SwingWorker.
Here's something that might be a good example:
http://www.java2s.com/Code/Java/Development-Class/UsejavautilTimertoscheduleatasktoexecuteonce5secondshavepassed.htm
I can try to explain the code if it appears confusing
There is nothing necessarily inefficient about using threads when threads are the right tool for the job.
In this case, it would not be unreasonable to create a new class that implements Runnable, which holds a reference to the label you wish to change the image on.
This means that the image could be changed without causing waits on the main application that would cause it to hang until it was done.
You would want to avoid 'Busy Loops' [basically, a while loop with no Thread.sleep() within it], and look to see if there is any needed thread exit criteria