Event handlers and loops - java

I have a full screen window that plays a simple animation, and I want to make it so that when I press any key, the full screen is restored and the program stops.
The key listener class looks like this:
import java.awt.event.*;
public class key implements KeyListener {
private framerun animation=new framerun();
public void keyPressed(KeyEvent e){}
public void keyReleased(KeyEvent e){}
public void keyTyped(KeyEvent e){
animation.x=false;
}
}
The animation runs in a method, run, with a while loop which looks like this:
public void run(DisplayMode dm){
Screen s=new Screen();
s.setFullScreen(dm, this);
while(true){
try{
System.out.println(x);
Thread.sleep(300);
}catch(Exception e){}
if(!x)
s.RestoreScreen();
repaint();
}
}
PS: x is a boolean with initial value true, initiated in the constructor.
This is the main method:
public static void main(String args []){
DisplayMode dm=new DisplayMode(800, 600, 16,DisplayMode.REFRESH_RATE_UNKNOWN);
framerun f=new framerun();
key k=new key();
f.addKeyListener(k);
f.run(dm);
}
Now this works perfectly if there is no while loop. The full screen closes and the program stop. But with the while loop there is no response when I press a key. The value of x doesn't change to false as expected.
Ideas?

I can't get the DisplayMode switching to work, but it shouldn't make a difference.
Basically, KeyListener is fiddly. It requires the component that it is attached to is focusable and has focus.
The following example basically uses a combination of requestFocusInWindow and setFocusable on a JPanel to try and force focus to the JPanel, so that when a key is typed, the JPanel can respond to it...
import java.awt.Dimension;
import java.awt.DisplayMode;
import java.awt.EventQueue;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.GridBagLayout;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
private DisplayMode defaultMode;
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
defaultMode = gd.getDisplayMode();
JFrame frame = new JFrame("Testing");
frame.setUndecorated(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
// DisplayMode dm = new DisplayMode(800, 600, 16, DisplayMode.BIT_DEPTH_MULTI);
// gd.setDisplayMode(dm);
gd.setFullScreenWindow(frame);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setFocusable(true);
setLayout(new GridBagLayout());
add(new JLabel("Test"));
addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
requestFocusInWindow();
}
});
addKeyListener(new KeyAdapter() {
#Override
public void keyTyped(KeyEvent e) {
try {
GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
// gd.setDisplayMode(defaultMode);
gd.setFullScreenWindow(null);
} catch (Throwable exp) {
exp.printStackTrace();
}
SwingUtilities.windowForComponent(TestPane.this).dispose();
}
});
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
}
}
Personlly, I'd recommend using the key bindings API, How to Use Key Bindings, but this focuses on binding a single key to a given action, but overcomes the focus issues related to KeyListener

Related

jSplitPane Showing and Hiding Left Pane when Mouse over

I'm working on an application that allows me to show and hide split planes.
I've read some articles on how to get this but its not what I'm looking for.
here's the code Ive written:
Im currently using netbeans.
private void jSplitPane1MouseEntered(java.awt.event.MouseEvent evt) {
if(MouseInfo.getPointerInfo().getLocation() == jSplitPane1.getLeftComponent().getLocation()){
jSplitPane1.setDividerLocation(100);
System.out.println("Mouse Entered");
}else{
jSplitPane1.setDividerLocation(20);
System.out.println("Mouse Exited");
}
}
I have referred to these posts:
How to make JSplitPane auto expand on mouse hover?
Get Mouse Position
What I want to happen is when I mouse over the left side of the jSplitPane, I would get the divider to extend to 100 as per my first if statement, and when it exists the left side, it contracts back to divider location 20.
This is really, really tricky.
You could use a MouseListener on the "left" component and monitor the mouseEntered and mouseExited events, but these will also get triggered when when you move into and out of a child component which has a MouseListener of it's own (like a JButton).
Okay, you could use a MouseMotionListener on the JSplitPane and monitor for the mouseMoved event and check where the mouse cursor is, but this goes to hell the moment the components (left/right) get their own MouseListener, as the MouseEvents are no longer delivered to the JSplitPane
So, one of the last options you have is to attach a global AWTListener to the event queue and monitor for events which occur on the JSplitPane itself, for example...
import java.awt.AWTEvent;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.awt.Toolkit;
import java.awt.event.AWTEventListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSplitPane;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new BorderLayout());
JSplitPane pane = new JSplitPane();
pane.setLeftComponent(makePane(Color.RED));
pane.setRightComponent(makePane(Color.BLUE));
Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
#Override
public void eventDispatched(AWTEvent event) {
if (event instanceof MouseEvent) {
MouseEvent me = (MouseEvent) event;
if (pane.getBounds().contains(me.getPoint())) {
System.out.println("Global Motion in the pane...");
me = SwingUtilities.convertMouseEvent(me.getComponent(), me, pane);
Component left = pane.getLeftComponent();
if (left.getBounds().contains(me.getPoint())) {
pane.setDividerLocation(100);
} else {
pane.setDividerLocation(20);
}
}
}
}
}, MouseEvent.MOUSE_MOTION_EVENT_MASK);
// You don't need this, this is to demonstrate
// that mouse events aren't hitting your component
// via the listener
pane.addMouseMotionListener(new MouseAdapter() {
#Override
public void mouseMoved(MouseEvent e) {
System.out.println("Motion in the pane...");
Component left = pane.getLeftComponent();
if (left.getBounds().contains(e.getPoint())) {
pane.setDividerLocation(100);
} else {
pane.setDividerLocation(20);
}
}
});
pane.setDividerLocation(20);
add(pane);
}
protected JPanel makePane(Color background) {
JPanel pane = new JPanel() {
#Override
public Dimension getPreferredSize() {
return new Dimension(100, 100);
}
};
pane.setLayout(new GridBagLayout());
pane.add(new JButton("..."));
pane.setBackground(background);
pane.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
System.out.println("...");
}
});
return pane;
}
}
}

Why does viewport changelistener get called multiple times

I've got a viewport, and I've attached a change listener to it. Whenever I scroll through my viewport, my change listener gets called about four times. I'm not sure how to avoid this; I only want the call to happen once?
There's no way around this, JViewport will fire several stateChanged events because it's providing notification about changes to a number of properties...
From the JavaDocs...
Adds a ChangeListener to the list that is notified each
time the view's size, position, or the viewport's extent size has
changed.
At this point, it's kind of hard to know what to suggest as we don't know what it is you are trying to achieve, however, if you have to use a ChangeListener, you could set up a coalescing mechanism. That is, rather then responding to each event, you basically wait until a long enough delay has occurred between events before responding to it...
For example...
public class DelayedChangeHandler implements ChangeListener {
private Timer timer;
private ChangeEvent last;
public DelayedChangeHandler() {
timer = new Timer(250, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
stableStateChanged();
}
});
timer.setRepeats(false);
}
#Override
public void stateChanged(ChangeEvent e) {
last = e;
timer.restart();
}
protected void stableStateChanged() {
System.out.println("Finally...");
}
}
Basically, this is a ChangeListener implementation that uses a non-repeating javax.swing.Timer with a short delay. Each time stateChanged is called, the timer is restart. Finally, when the timer is allowed to "tick", it calls stableStateChanged indicating that enough time has passed since the last event was raised.
This assumes that you don't so much care about what caused the event, only that the event occured...
A runnable example...
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class TestViewport {
public static void main(String[] args) {
new TestViewport();
}
public TestViewport() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JPanel pane = new JPanel() {
#Override
public Dimension getPreferredSize() {
return new Dimension(1000, 1000);
}
};
JScrollPane sp = new JScrollPane(pane);
sp.getViewport().addChangeListener(new DelayedChangeHandler());
sp.getViewport().addPropertyChangeListener(new PropertyChangeListener() {
#Override
public void propertyChange(PropertyChangeEvent evt) {
System.out.println(evt.getPropertyName());
}
});
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(sp);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class DelayedChangeHandler implements ChangeListener {
private Timer timer;
private ChangeEvent last;
public DelayedChangeHandler() {
timer = new Timer(250, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
stableStateChanged();
}
});
timer.setRepeats(false);
}
#Override
public void stateChanged(ChangeEvent e) {
last = e;
timer.restart();
}
protected void stableStateChanged() {
System.out.println("Finally...");
}
}
}
You can try to use AdjustmentListener for gettign scroll event once, try next:
import java.awt.event.AdjustmentEvent;
import java.awt.event.AdjustmentListener;
import java.io.UnsupportedEncodingException;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
public class Example {
public static void main(String[] args) throws UnsupportedEncodingException {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final JScrollPane pane = new JScrollPane(new JTextArea());
pane.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener() {
#Override
public void adjustmentValueChanged(AdjustmentEvent e) {
if(e.getValueIsAdjusting()){
return;
}
System.out.println("vertical scrolled");
System.out.println("bar value = " + e.getValue());
}
});
frame.setContentPane(pane);
frame.setSize(300, 200);
frame.setVisible(true);
}
}
Here is another example.

How do I make my JWindow window always stay focused

I am making a java application that includes a JWindow. I want to be able to track the mouse without the user having to click the window after going to another window.
Your question is little vague on why you want to continue processing the mouse once it's left the JWindow...but
You have two (basic) choices when it comes to mointoring the mouse outside of your application, you can use a JNI/JNA solution or you can poll MouseInfo.
The following demonstrates the latter, using MouseInfo and a javax.swing.Timer to update a label...
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.MouseInfo;
import java.awt.PointerInfo;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class MouseWindow {
public static void main(String[] args) {
new MouseWindow();
}
public MouseWindow() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private JLabel label;
public TestPane() {
setLayout(new BorderLayout());
label = new JLabel();
label.setFont(label.getFont().deriveFont(48f));
label.setHorizontalAlignment(JLabel.CENTER);
label.setVerticalAlignment(JLabel.CENTER);
add(label);
updateMouseInfo();
Timer timer = new Timer(250, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
updateMouseInfo();
}
});
timer.start();
}
protected void updateMouseInfo() {
PointerInfo pi = MouseInfo.getPointerInfo();
label.setText(pi.getLocation().x + "x" + pi.getLocation().y);
}
}
}
Updated
You may also find Window#setAlwaysOnTop of help to keep the window ontop of the others, if support for the platform

Get the Tray Icon to bounce in Mac [duplicate]

Well I'm writing an IRC client in Java and I was wondering if there was a way to make my app's icon bounce in the dock when a nickalert is triggered (or any other relevant notification).
If Windows also has some sort of notification system I'd like to know about it as well.
Under the MacOS, try using something like Application#requestUserAttention(boolean)
import com.apple.eawt.Application;
...
Application application = Application.getApplication();
application.requestUserAttention(false);
nb- I've not tried this my self - sorry.
Updated with example
From the JavaDocs
Requests user attention to this application (usually through bouncing
the Dock icon). Critical requests will continue to bounce the Dock
icon until the app is activated. An already active application
requesting attention does nothing.
That means, that if the application has focus, then the method will do nothing.
Test on Mac OSX 10.7.5, Java 1.7.0_07
import com.apple.eawt.Application;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class TestMacIcon {
public static void main(String[] args) {
new TestMacIcon();
}
public TestMacIcon() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
final Application application = Application.getApplication();
addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
try {
System.out.println("clicked");
application.requestUserAttention(true);
application.setDockIconImage(ImageIO.read(getClass().getResource("/Java.png")));
application.setDockIconBadge("Blah");
application.requestUserAttention(true);
} catch (IOException ex) {
ex.printStackTrace();
}
}
});
Timer time = new Timer(2000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (!SwingUtilities.getWindowAncestor(TestPane.this).hasFocus()) {
((Timer)e.getSource()).stop();
System.out.println("Pay attention!!");
application.requestUserAttention(true);
}
}
});
time.setRepeats(true);
time.setCoalesce(true);
time.start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
}
}
Ps make sure that you do-focus application ;)

How to make my app icon bounce in the Mac dock

Well I'm writing an IRC client in Java and I was wondering if there was a way to make my app's icon bounce in the dock when a nickalert is triggered (or any other relevant notification).
If Windows also has some sort of notification system I'd like to know about it as well.
Under the MacOS, try using something like Application#requestUserAttention(boolean)
import com.apple.eawt.Application;
...
Application application = Application.getApplication();
application.requestUserAttention(false);
nb- I've not tried this my self - sorry.
Updated with example
From the JavaDocs
Requests user attention to this application (usually through bouncing
the Dock icon). Critical requests will continue to bounce the Dock
icon until the app is activated. An already active application
requesting attention does nothing.
That means, that if the application has focus, then the method will do nothing.
Test on Mac OSX 10.7.5, Java 1.7.0_07
import com.apple.eawt.Application;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class TestMacIcon {
public static void main(String[] args) {
new TestMacIcon();
}
public TestMacIcon() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
final Application application = Application.getApplication();
addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
try {
System.out.println("clicked");
application.requestUserAttention(true);
application.setDockIconImage(ImageIO.read(getClass().getResource("/Java.png")));
application.setDockIconBadge("Blah");
application.requestUserAttention(true);
} catch (IOException ex) {
ex.printStackTrace();
}
}
});
Timer time = new Timer(2000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (!SwingUtilities.getWindowAncestor(TestPane.this).hasFocus()) {
((Timer)e.getSource()).stop();
System.out.println("Pay attention!!");
application.requestUserAttention(true);
}
}
});
time.setRepeats(true);
time.setCoalesce(true);
time.start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
}
}
Ps make sure that you do-focus application ;)

Categories

Resources