I want have a very easy effect:
create a window, then if I press a button, it will be closed.
So I write the following code, but it doesn't work.
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
public class test
{
public static void main(String[] args)
{
final Window wnd = new Window(new Frame());
wnd.setLocation(100, 100);
wnd.setSize(400,300);
wnd.setVisible(true);
wnd.requestFocusInWindow();
wnd.addKeyListener(
new KeyAdapter() {
public void keyPressed(KeyEvent event)
{
wnd.setVisible(false);
wnd.dispose();
System.exit(0);
}
}
);
}
}
I guess the problem may be lie in:
wnd.requestFocusInWindow();
because the returned value of wnd.requestFocusInWindow() is always "false". Why? How can I fix the problem? (I use ubuntu and Eclipse.)
Related
I'm making a program for a game HUD GUI but java cant get global keystrokes when the window isn't in focus so, and i dont want to do any black magic with jnativeinterface as i need it to work on both Linux and windows. My idea for getting around this was to pipe output from python to java but I'm not entirely sure how to do so.
here's my code so far for reference:
I've tried assigning a java key-listener to a none existent window just because i was curious and it didn't work.
package main;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.PointerInfo;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class MainThread extends JFrame implements KeyListener{
private static final long serialVersionUID = 1L;
public static void main(String[] args) throws Exception {
System.out.println("Jeffrey was here");
JFrame win = new JFrame();
JPanel wind = new JPanel();
win.add(wind);
win.setDefaultCloseOperation(EXIT_ON_CLOSE);
win.setVisible(true);
win.setLocation(500, 500);
win.setResizable(false);
win.setSize(300,50);
win.setAlwaysOnTop(true);
win.setTitle("Mouse Cordinates");
JLabel xCord = new JLabel("");
JLabel yCord = new JLabel("");
wind.add(xCord);
wind.add(yCord);
while(true) {
Thread.sleep(30);
PointerInfo mouse = MouseInfo.getPointerInfo();
Point poin = mouse.getLocation();
xCord.setText("X cordinates: " + (int) poin.getX());
yCord.setText("Y cordinates: " + (int) poin.getY());
}
}
#Override
public void keyPressed(KeyEvent arg0) {
// TODO Auto-generated method stub
int key = arg0.getKeyCode();
if(key == KeyEvent.VK_W) {
System.out.print("w pressed");
}
}
#Override
public void keyReleased(KeyEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void keyTyped(KeyEvent arg0) {
// TODO Auto-generated method stub
}
}
i need it to detect when the key is pressed without the window is in focus.
There are already existing libraries that give you this option (i know this is not exactly what you are looking for (python and stuff), but it might be a solution to your problem). Take a look at kristian's system hook code snippet:
public static void main(String[] args) {
// might throw a UnsatisfiedLinkError if the native library fails to load or a
// RuntimeException if hooking fails
GlobalKeyboardHook keyboardHook = new GlobalKeyboardHook(true);
keyboardHook.addKeyListener(new GlobalKeyAdapter() {
#Override
public void keyPressed(GlobalKeyEvent event) {
System.out.println(event);
if (event.getVirtualKeyCode() == GlobalKeyEvent.VK_ESCAPE)
run = false;
}
#Override
public void keyReleased(GlobalKeyEvent event) {
System.out.println(event);
}
});
And of course there is also the JNativeHook option.
Some other already existing questions to take a look:
How to capture global key presses in java
How can I write a key listener to track all keystrokes in Java?
I am stuck with a very unusual situation. I have a class "ScreenSizeSelector" which has a method 'getSelectedScreenSize'. The method's work is to create a UI, user drags the UI and method return back size of window.
Now I am calling the method of class in following ways:
A simple class (non GUI)
On the button click from a JFrame
In the first case, it is working perfectly fine (i.e. size selector window opens, user drags it, resize it and it is giving back window coordinates) but in second case, window opens but in disabled mode, user is not able to perform any operation on the window, not even able to close the window.
Here is the code I am using
ScreenSizeSelector class :
package screenrecorder;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.Border;
class ScreenSizeSelector {
private JFrame sizeSelectorWindow;
private JButton btnOk;
private Border emptyBorder;
private Rectangle screenArea = null;
private static Object lock = new Object();
public Rectangle getSelectedScreenSize(){
screenSizeSelectorUI();
Thread t = new Thread() {
public void run() {
synchronized(lock) {
while (sizeSelectorWindow.isVisible())
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
t.start();
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
return screenArea;
}
public void screenSizeSelectorUI() {
emptyBorder = BorderFactory.createEmptyBorder();
sizeSelectorWindow = new JFrame("Select screen area");
btnOk = new JButton("Start");
sizeSelectorWindow.setUndecorated(true);
sizeSelectorWindow.getRootPane().setWindowDecorationStyle(3);
sizeSelectorWindow.setBackground( new Color(0, 0, 0, 0) );
sizeSelectorWindow.setSize(400,400);
sizeSelectorWindow.addWindowListener(new WindowEventHandler());
sizeSelectorWindow.setAlwaysOnTop(true);
sizeSelectorWindow.setLocationRelativeTo(null);
btnOk.setToolTipText("Click this button after deciding the screen area");
btnOk.addActionListener(new ButtonEventHandler());
JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
buttonPanel.setBackground(new Color(0,0,0,0));
buttonPanel.add(btnOk);
sizeSelectorWindow.add(buttonPanel,BorderLayout.SOUTH);
sizeSelectorWindow.setVisible(true);
sizeSelectorWindow.setEnabled(true);
}
class ButtonEventHandler implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
int x = (int)(sizeSelectorWindow.getBounds().getX());
int y = (int) (sizeSelectorWindow.getBounds().getY());
int width = sizeSelectorWindow.getWidth();
int height = sizeSelectorWindow.getHeight();
screenArea = new Rectangle(x,y,width,height);
sizeSelectorWindow.dispatchEvent(new WindowEvent(sizeSelectorWindow, WindowEvent.WINDOW_CLOSING));
}
}
class WindowEventHandler implements WindowListener{
#Override
public void windowOpened(WindowEvent e) {
}
#Override
public void windowClosing(WindowEvent e) {
synchronized (lock) {
sizeSelectorWindow.setVisible(false);
lock.notify();
}
}
#Override
public void windowClosed(WindowEvent e) {
}
#Override
public void windowIconified(WindowEvent e) {
sizeSelectorWindow.setState(JFrame.NORMAL);
Toolkit.getDefaultToolkit().beep();
}
#Override
public void windowDeiconified(WindowEvent e) {}
#Override
public void windowActivated(WindowEvent e) {}
#Override
public void windowDeactivated(WindowEvent e) {}
}
}
Test1 class :
package screenrecorder;
import java.awt.Rectangle;
public class Test1{
public static void main(String[] args){
System.out.println(new ScreenSizeSelector().getSelectedScreenSize());
}
}
Test2 class :
package screenrecorder;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
public class Test2 extends JFrame{
public Test2(){
JButton btn = new JButton("Click ME");
btn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println(new ScreenSizeSelector().getSelectedScreenSize());
}
});
getContentPane().add(btn);
setSize(100,100);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args){
new Test2();
}
}
Any help is appreciated.
when you click the button, the action listener waits for the getSelectedScreenSize() function to return. and the getSelectedScreenSize() function is waiting for the second window created by screenSelectorUI() to be invisible. screenSelectorUI() does create a second window, but you set the color like this:
sizeSelectorWindow.setBackground( new Color(0, 0, 0, 0) );
if you look at the color constructor javadocs:
public Color(int r,
int g,
int b,
int a)
Creates an sRGB color with the specified red, green, blue, and alpha values in the range (0 - 255).
Parameters:
r - the red component
g - the green component
b - the blue component
a - the alpha component
you set the alpha value to 0, making it completely invisible. (alpha value is transparency) also, this second window is undecorated and does not exit on close, so you don't even know it's there at all.
what I don't get is how test1 worked at all.
side note: when I try test 1 on mac it only shows the button and all I can do is click it. the button will disappear, but the application will still be running.
This is basically a total guess, but a lot of the swing components make requests to the operating system, not commands. sort of like saying, "hey can I please be resized to 400, 400?" the OS doesn't technically have to do what you say. and I was reading How does Java handle multithreading? which says that multithreading really depends on the OS. I have a feeling it just messes up somewhere when screenSelectorUI() is called by itself, but somehow gets it right when it's inside the thread of some button.
Please have a look at the following code
import com.sun.jna.Native;
import uk.co.caprica.vlcj.binding.LibVlc;
import uk.co.caprica.vlcj.component.EmbeddedMediaPlayerComponent;
import uk.co.caprica.vlcj.runtime.RuntimeUtil;
import com.sun.jna.NativeLibrary;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import javax.media.bean.playerbean.MediaPlayer;
import uk.co.caprica.vlcj.player.MediaPlayerEventAdapter;
import uk.co.caprica.vlcj.player.MediaPlayerEventListener;
public class PlayMedia extends JFrame
{
private EmbeddedMediaPlayerComponent m;
private JProgressBar bar;
public PlayMedia()
{
NativeLibrary.addSearchPath(
RuntimeUtil.getLibVlcLibraryName(), "c:\\program files\\videolan\\vlc"
);
Native.loadLibrary(RuntimeUtil.getLibVlcLibraryName(), LibVlc.class);
m = new EmbeddedMediaPlayerComponent();
m.getMediaPlayer().addMediaPlayerEventListener(new UpdateBar());
bar = new JProgressBar(0,100);
bar.setStringPainted(true);
getContentPane().add(m);
getContentPane().add(bar,"South");
this.setSize(500,500);
this.validate();
this.setLocationRelativeTo(null);
this.setVisible(true);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
m.getMediaPlayer().playMedia("C:\\Users\\Yohan\\Desktop\\video.avi");
}
private class UpdateBar extends MediaPlayerEventAdapter
{
public void positionChanged(MediaPlayer mp, float pos)
{
int value = Math.min(100, Math.round(pos * 100.0f));
bar.setValue(value);
}
}
public static void main(String[]args)
{
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
new PlayMedia();
}
});
}
}
In here, video is playing fine, but the progress bar is not getting updated. How to update the progress bar as the video plays? Please help!
I haven't used ProgressBars in Swing, but I have used them in Silverlight, so I would think most of the principles would be the same. Check out the answer to my question here:
How do I make a Silverlight Progressbar update according to its value? It may not show you exactly how to do this in Swing, but it doesn't seem like you're using threading in your code, which is what my problem was.
for some unknown reason positionChanged() isn't called during the video.
try to use timeChanged() istead, it worked for me!
public void positionChanged (MediaPlayer mediaPlayer , long time) { ... }
This is getting me quite confused:
I have a small application that uses a JSpinner for numeric values. I added a MouseAdapter to it, setting the value depending on the resulting event's getScrollAmount() and getWheelRotation().
Everything is working quite fine as long as the application is run on linux (Debian Wheezy, Oracle JDK 1.6.0_32). That is, scrolling the mouse wheel while the JSpinner has focus works just fine (using GTK LookAndFeel).
Testing the software on Microsoft Windows exposed a different behavior:
The JSpinner will not react on mouse wheel movement. LookAndFeels don't seem to be a problem here, as i already tried MetalLookAndFeel on both Linux and Windows.
Any suggestions on how to get this JSpinner reacting on MouseWheelEvents on both OSes?
Thank you.
Hmm im not sure what could be wrong, but here is code designed on windows 7 and it works fine so maybe try it out on yours and see where the code is different:
import java.awt.Container;
import java.awt.EventQueue;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import javax.swing.JFrame;
import javax.swing.JSpinner;
import javax.swing.UIManager;
import javax.swing.UIManager.LookAndFeelInfo;
/**
*
* #author David
*/
public class JSpinnerMouse extends JFrame {
private JSpinner jspinner;
public JSpinnerMouse() {
createAndShowUI();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
try {
for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (Exception e) {
// If Nimbus is not available, you can set the GUI to another look and feel.
}
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JSpinnerMouse jSpinnerMouse = new JSpinnerMouse();
}
});
}
private void createAndShowUI() {
setTitle("JSpinner using mouse wheel");
setSize(300, 300);
setResizable(false);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
addComponentsToContentPane(getContentPane());
addListeners();
setVisible(true);
}
private void addComponentsToContentPane(Container contentPane) {
jspinner = new JSpinner();
contentPane.add(jspinner);
}
private void addListeners() {
this.addMouseWheelListener(new MouseWheelListener() {
#Override
public void mouseWheelMoved(MouseWheelEvent mwe) {
if (MouseWheelEvent.WHEEL_UNIT_SCROLL == mwe.getScrollType()) {
int value = (int) jspinner.getValue();
if (mwe.getWheelRotation() == -1) {//up
jspinner.setValue(value + 1);
} else {//down
jspinner.setValue(value - 1);
}
}
}
});
}
}
Also to mention, I could not find the getDirection() method in the MouseWheelEvent like you said you are using so i used the getUnitsToScroll() which will return either a positive or negative value depending on the direction. Maybe this is whats causing the trouble. Where did you find a getDirection() method in the MouseWheelEvent Class?
I want to write a little code which react to a mouse click. But it seems the only way is to listen to clicks on Java components. A direct listener to all clicks would be great.
Is there actually a possibility to implement this in Java?
Thanks in advance!
Update:
Found out, that it would need a hook via JNI with some C coding.
More information on
http://www.jotschi.de/?p=90
Best regards,
fnst
It's perfectly possible if you are willing to use a third party library - JNativeHook
It provides these functionality using JNI which is otherwise not possible in pure java apps.
Don´t think so, because of the sandbox you´re running in.
some food for thought: use Point in Java to detect where the click occurs. http://download.oracle.com/javase/1.4.2/docs/api/java/awt/Point.html
admittedly, ive only used it once before for detecting rows in a table something like, but it seems the closest to what ive found answering your qn.:
public void mouseClicked(MouseEvent e) {
JTable target = (JTable)e.getSource();
//get the coordinates of the mouse click
Point p = e.getPoint();
//get the row index that contains that coordinate
row= target.rowAtPoint(p);
}
im sorry if this isn't what you're looking for, but otherwise, clicking on components is the only way to go. whats the alternative- clicking on containers? well that just doesn't make any sense does it?
As far as I know, there is not easy way to accomplish what you want. But what you want could be done.. Well for modern way to accomplish this task, I suggest you examine java.awt.Dialog show method..
package mouseclickevent;
import java.awt.AWTEvent;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.MenuComponent;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.lang.reflect.Method;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class FrmEvent extends JFrame {
public FrmEvent(){
JPanel panel = new JPanel();
getContentPane().add(panel);
JButton btn = new JButton("Test");
panel.add(btn);
panel.add(new JTextField("Test"));
btn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
FrmEvent frm = new FrmEvent();
frm.setBounds(300,300, 200, 200);
frm.show();
}
});
}
private void consumeEvents() {
try {
if (Thread.currentThread().getClass().getName().endsWith(
"EventDispatchThread")) {
EventQueue eq = null;
eq = Toolkit.getDefaultToolkit().getSystemEventQueue();
if (eq == null) {
return;
}
while (isVisible() || isShowing()) {
AWTEvent event = eq.getNextEvent();
Object src = event.getSource();
Class kActiveEvent= Class.forName("java.awt.ActiveEvent");
if (kActiveEvent != null) {
if (kActiveEvent.isInstance(event)) {
Method m;
Class types[] = {};
Object args[] = {};
m = kActiveEvent.getMethod("dispatch", types);
if (m != null) {
m.invoke(event, args);
continue;
}
}
}
dispatchEvent(src, event);
}
}
}
catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
private void dispatchEvent(Object src, AWTEvent event) {
if (event.getID()== MouseEvent.MOUSE_CLICKED) {
System.out.println("mouseClicked");
}
if (src instanceof Component) {
( (Component) src).dispatchEvent(event);
} else if (src instanceof MenuComponent) {
( (MenuComponent) src).dispatchEvent(event);
}
}
public void show(){
super.show();
consumeEvents();
}
public static void main(String[] args) {
FrmEvent frm = new FrmEvent();
frm.setBounds(300,300, 200, 200);
frm.show();
}
}