Right now, the object moves a certain increment each time I manually click a button, but its actually suppose to move on its own across the screen on its own once the button is clicked. I tried calling timer.start(); various times in my code. As well as, setting up an 'if' statement in the actionPerformed method that checks for a button being pressed and then calls timer.start() as a result. But, it didn't get the object to move on its own.
Can anyone lead me in the right direction? Am I not writing the code right? Or is does this problem have something to do with java swing timer.
PS. I am new to java,
And this is part of my code :
public void actionPerformed(ActionEvent e){
if (e.getSource() == rightBtn) {
objXpos += objMoveIncrement;
direction.equals("Right");
}
if (e.getSource() == leftBtn) {
direction.equals("Left");
objXpos -= objMoveIncrement;
}
repaint();
}
}
**edit
the timer is suppose to start once a button is clicked, and the timer is what allows the object to move across the screen
this problem have something to do with java swing timer.
No.
Am I not writing the code right?
That would be the problem.
the timer is suppose to start once a button is clicked
And how does the Timer stop? What happens if you click "right" and then "down"?
Without knowing the exact requirements it is hard to give an exact solution.
So I would suggest that one solution is to just start the Timer when your program starts.
Then in the ActionListener for each button, you change the direction.
Then when the ActionListner for the Timer is invoked, you simply move the object based on the current direction and then repaint the object.
Generally you would use Key Bindings for something like this. So when you press a key you start the Timer and when you release the key you stop the Timer. Check out the Motion With Key Bindings example from Motion Using the Keyboard for a working example of this approach.
Related
I am working on a Chess game in JavaFx and I have gotten to the first part of player interaction where I must detect which chess 'piece' the player selects.
After researching for 3-4 days on how to handle mouse click in Javafx I have found the solution to be akin to the sort of,
scene.addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {
public void handle(MouseEvent event) {
//code here
}
});
Although this block of code works for detecting mouse click and handling it, my program does not run exactly as I intend.
https://imgur.com/a/DIcmKIL)
As you can see from the output of the program in the photo above, the println "Passed" gets called before the program waits for the mouseclick event, which prints out the x location of the mouse.
So I was wondering, how can I make the rest of the program wait for a user for a mouse event?
My attempts:
I have tried a while loop where I looped the addEventHandler listener until the getX value was of a certain value, but when I had implemented the while loop my scene would not render, the scene would just be white.
Any help is appreciated
I'm trying to create a desktop program to move the mouse until I press for example the letter "q" in java.
I've created a window (JFrame), when I press a buttom the mouse start to move.
My doubt is related to this part:
while (true) {
for (int j = 1500; j <1600; j++) {
robot.mouseMove(j, 0);
robot.delay(100);
}
}
How can I stop this infinit loop by pressing a letter?
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_Q) {
System.exit(0);
}
}
why this is not working?
(I need to press a letter because the mouse, while the program works, is unusable)
Thanks in advance.
First, you might have to let go of the event handler.
If this while(true) is ran on the awt event queue, you are hogging the whole GUI and no wonder it is not responsive; no other event can be fired until you return from the mouse event.
Can you give more code? This is not enough to explain the behavior.
You would probably need to launch a thread to perform this work.
UPDATE:
instead of calling synchronously your JavaRobot(); method, you will need to run it in a thread. Ugly hacked version for testing:
(new Thread(() -> JavaRobot())).start();
The cleaner version would likely save thread in a variable so you can interrupt it with another button. You can also go nuts with the executor services apis if you prefer not handling threads yourself yet still run tasks in threads.
Through some searching, I made about ActionListeners and GUI. I think I have come to a conclusion that all the changes you do that affect the GUI, in the ActionListener, actually happen when ActionListener comes to it's end
I am currently making a memory game. In the action listener of a card button I first flip the image (that changes it's icon) and the I check if a have a match and in the case I don't have one I close the card(change icon).
Since those two happen in the same actionListener as a result if I dont have a match I only see the first card I pick and he second seems to no react to flip.
Sorry if it's confusing how I explain it. I think that the problem is the actionListener but maybe I am wrong. What would you suggest?
c.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent ae){
selectedCard = c;
String imgName = "Images/"+c.getId()+".jpg";
URL imageURL = this.getClass().getResource(imgName);
if (imageURL != null) {
ImageIcon icons = new ImageIcon(imageURL);
c.setIcon(icons);
}
c.setEnabled(false);
c.setDisabledIcon(c.getIcon());
pl.singlePlay(c);
if(pl.getMatch()==false){
for (Cards cd : cards){
if(cd.getMatched()==false){
cd.setEnabled(true);
cd.setIcon(icon);
}
}
}
});
I have come to a conclusion that all the changes you do that affect the GUI, in the ActionListener, actually happen when ActionListener comes to it's end
Yes, all code invoked from any listener executes on the Event Dispatch Thread (EDT). This thread is responsible for updating the GUI and so the GUI can't be updated until the code has finished executing. Read the section from the Swing tutorial on Concurrency for more information.
Since those two happen in the same actionListener
If you want to schedule animation, that is show one Icon and then seconds later show another Icon, then you can use a Swing Timer. The Timer allows you to schedule another event. The tutorial link from above also has a section on How to Use Swing Timers to get you started.
I'm a little bit new to Key Bindings, as I have been using KeyListeners for the majority up until recently when KeyListeners proved to be my biggest obstacle. I'm wondering how you would program a keyReleased-like event with KeyBindings. KeyListeners provided the easy three methods: keyPressed, keyTyped, and keyReleased, but I'm a little bit confused as for how to make this happen with Key Bindings.
Basically, when the user presses UP, I want an object to move upwards. But when the user releases UP, the object should move downwards automatically to simulate basic gravity. Here's a little bit of my code showing the UpAction class.
class UpAction extends AbstractAction
{
public void actionPerformed(ActionEvent tf)
{
north = true;
helitimer.start();
helitimer.start();
helitimer2.start();
repaint();
}
}
The three helitimers are Timer objects that start a series of Timers to increment the y position of the object continuously and smoothly. When the action upAction is invoked, the class UpAction is called and the three timers start in order to move the object.
Is there anyway I could make it so when the user releases UP, the action is no longer invoked and the timers stop?
Thanks a lot!
I'm wondering how you would program a keyReleased-like event with KeyBindings
Exactly the same way you do for a keyPressed event. The difference is in the KeyStroke. Read the KeyStroke API, is shows how to create a KeyStroke for a keyReleased event. There are a couple of different ways depending on how you want to create the KeyStroke.
The KeyStroke methods assume keyPressed, so you will need to add an additional parameter or additional keyword for the keyReleased event. I don't know which method you are using to create the KeyStroke so I can't tell you the exact change. Check the API for the details.
The three helitimers are Timer objects that start a series of Timers to increment the y position of the object continuously and smoothly
You should not need 3 Timer for this. One Timer should work satisfactorily.
Is there anyway I could make it so when the user releases UP, the action is no longer invoked and the timers stop?
If you can "start" a Timer in your keyPress Action, then you can "stop" the Timer in the keyReleasedAction. All you need is a reference to the Timer. Based on the code you posted you already defined the Timer as a class variable so this should not be an issue.
But when the user releases UP, the object should move downwards automatically to simulate basic gravity
Sounds to me like you will need another Timer to do this.
Another option is to always have a Timer running. Then when the UP key is pressed you make the Y increment a negative value. When the UP key is released you make the Y increment a positive value.
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.