Keypressed while a thread is running - how to capture the keys? - java

I have a JPanel that contains a few other objects that do stuff. I will simplify the example by talking about some circle object (defined by circle class I made), and a square object (similar).
the circle moves randomly around the screen, while the square sits at its place. my intention is to move the square using the arrow buttons.
the current design is to have a thread with a while loop that contains a delay that sets the 'refresh rate' inside its run method.
I'm trying every method I know to capture the arrow keys and move the square around while the ball is running around the screen.
how do I capture keypresses (arrows for the example) so I can know where to move my square to?
I tried implementing keylistener in the jpanel but it didn't work. when I tried to use a KeyEvent in the run, I got an exception.
please save me. :)
EDIT:
Thanks for that info. I would like further help to settle this issue -
lets say I have the following code:
this.getInputMap().put(KeyStroke.getKeyStroke("UP"), "actionName");
this.getInputMap().put(KeyStroke.getKeyStroke("DOWN"), "actionName");
this.getActionMap().put("actionName",
new AbstractAction("actionName") {
public void actionPerformed(ActionEvent evt) {
//dostuff
}
}
);
how do I distinguish between UP and DOWN presses? what do I need to change?
Thanks! I'm a bit of a newbie, I know :)

KeyListener isn't designated for listening in Swing GUI, this Listener was builded for pre_historic AWT Component, these days so far away, use KeyBindings, this example can save your person

Related

MouseListener across several panels?

My user story is the following:
In order to upgrade a tower, the player has to drag a gun from the shop and drop it on the tower.
In practice, the GameView contains both the BattlefieldCanvas and the ShopView. Besides, the ShopView contains a GunSelector for each buyable gun. All those guys are sub-classes of JPanel.
I'm currently using a MousListener to handle several actions performed on the BattlefieldCanvas; I thought I could use the same stuff to handle a mouse trip from one of the GunSelector to the BattlefieldCanvas ( = across several panels ), so I tried to add the same MousListener to the gun selectors and the battlefield.
Problem: doesn't work. The getSource() method of the event object returns a reference to the gun selector while the mouse is actually released on the battlefield.
PS: Unlike gun selectors, towers are not swing components but images drawn by the paintComponent method.
1) To answer to your original question as to why source is still the component mouse was clicked on. You just need to read the JavaDoc:
public Object getSource()
The object on which the Event initially occurred.
Returns:
The object on which the Event initially occurred.
2) Now, how can we get the actual component that mouse is released on. You can try this approach:
#Override
public void mouseReleased(MouseEvent e) {
Component theCOmponentMouseIsReleasedOn = frame.findComponentAt( e.getLocationOnScreen() );
}
You don't need to always call findComponentAt on frame, you can call on the container that contains your BattlefieldCanvas.

How can I fix the actionPerformed method freezing when the mouse is moved within the pane?

In a Swing application when the mouse is moved within the frame, the actionPerformed method stops cycling. How can I fix this?
Here's the basic layout of my program:
ActionListener taskPerformer = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
// main game loop
}
}
public void paintComponent(Graphics g) {
// render loop
}
I found a similar question here. The user found that by lowering the polling rate of the mouse they fixed the problem; however I cannot change the polling rate on my apple trackpad, and no other solutions were offered. Also it is an inelegant solution that would require the user to change settings, and honestly there has to be a better way to fix the problem.
Basically the question boils down to this:
Is there a way for me to change the polling rate from within my program? I did some research and couldn't find a solution.
How can I disable mouse movement events, so as to not slow down my game loop? (Also perhaps move it to a separate process, and use the mouses x and y position provided by that process for logic in the game loop.)
What alternate solution can I implement to fix this problem?
I think you need to implement the "ActionListener" where you can take it, because when you are moving will work the ActionListener, when you will click, it will be already ActionEvent.
Also you can get more from:
https://docs.oracle.com/javase/tutorial/uiswing/events/mouselistener.html
and
How can I get the location of the mouse pointer in a JPanel (Without any operation of the Mouse)?

How to continuously poll a button that I created using scene2d

I am attempting to create four buttons that act like a D-pad on the screen. I created the buttons using scene2d, organizing them in a table. I understand how to add a listener that fires once one of the buttons has been clicked, but I want to be able to do something, such as move a character as long as the button is held down. I tried the code below and was getting a null pointer exception. Any thoughts on what I might be able to do? Thank you.
public void render() {
stage.act(Math.min(Gdx.graphics.getDeltaTime(), 1 / 30f));
stage.draw();
if (up_button.isPressed()){
// do something, such as move a character up
}
}
Look into ActorGestureListener. Perhaps you can test longPress() against a timer.
ActorGestureListener

stop animation in java applet at mouse click

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.

Is there a standard way to handle many different options for mouse events in java?

I'm developing a grid based sim game in java, and I was wondering if there is a standard way of doing the following.
I have a panel which is the game panel, and there are many different things which could happen when the panel is clicked. For example, when building a room, there are several stages, where dragging the mouse and left clicking will have different actions.
Right now, the way I have done it, is to use booleans to check what's being built, and then what stage it is at.
Is there any better or standard way of handling something like this? I had a quick google, but as I have said before, people on Stack Overflow always give a better, more relevant, up to date answer.
I consider myself still rather new to java.
Thanks in advance.
You might try looking into something similar to the strategy pattern.
Basically, you start by clicking the room button on your toolbar. The toolbar goes through and tells the grid to use the 'room place' actionlistener. Presumably removing any previous action listener that was listening
The room place actionlistener would in turn implement all the interesting bit of logic for left/right clicking, dragging, etc.
If you have multiple stages to building a room (say, placing doors, then windows, then trap doors); the action listeners would be responsible for handing control off to the next stage: a bit of a finite state machine.
So, start by clicking 'room' button, 'place room' listener is added. Drag out the area you want the room to be, 'place room' modifies the game state, then changes the actionlistener to the 'place windows' listener. Ad infinitum... until you finish.
One very simple (non compilable) example:
class GridPanel extends JPanel
{
void SetMouseListener(MouseListener newListener)
{
for(MouseListener ml : getMouseListeners())
removeMouseListener(ml);
addMouseListener(newListener);
}
}
class ControlPanel extends JPanel
{
GridPanel gameGrid;
void OnRectangleButtonClicked(some stuff)
{
gameGrid.SetMouseListener(new PlaceRoomListener(gameGrid));
}
}
class PlaceRoomListener extends MouseAdapter
{
GridPanel gameGrid;
//constructor, etc
void OnClick(mouse event)
{
gameGrid.doCoolStuff();
gameGrid.SetMouseListener(new PlaceTrapDoorListener());
}
}
//etc
Now, that non-compilable example aside, Pyrolistical does have a point: you generally don't want to combine your game model and graphic interface into one single glob of classes. You want the model separated from the GUI, and to manipulate it through a well defined interface.
(Also, there are probably better methods for going about removing the mouse listener then just randomly removing all listeners... I was in a bit of a rush, sorry)
It sounds like you need to define your game model/state and keep it separate from your mouse actions.
Are you using MVC?

Categories