I am trying to use Swing Timer and I wanted to start from a very simple program. I have a window with text: "You have n seconds", where n changes from 10 to 0 every second.
I know how to generate a window with text. And I understand how Timer works (it starts an action periodically). But I cannot figure out how to combing this two things. Should I use that: JLabel label = new JLabel(myMessage); and then with timer I need to update the "myMessage" variable?
But I think I need to "force" my window to "update" itself (to display a new value stored in "myMessage").
I suggest you to call the JLabel#setText method each time content is updated. however, due to the very monothread nature of Swing, you have to update its widgets in the so-called Event Dispatch Thread (EDT). To do so, consider calling SwingUtilities.invokeLater or SwingUtilities.invokeAndWait in your timer code.
This way, when text will be changed due to your call of setText, events of JLabel will propagate correctly, and label will be correctly refreshed.
Hi bro use observer pattern . That is ,your ui class sould be listener of your timer structure.When your variable changes ,invoke the listeners of your timer which is your ui class.
//your observer class
update(Object obj){
label.setText(obj.toString());
}
...
//your observable class
//when timer changes varible's value you should call invokeListeners()
invokeListener(){
for(Listener listener :listeners)
listener.update(getSecond());
}
I dont know your class and structure.But i used this solution in one of my assignments.
Related
In my program, I need to wait for the user to input from a JFrame. When the user is done with the first input they press a JButton. This calls a constructor for a Class I made: HumanTrainer. In the constructor I need the user to have more inputs. I made two functions to wait and notify. But when the code gets to wait, everything freezes, and the JFrame doesn't update to what it should.
This is the action the first button preforms
startingButton.addActionListener((e)->{
Trainer[]t=new Trainer[2];//HumanTrainer extends Trainer
String[]names=new String[2];
for(int a=0;a<2;a++)
names[a]=((JTextField)(startingInputs[2][1+a])).getText();
grid.removeAll();//The JPanel that the Frame has
Frame.repaint();//The JFrame
Frame.validate();
if(isHuman[0])
t[0]=new HumanTrainer(names[0],grid,Frame);//The constructor
if(isHuman[1])
t[1]=new HumanTrainer(names[1],grid,Frame);
});
And the constructor for HumanTrainer
HumanTrainer(String name,JPanel grid,JFrame Frame){
super(name);
GridBagConstraints manager=new GridBagConstraints();
manager.gridx=0;
manager.gridy=0;
manager.gridheight=1;
manager.gridwidth=1;
manager.fill=GridBagConstraints.HORIZONTAL;
Font Format=new Font("Courier New",Font.PLAIN,14);
JButton cont=new JButton("Continue");//This is the button that when clicked should run the function that notifies
grid.add(cont,manager);
grid.repaint();//One of these four things SHOULD change the view of the frame
grid.validate();
Frame.repaint();
Frame.validate();
System.out.print("TEST");//This prints
cont.addActionListener((e)->{
made();//This is a function contained in HumanTrainer that only calls notify();
});
make();//This is a function contained in HumanTrainer that only calls wait(); With the proper try and catch
}
But when starterButton is pressed the screen freezes and doesn't update so that cont can be pressed.
Start by taking a look at Concurrency in Swing. Swing uses a single thread to dispatch it's events from, if you perform any long running or blocking operation from within the EDT (like calling wait), then it freeze your program and the user will have to terminate it.
You have two basic choices. You can either use a modal dialog to gather information from the user, see How to Make Dialogs, which will block the execution of the code at the point they are displayed, without blocking the entire EDT OR use a observer pattern, which can generate notifications that the user has provided what ever information you are expecting.
To be honest, a modal dialog is generally easier and can help prevent unexpected side effects
This...
make();//This is a function contained in HumanTrainer that only calls wait(); With the proper try and catch
would seem to be the core of your problem, but without more information and context of what you are trying to do, it's impossible to really suggest what you should do, however I'd recommend having a look at model-view-controller and seperare your code into more appropriate layers
First of all, you may want to close that for loop with {} so that it doesn't loop the whole code twice. Also you should check if wait() and notify() work correctly by individually testing them without java awt.
I have a JTable, where a user can select a single row. If that happens, i want to "highlight" another part of the page for a short time to indicate that this is the part of the page that changed after the user interaction.
So my question is: What's the best way to achieve this? At the moment i did it by setting the background color of that panel and starting a SwingWorker which sets the Color back after a short delay. It works as intended, but is it a good idea to use a SwingWorker like that? Are there any drawbacks to that approach? How would you solve this?
Thanks in advance.
I guess a Swing Timer would be a better option as it reuses a single thread for all scheduled events and executes the event code on the main event loop. So, inside your SelectionListener code you do:
// import javax.swing.Timer;
final Color backup = componentX.getBackground();
componentX.setBackground(Color.YELLOW);
final Timer t = new Timer(700, new ActionListener() {
public void actionPerformed(ActionEvent e) {
componentX.setBackground(backup);
}
});
t.setRepeats(false);
t.start();
I recommend a swing Timer (javax.swing.Timer). (do NOT use the Timer class in Java.util)
This is where you make the timer:
Timer t = new Timer(loopTime,actionListener)//loopTime is unimportant for your use of this
t.setInitialDelay(pause)//put the length of time between starting the timer and the color being reverted to normal
t.setRepeats(false);//by default, timer class runs on loop.
t.start();//runs the timer
It probably makes sense to hold on to a reference to the timer, and then just call t.start when you need it.
You need to implement an action listener to handle the timer events. I can edit this if you don't know how to do that, but as you are already doing stuff with Swing I figure it shouldn't be a problem.
I'm really new to Java, especially working with GUI in Java.
I want to put a progress bar in my program, where it updates its value each time after certain amount of work has been done. Right now I have a button that executes a method when pressed, and I put setValue() function (with the value that I want) each time after certain work has been done in that method. However, when I press the button, the button seems to be stuck pressed while the method continues (the method takes a while to finish executing), and the progress bar doesn't get updated until all the other things has been done in the ButtonListener, so it goes directly to 100% after it's done).
What am I doing wrong?
Thanks in advance.
That is, most probably, because you are doing all work in main thread so it hangs your UI until all work is done. You should not do this. You should use separate EDT for such operations. What you should try is do your update progressBar job in separate EDT. Use SwingUtilities.invokeLater(Runnable r) for this.
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.
Is there anyway that I can control the order in which events are fired in my Swing application?
For example, I have a MouseListener and an ActionListener for a component. Can I make it so the MouseListener always fires before the ActionListener?
Seems to me if I add the MouseListener before the ActionListner, I am just praying that they will fire in that order.
Now I understand that coding this way is bad practice and that you should not count on the order of events firing, but for this situation I am encountering, it is a must.
Thanks
If you have an action triggered off of a one listener that needs to happen before the other then change your logic.
Either combine the listeners so that a single listener gets both events and holds onto one temporarily if needed. Or only add one listener and have it call the appropriate method or create a new event after it finishes.
Wrap the ActionListener code in a SwingUtilities.invokeLater(...). The code will be added to the end of the EDT.
I would still have both listeners in the same class so the dependency is well documented.