As I wrote in title,
I want to drawLine additionally when Timer generates events.
Line will be draw like
first time;
ㅡ
second time;
ㅡ
ㅡ
I want line will be added on before's maintained situation
If first purpose cannot be done, (because I'm not good at Java yet, that's just my idea) I want to draw N line in Nth events then i redraw new N+1 line in (N+1)th events.
Which could be done in Java?
P.S. How to stop the Swing Timer?
You'll basically have to (not in order):
Build an event to happen on each tick of the timer
Pass it to a new timer (stopping the timer is in the documentation)
Set some sort of incrementing counter, either coordinate-based or tick-based
Override the paintComponent method in a component to draw the lines, based on the incrementing counter
From inside the event, call repaint() on your component (will happen on each timer tick)
Work on each one of those tasks individually, and when you feel you've mastered each one, you can try putting them all together.
Related
So, I have an object that extends JPanel and displays dots in a matrix via paintComponent. The dots of the matrix can move, disappear or multiply given certain conditions, and I want to show their evolution over time automatically like so:
for(int i = 0; i < 100; ++i){
matrix = calculateNextMatrix(); //Calculate possible movements, deaths or births of dots
myGraphic.updateMatrix(matrix); //Pass new dots to the JPanel object
myGraphic.repaint(); //Draw new dots
Thread.sleep(100); //Wait 0.1 seconds for next iteration (yes, this should be in a
//try-catch)
}
However, I only get drawn the last iteration after the loop is finished, and all the previous calls to repaint() are basically ignored. If I do the iterations only one at a time (for example, via a manual button press), I have no problem.
Is there any way to get multiple, periodic repaint calls automatically?
I had a simile problem with JComponent in my library and I found a solution with swing timer, I reported the java description of timer
In general, we recommend using Swing timers rather than general-purpose timers for GUI-related tasks because Swing timers all share the same, pre-existing timer thread and the GUI-related task automatically executes on the event-dispatch thread. However, you might use a general-purpose timer if you don't plan on touching the GUI from the timer, or need to perform lengthy processing.
You can use Swing timers in two ways:
To perform a task once, after a delay.
For example, the tool tip manager uses Swing timers to determine when to show a tool tip and when to hide it.
To perform a task repeatedly.
For example, you might perform animation or update a component that displays progress toward a goal.
I think you are in one of this cases.
Without a minimal example reproducible, I can use the my code.
You should create the Swing action listener, like this:
public class UpdateComponentListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
count += 10;
timeLabel.setText(count + "");
//The label call repaint
//in your app you should be call the repaint
//In your cases
/*
matrix = calculateNextMatrix(); //Calculate possible movements, deaths or births of dots
myGraphic.updateMatrix(matrix); //Pass new dots to the JPanel object
myGraphic.repaint();
*/
}
}
The timer constructor get in input the delay and the action listener, so you can build your timer, with this code:
Timer timer = new Timer(1000, new UpdateComponentListener());
timer.start();
You can stop, restart your timer, so you should be set how propriety the timer.
The GUI example:
I wrote the post and after I see the #camickr comment. I post the answer because my work is finished but, the comment answered your question.
I hope to have to build a food example
I am about to write an animation in which a character on a JPanel moves left/right when the user presses (and holds) the appropriate keys.
Now, since I am new to concurrency I want to ask : should the code handling the animation (namely the method that will move and repaint the character as long as the key is held) be executed on a worker thread or the event dispatch thread ?
I read the tutorials on concurrency in swing, and it seems that stuff that changes the components (in this case it's painting JPanel) should be on the event handling thread, but on the other hand that would freeze all the other events as long as a key would be held right ?
For example a user won't be able to pause the game while he's holding the go-left key, if I understand this correctly. So which approach is correct and why? Or maybe there is totally different way to make such an animation ?
Thank you in advance!
All the Drawings Paintings need to be done on EDT thread. Never on any other Thread . Use
SwingUtilities.invokeLater() .. for your painting. You can do calculations like what will be the next postion of your character on Worker Thread. You won't have any unresponsiveness if you are doing creating and using Swing Classes on EDT. just Make sure that your computation is not too long. For Animation whenever you find the next positon of your Character just call
SwingUtilties.invokeLater to update changes on UI
I have the following scenario: If I have a while block in the paint() method (used for example to simulate a simple animation such as rotating a polygon, done by multiple drawing and erasing the figure), is there a way to break the while block, when clicking the mouse inside the applet?
The animation of the polygon is done without recalling the paint() method. Also would it be possible to do so if the while block looked something like this:
while (count<n)
{
//code that draws the polygon rotating
count++;
}
Yes there is a scenario to hold on your while loop.
The simpliest way would be to set up a variable in your classfile private boolean stopLoop=false and within your while loop check for this attribute while (!stopLoop).
Now the MouseEvent just set the attribute stopLoop=true and you are done (if you need help, here you are How to Write a Mouse Listener
The other solution is using Swing Timer as mentioned by #camickr (see other answer). Lets assume you have a general Timer method outside your paint() method. Then you sould't use a while loop in there. I would suggest to just paint a static picture and if you want that your poligon rotates, just draw the next one, but with another angle and so on.
The idea is that you cut out your while loop into the Timer method so paint() gets called a lot of times. If you want to stop the poligon from circling around use a boolean flag for it or stop the timer. In the first case you can handle more then one polygon and each of them can be started and stopped, if you handle the boolean variables and the mouse event correct.
If you have further questions please add some more detail, or bedder show us some minimized code.
Don't use a while loop.
Instead use a Swing Timer to schedule the animation. Then you can simply start/stop the timer as required.
I need a variable countdown timer for between 1-10 seconds, that can be stopped and restarted. What's a good set of UI elements to use for this? I need something intuitive that uses a fairly small amount of screen real estate, comparable to a normal-sized JButton. A windup kitchen egg timer would be the best physical analogy:
NOTE: I know how to implement timers and restart them, I just need to figure out what UI elements to use.
NOTE 2: I need a variable countdown timer. If the user wants 1 second, I want a 1 second timer. If the user wants an 8.2 second timer, I want an 8.2 second timer. The kitchen timer above is simple, the user just turns it to a certain amount and lets it go.
Why not use a JProgressBar that starts off "full" and empties as the time decreases? You overlay the remaining time in seconds over the bar, therefore avoiding using additional screen real estate.
For a short term solution I used a JSlider... I add an ActionListener to its BoundedRangeModel, and set my timer when there is a change and the BoundedRangeModel.getValueIsAdjusting() returns false. When my timer counts down but is not yet expired and the BoundedRangeModel.getValueIsAdjusting() returns false, I call BoundedRangeModel.setValue().
Not too happy with it but it kinda does what I want.
A (ridiculously) simple solution: if you don't need too much graphical flair, just use a single JButton that displays the seconds remaining when the timer is running. When the timer's off, it displays "Start"; clicking it will begin the countdown. You could then stop (or pause) it by clicking when the timer is running.
It is fairly simple... Labels and buttons should be fine.. Here are some examples
(source: itblogs.info)
(source: softpedia.com)
(source: leancrew.com)
I'd use a JSpinner for the setting; a javax.swing.Timer for the counting; and a single button, labelled "Start" or "Stop" as a function of the Timer state. Almost anything would do for display, but #Adamski's JProgressBar idea has appeal.
I'm using the java swing library to develop a board game called DAO.
The problem is that after the human player makes its move, by clicking on the JButton with the piece image that he wants to play, I call the computer AI routine but inside the mouse event function. By doing this only when the function returns, the computer ends its turn, do the JButtons refresh their Images (setIcon comes in).
I'd like to know how can I force the JButtons to change their image at the moment they are clicked and not only when the mouse event function ends (as I need to handle data inside it).
I've tried all of this
myButtons[i][j].setIcon(xIcon);
myButtons[i][j].revalidate();
myButtons[i][j].repaint();
myButtons[i][j].validate();
None worked.
Thx in advance
You may want to try putting the action performed upon clicking the JButton into a Swing worker. This will allow the task to go on in the background, while the user can still click other buttons, etc.
See http://java.sun.com/docs/books/tutorial/uiswing/concurrency/simple.html.
There is a single thread used for all Swing activity.
Here's the process.
One event appears on the event queue
it is pulled from the queue and executed by The AWT Thread
Any new events created while this is executing are placed on the queue to be held until the currently running AWT event returns.
The event executing returns and the next event on the queue is dequeued and executed.
This means that if you need to do anything that takes more than, say 1/100 of a second or so, you shouldn't do it any thread started from a swing event. Instead, spawn your own thread and return the swing thread to the system so the GUI can be updated.
Now, your thread MUST NOT update any GUI objects! If you need to update a GUI object, use invokeLater to place your code back on the AWT thread.
New Java programmers not conforming to this rule and executing tasks on the AWT thread is almost certainly the biggest reason people think Java is slow.