infinite loop if pause java game - java

I have a part of my code:
while(_running){
// render screens
if( _input.escape) {
if( isPaused ) {
pauseDialog.setVisible(false);
remuse(); // set isPaused = false, _running = true and render screens
}
else {
pause(); // set isPaused = true and _running = false and render screens
pauseDialog.setVisible(true);
}
}
}
and _input like this
public void keyPressed(KeyEvent e) {
keys[e.getKeyCode()] = true;
}
#Override
public void keyReleased(KeyEvent e) {
keys[e.getKeyCode()] = false;
}
and pauseDialog
public class PauseDialog extends JDialog{
JButton b1,b2;
public PauseDialog() {
setLayout(new GridLayout(2, 1,8,8));
setSize(new Dimension(85, 180));
setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
b1 = new JButton("resume");
b2 = new JButton("exit");
b1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("resume");
}
});
b2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("exit");
}
});
add(b1); add(b2);
}
but if i setvisible(true) for pauseDialog when escape key is released, variable _input.escape is always set true value, so dialog appears and disappears and appears again ... like an infinite loop. what should i do next? thanks.

Set "_input.escape" to False, after Escape is pressed?
Or does "_input.escape" need to be True for pausing to happen?
If so, that implies something's wrong, 'cause you shouldn't need to hold down Escape to keep the game paused?
It just seems you need a good logic system so that the dialog isn't being triggered more than once.
Maybe check if it's already triggered and don't trigger it again?

Related

How to count clicks with mouselistener and timer

So I am having a bit of trouble writing a mouse listener because I want the action to be performed only on a double click. I am trying to use a timer to reset a value that keeps track of the clicks but I don't think I have the correct understanding of the timers.
getTable().addMouseListener(new MouseAdapter(){
public void mouseClicked(MouseEvent e)
{
if ( isClickedOnce && SwingUtilities.isLeftMouseButton(e))
{
isClickedOnce = false;
System.out.println("anything");
}
else if(SwingUtilities.isLeftMouseButton(e))
{
isClickedOnce = true;
Timer time = new Timer(1000,new ActionListener(){
public void actionPerformed(ActionEvent actionEvent)
{isClickedOnce=false;}
});
time.start();
}
}
});
Java will do this for you. Within mouseClicked():
if(e.getClickCount() == 2) {
// do something
}

Timer works with println but not label using java

I have some labels that become visible when the letter a is pressed.
private void formKeyPressed(java.awt.event.KeyEvent evt) {
// TODO add your handling code here:
if(evt.getKeyCode()==KeyEvent.VK_A){
jLabel7.setVisible(true);
jLabel8.setVisible(true);
jLabel9.setVisible(true);
myBlink();
}
I have Label8 on a timer myBlink()
public void myBlink()
{
new Timer(1000, new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("begin");
jLabel8.setVisible(false);
jLabel8.setVisible(true);
System.out.println("Timer");
}
}).start();
}
I have placed printlns to see if timer begins and ends and when I press key "a" my output shows begin Timer multiple times but my label does not appear and disappear. What tweak does this code need? What am I missing? Thanks for the extra set of eyes.
This is probably because you call successively setVisible(false) and setVisible(true) which is done too fast to be seen, you should use a variable and modify its value any time the action of the Timer is called as next:
public void myBlink()
{
new Timer(1000, new ActionListener() {
boolean visible = true;
public void actionPerformed(ActionEvent e) {
jLabel8.setVisible(visible = !visible);
}
}).start();
}

How to change the value of a boolean when a JButton is pressed

My question states it all.
Here is my code:
fullscreen.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
MainMenu.isFullscreen = true;
}
});
Where fullscreen is a JButton.
And then in my Screen class:
if(mm.isFullscreen) {
GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().setFullScreenWindow(this);
repaint();
}
With mm being a deceleration of MainMenu. When mm.isFullscreen is false the Screen is its normal size.
I think I read somewhere that ActionListeners can't change the value of something outside the ActionListener...?
edit:
I have fixed the isue thanks for the help but this is new code:
In the screen class:
public void setFullscreen() {
GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().setFullScreenWindow(this);
repaint();
}
In the mainMenu class:
fullscreen.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if(isFullscreen) {
isFullscreen = false;
}
if(!isFullscreen) {
isFullscreen = true;
screen.setFullScreen();
}
});
When setting isFullscreen = false; you are not changing the state of full screen window!
You may use GraphicsDevice#setFullScreenWindow(null); to set it back to windowed mode.

Always on top with Checkbox on Java

Hello all I am trying to make a new software that it gives me modulo of any number I gave. What I want is I put a JCheckBox on my gui and when it's checked the window should be
setAlwaysOnTop(true);
and when deselected
setAlwaysOnTop(false);
Some of my code is
boolean top = false;
Check = new JCheckBox("Always on top");
Check.setLocation(140, 105);
Check.setSize(150, 20);
Check.setSelected(top);
Check.addItemListener(new CheckBoxListener());
add(Check);
setAlwaysOnTop(top);
private class CheckBoxListener implements ItemListener{
public void itemStateChanged(ItemEvent e){
if(e.getSource()==Check){
if(Check.isSelected()){
top = true;
}else{
top = false;
}
}
}
}
setAlwaysOnTop does not observe further state changes to your boolean top. It takes the value of top when it is passed.
In your listener, write:
if(e.getSource() == Check) {
setAlwaysOnTop(Check.isSelected());
}
Change:
public void itemStateChanged(ItemEvent e){
if(e.getSource()==Check){
if(Check.isSelected()){
top = true;
}else{
top = false;
}
}
}
to
public void itemStateChanged(ItemEvent e){
if(e.getSource()==Check){
setAlwaysOnTop(Check.isSelected());
}
}
}
(Also, look into the various LayoutManagers in Java; don't make a GUI with fixed positioning.)

Showing/hiding a JPopupMenu from a JButton; FocusListener not working?

I needed a JButton with an attached dropdown style menu. So I took a JPopupMenu and attached it to the JButton in the way you can see in the code below. What it needs to do is this:
show the popup when clicked
hide it if clicked a second time
hide it if an item is selected in the popup
hide it if the user clicks somewhere else in the screen
These 4 things work, but because of the boolean flag I'm using, if the user clicks somewhere else or selects an item, I have to click twice on the button before it shows up again. That's why I tried to add a FocusListener (which is absolutely not responding) to fix that and set the flag false in these cases.
EDIT: Last attempt in an answer post...
Here are the listeners: (It's in a class extending JButton, so the second listener is on the JButton.)
// Show popup on left click.
menu.addFocusListener(new FocusListener() {
#Override
public void focusLost(FocusEvent e) {
System.out.println("LOST FOCUS");
isShowingPopup = false;
}
#Override
public void focusGained(FocusEvent e) {
System.out.println("GAINED FOCUS");
}
});
addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("isShowingPopup: " + isShowingPopup);
if (isShowingPopup) {
isShowingPopup = false;
} else {
Component c = (Component) e.getSource();
menu.show(c, -1, c.getHeight());
isShowingPopup = true;
}
}
});
I've been fighting with this for way too long now. If someone can give me a clue about what's wrong with this, it would be great!
Thanks!
Code:
public class Button extends JButton {
// Icon.
private static final ImageIcon ARROW_SOUTH = new ImageIcon("ArrowSouth.png");
// Unit popup menu.
private final JPopupMenu menu;
// Is the popup showing or not?
private boolean isShowingPopup = false;
public Button(int height) {
super(ARROW_SOUTH);
menu = new JPopupMenu(); // menu is populated somewhere else
// FocusListener on the JPopupMenu
menu.addFocusListener(new FocusListener() {
#Override
public void focusLost(FocusEvent e) {
System.out.println("LOST FOCUS");
isShowingPopup = false;
}
#Override
public void focusGained(FocusEvent e) {
System.out.println("GAINED FOCUS");
}
});
// ComponentListener on the JPopupMenu
menu.addComponentListener(new ComponentListener() {
#Override
public void componentShown(ComponentEvent e) {
System.out.println("SHOWN");
}
#Override
public void componentResized(ComponentEvent e) {
System.out.println("RESIZED");
}
#Override
public void componentMoved(ComponentEvent e) {
System.out.println("MOVED");
}
#Override
public void componentHidden(ComponentEvent e) {
System.out.println("HIDDEN");
}
});
// ActionListener on the JButton
addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("isShowingPopup: " + isShowingPopup);
if (isShowingPopup) {
menu.requestFocus();
isShowingPopup = false;
} else {
Component c = (Component) e.getSource();
menu.show(c, -1, c.getHeight());
isShowingPopup = true;
}
}
});
// Skip when navigating with TAB.
setFocusable(true); // Was false first and should be false in the end.
menu.setFocusable(true);
}
}
Here's a variant of Amber Shah's "big hack" suggestion I just made. Without the isShowingPopup flag...
It's not bulletproof, but it works quite well until someone comes in with an incredibly slow click to close the popup (or a very fast second click to reopen it...).
public class Button extends JButton {
// Icon.
private static final ImageIcon ARROW_SOUTH = new ImageIcon("ArrowSouth.png");
// Popup menu.
private final JPopupMenu menu;
// Last time the popup closed.
private long timeLastShown = 0;
public Button(int height) {
super(ARROW_SOUTH);
menu = new JPopupMenu(); // Populated somewhere else.
// Show and hide popup on left click.
menu.addPopupMenuListener(new PopupMenuListener() {
#Override
public void popupMenuWillBecomeInvisible(PopupMenuEvent arg0) {
timeLastShown = System.currentTimeMillis();
}
#Override public void popupMenuWillBecomeVisible(PopupMenuEvent arg0) {}
#Override public void popupMenuCanceled(PopupMenuEvent arg0) {}
});
addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if ((System.currentTimeMillis() - timeLastShown) > 300) {
Component c = (Component) e.getSource();
menu.show(c, -1, c.getHeight());
}
}
});
// Skip when navigating with TAB.
setFocusable(false);
}
}
As I said in comments, that's not the most elegant solution, but it's horribly simple and it works in 98% of the cases.
Open to suggestions!
Here is another approach which is not too bad of a hack, if not elegant, and which, as far as I could tell, works. First, at the very top, I added a second boolean called showPopup.
The FocusListener has to be as follows:
menu.addFocusListener(new FocusListener() {
#Override
public void focusLost(FocusEvent e) {
System.out.println("LOST FOCUS");
isShowingPopup = false;
}
#Override
public void focusGained(FocusEvent e) {
System.out.println("GAINED FOCUS");
isShowingPopup = true;
}
});
The isShowingPopup boolean does not get changed anywhere else--if it gains focus, it assumes it's shown and if it loses focus, it assumes it isn't.
Next, the ActionListener on the button is different:
addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("isShowingPopup: " + isShowingPopup);
if (showPopup) {
Component c = (Component) e.getSource();
menu.show(c, -1, c.getHeight());
menu.requestFocus();
} else {
showPopup = true;
}
}
});
Now comes the really new bit. It's a MouseListener on the button:
addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
System.out.println("ispopup?: " + isShowingPopup);
if (isShowingPopup) {
showPopup = false;
}
}
#Override
public void mouseReleased(MouseEvent e) {
showPopup = true;
}
});
Basically, mousePressed gets called before the menu loses focus, so isShowingPopup reflects whether the popup was shown before the button is pressed. Then, if the menu was there, we just set showPopup to false, so that the actionPerformed method does not show the menu once it gets called (after the mouse is let go).
This behaved as expected in every case but one: if the menu was showing and the user pressed the mouse on the button but released it outside of it, actionPerformed was never called. This meant that showPopup remained false and the menu was not shown the next time the button was pressed. To fix this, the mouseReleased method resets showPopup. The mouseReleased method gets called after actionPerformed, as far as I can tell.
I played around with the resulting button for a bit, doing all the things I could think of to the button, and it worked as expected. However, I am not 100% sure that the events will always happen in the same order.
Ultimately, I think this is, at least, worth trying.
You could use the JPopupMenu.isVisible() instead of your Boolean variable to check the current state of the popup menu.
Have you tried adding a ComponentListener to the JPopupMenu, so that you know when it's been shown and hidden (and update your isShowingPopup flag accordingly)? I'm not sure listening for focus changes is necessarily the right approach.
What you need is a PopupMenuListener:
menu.addPopupMenuListener(new PopupMenuListener() {
#Override
public void popupMenuWillBecomeVisible(PopupMenuEvent arg0) {
}
#Override
public void popupMenuWillBecomeInvisible(PopupMenuEvent arg0) {
System.out.println("MENU INVIS");
isShowingPopup = false;
}
#Override
public void popupMenuCanceled(PopupMenuEvent arg0) {
System.out.println("MENU CANCELLED");
isShowingPopup = false;
}
});
I inserted this into your code and verified that it works.
Well, I can't be sure without seeing all of your code, but is it possible that the popup never actually gets focus at all? I've had problems with things' not getting focus properly in Swing before, so it could be the culprit. Try calling setFocusable(true) on the menu and then calling requestFocus() when you make the menu appear.
I tried the Answer of Tikhon Jelvis (introducing a smart combination of focusListener and mouseListener). It does not work for me on Linux (Java7/gtk). :-(
Reading http://docs.oracle.com/javase/7/docs/api/javax/swing/JComponent.html#requestFocus%28%29 there is written "Note that the use of this method is discouraged because its behavior is platform dependent."
It may be that the order of listener calls changed with Java7 or it changes with GTK vs Windows. I would not recommend this solution if you want to be platform independent.
BTW: I created a new account on stackoverflow to give this hint. It seems I am not allowed to comment to his answer (because of reputation). But it seems I have a button to edit it. This stackoverflow is a very funny thing. :-)

Categories

Resources