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
Related
For my program I have a JPane that as the game progresses it adds labels to the panel, however the only way I can make the panels show up is by using add(label) then revalidating and vice versa for removing labels.
My problem is that once it gets to the point that I have more than 40 labels on the screen the revalidate has to process too many things, so how can I override the revalidate(), ether works, so that it only revalidates the specific component that was added, and not every component on the screen. I know there is a loop somewhere within the revalidate() method that will run through a loop of all components, but I just can not for the life of me find it. I would like to be able to call revalidate(component-here) or validate (component-here) and have it only update that specific component.
I know there are other ways of writing this program but I am only interested in how to override revalidate() so no "you could have redone your whole code this way which should only take you like 6 hours >.<".
http://www.fileserve.com/file/jFdQ6nv/FINAL_PROJECT.zip a link to my eclipse project, if anyone who wants to help would like to see what im actually talking abouyt
I just tried this example. Adding 1000 text areas only takes a second, and updates are instant. Labels go even faster. You might want to look at something else slowing it down.
Also, you could look at CellRendererPane. It overrides invalidate() to do nothing.
public void invalidate() {}
I am going through a legacy application which is using Swing and i am struggling to figure out how the screens are changing when a user clicks a button. One of the reasons i cant figure this out is because this is the first time i am using Swing. I have read a book and got the basics but still struggling.
Basically, the screen i am looking at has a JSplitPane which has a number of shortcut buttons on the left and an empty pane on the right. When i click on the button, the right side pane is populated with a different screen depending on the button pressed.
Going through the code, i was expecting somewhere that there will be something that calls a setVisible() method depending on which button is pressed.
The actionPerformed method for each of the shortcut buttons looks something like this:
void shortCutBtn_actionPerformed(ActionEvent e) {
propertyChangeListeners.firePropertyChange("selectedShortCut", previousShortCutSel, currentShortCutSel);
mainPanel.updateUI();
}
I have gone through most of the code and came to a conclusion that the above code is what is causing the frame switching but i dont understand how that is happening.
Each screen is identified by a numeric constant. In the above code example, previousShortCutSel and previousShortCutSel refer to a numeric value that represents individual screens screen.
I have tried to look for documentation of how updateUI() works but i am lost. How does the above cause the content of the right panel of the JSplitPanel to be updated with a new screen?
This is not an appropriate use of updateUI(), which "Resets the UI property to a value from the current look and feel." As the example itself may be unreliable, consider studying another. GoogleOlympiad, for example, sets a label's icon using a (cached) image.
ImageIcon image = getImage(index);
imageLabel.setIcon(image);
(source: drjohnbmatthews at sites.google.com)
As per comments by ziggy (glad it helped)
Have a look at the PropertyChangeListeners that appear to be added in the code. In particular the propertyChange(PropertyChangeEvent e) method is where the code which changes the content will be present.
+1 to trashgod nice example/advice as always
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
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.
Apologies for the somewhat unclear question - couldn't think of a better way of putting it.
I use a JXTaskPane (from the Swing labs extension API) to display some information.
The user can "click" the title to expand the panel. The JXTaskPane is in a container JPanel, which is then added to a JFrame, my main application window.
I want my application window to resize to the size of the expanded task pane. To achieve this, I added a component listener to my container JPanel which would set size to the now expanded panel.
panel.addComponentListener(new ComponentListener()
{
public void componentResized(ComponentEvent e)
{
Dimension newSize = ((JXTaskPane)e.getSource()).getSize();
reSizeFrame(newSize);
}
}
private void reSizeFrame(Dimension newSize)
{
if ((newSize.height < maxSize.height) && (newSize.width < maxSize.width))
{
containerPanel.setSize(newSize);
appFrame.setSize(containerPanel.getSize());
appFrame.pack();
}
}
The problem is that the componentResized method is called as the task pane expands, as a result the resizeFrame method is called lots of times, and looks really awful on the screen.
How can I detect when the JXTaskpane has finished resizing? I thought of two approaches:
Put the resizeFrame() method in a SwingUtilities.invokeLate(..) call.
Put in a timer resizeFrame call, so any subsequent calls do not do anything until the timer fires. This should give enough time for the panel to resize.
What is the best way forward?
Also - This is my first serious Java GUI app after years of server side program. StackOverflow has been very helpful. So thanks!
I know you've already selected an answer, but overriding the paint method is definitely not correct, and while you may be able to hack something in place, it won't be ideal.
Looking at the source for JXTaskPane and specifically looking in setExpanded() (line 387), you can see it calls JXCollapsiblePane.setCollapsed(...) and then fires a property change event for expanded. A listener on that property won't be correct, because it'll fire before the animation is complete. So, if you go into JXCollapsiblePane and look at setCollapsed(...) (line 470) you'll see that if it's animated, it sets the paramaters and starts a timer. We want to know when the animation ends, so in that file, look at the animator (line 620, and specifically 652-667), which shows that when the animation ends, it fires a property change for ANIMATION_STATE_KEY with a value of "collapsed" or "expanded". This is the event you actually want. However, you don't have access to JXCollapsiblePane, so go back to JXTaskPane and search for ANIMATION_STATE_KEY, and you find line 208, which shows that JXTaskPane creates a listener on JXCollapsiblePane.ANIMATION_STATE_KEY and refires it as it's own event.
Since you do have access to JXTaskPane, you can listen for that event, so doing ...
taskPane.addPropertyChangeListener(JXCollapsiblePane.ANIMATION_STATE_KEY, new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent e) {
if(e.getNewValue().equals("expanded") {
...
}
else if(e.getNewValue().equals("collapsed") {
...
}
}
}
should get your event exactly when you want it.
The correct way to listen for events in Swing is through property listeners. Unfortunately, the only way to find out what the correct properties and values are is by digging through source code.
As a suggestion, have you tried overriding the paint method, first calling super and then putting your resize code at the end of that if (and only if) the size has changed significantly.
I'm not familiar with JXTaskPane, but my first reaction is that maybe you're handling the wrong event. You want the frame to resize when the user clicks on the header - so why not handle that event (perhaps using EventQueue.invokeLater() to resize the frame after the task pane has been resized)?
But if that doesn't work and you need to use the approach you've outlined above, using a javax.swing.Timer is probably best. Set it for 200 milliseconds or so and just restart() it every time componentResized() fires.