We know that JComponent has several methods to add various listeners. One example is the addMouseMotionListneer().
Within a MouseMotionListener, there are 2 methods to be overridden:
public void mouseMoved(MouseEvent e){}
public void mouseDragged(MouseEvent e){}
Whenever the mouse is moved, mouseMoved() will be invoked.
My question is:
1) How does Java detects mouse movement? Is there a lot of lower level stuff (like communicating with mouse drivers..etc) where Java is doing behind our back?
2) I know if we want to detect mouse movements, we simply could use the event listeners in the awt. But is there any possibilities we could write our own listeners to detect mouse movement? Or we can simply forget about it as it is mission impossible?
Something like this might be what you need:
import java.awt.MouseInfo;
import java.awt.GridLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.MouseListener;
import java.awt.event.MouseEvent;
import javax.swing.*;
public class mice {
public static void main(String[] args) throws InterruptedException{
while(true){
//Thread.sleep(100);
System.out.println("("+MouseInfo.getPointerInfo().getLocation().x+", "+MouseInfo.getPointerInfo().getLocation().y+")");
}
}
you could use the event listeners of awt but that are not platform independent.
ON some platforms it will not work fine.
Yes could write our own listeners to detect mouse movement by implementing MouseMotionListener or MouseListener interface and add your custom methods for some special events
OR
you have to follow delegate event model. So create a class MyMouseEvent , MyMouse and interface MyMouseListner
interface MyMouseListener{
public void clicked();
}
Class MyMouse{
MyMouseListener m;
public void register(MyMouseListener m){
this.m=m;
}
}
class MyMouseEvent{
//use in case of multiple event listener
}
Then registered by creating object
MyMouse m = new MyMouse().register(new MyMouseListener(){
public void clicked(){
// your code here
}
})
Related
I've been using JFrame to learn graphics and test my code because I know it much better. Now I want to update to Javafx. I have this JListener class that handles all the buttons for my JFrame. Is it possible to still use this class with Javafx? If so how?
For example, with JFrame I could use Button.setActionCommand("command"); and when the button was pressed it would run this with the actionListener, can I do this same thing with javafx?
package src.com.Kingdom;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Scanner;
import java.net.*;
public class JListener implements ActionListener
{
private boolean registered = false;
registerClient register;
loginClient login;
static GUIs gui = new GUIs();
#Override
public void actionPerformed(ActionEvent e) {
switch(e.getActionCommand()) {
case("login"):
login = new loginClient(gui.getUsername(), gui.getPassword());
System.out.println("Login");
break;
case("exit"):
System.out.println("exit");
break;
case("register"):
System.out.println("register");
gui.getFrame().dispose();
gui.createRegisterGui();
break;
case("registerperson"):
if(gui.checkRegister()) {
if(hasInternet()) {
if(!(registered)) {
registered = true;
try {
register =
new registerClient(gui.getUsername(), gui.getPassword(), gui.getEmail(), gui.getAge());
} catch(Exception ex) {
GUIs.showError(ex.getMessage());
}
if(!(register.isRegistered())) {
gui.createLoginGui();
}
new Timer().schedule(new TimerTask() {
public void run() {
registered = false;
}
},1000*1);
}
} else {
GUIs.showError("No Internet! Please connect to internet to connect!");
}
} else {
GUIs.showError("Problem with registration format");
}
break;
}
}
}
It is technically possible to integrate JavaFX and Swing. Oracle provide a tutorial on this. I don't recommend integrating the two unless you really need to (which you probably don't in this case). Note that the level of integration possible is just embedding Swing Components into JavaFX nodes (or vice versa). You cannot directly use a Swing listener to take action on a JavaFX button press.
Instead, I recommend that you write your code native to a single library, either JavaFX or Swing.
For your example code. The JavaFX equivalent for handling button actions is:
button.setOnAction(EventHandler<ActionEvent>)
How would I set the String for the action command? Is this possible? Or do I have to do it a different way?
You wouldn't, it's not necessary.
I don't code Swing, so I'm not familiar with the Swing ActionEvent. From looking at your code, your listener seems to be providing a single point for handling multiple action events which originate from different sources, then acting on them.
For JavaFX, just define separate event handlers for each source rather than using switches, then you don't need to pass a string to the action command because it is clear what action is to be taken based upon the context.
For instance:
loginButton.setOnAction(event -> { /** handle login **/});
exitButton.setOnAction(event -> { /** handle exit **/});
If you have multiple ways to trigger the actions, for instance an exit could be triggered by both a menu item and a button, then you can define a variable for the action handler and reuse that for each instance, for instance:
EventHandler<ActionEvent> exitHandler = event -> { /** handle exit **/ };
exitButton.setOnAction(exitHandler);
exitMenuItem.setOnAction(exitHandler);
On the Linux platform, Frame::getBounds and Frame::setBounds do not work consistently. This has already been reported in 2003(!), see here:
http://bugs.java.com/bugdatabase/view_bug.do?bug_id=4806603
For convenience, I have simplified the stated code that results in a bug and paste it as:
import java.awt.Button;
import java.awt.Frame;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
/** Demonstrates a bug in the java.awt.Frame.getBounds() method.
* #author Mirko Raner, PTSC
* #version 1.0 (2003-01-22) **/
public class GetBoundsBug extends Frame implements ActionListener {
public static void main(String[] arg) {
GetBoundsBug frame = new GetBoundsBug();
Button button = new Button("Click here!");
button.addActionListener(frame);
frame.add(button);
frame.setSize(300, 300);
frame.setVisible(true);
}
#Override
public void actionPerformed(ActionEvent event) {
Rectangle bounds = getBounds();
bounds.y--;
setBounds(bounds);
bounds.y++;
setBounds(bounds);
}
}
Unexpected behavior: Upon clicking the button the window is shifted slightly below! (On my system by 28 pixels each click.)
Here is a screen recording: https://youtu.be/4qOf99LJOf8
This behavior has been around for 13+ years, so probably there won't be any change from the official side.
Does anybody have a workaround for this bug? Specifically, I would like to store and restore the window/frame/dialog at the previous location reliably on all platforms.
PS: My java installation is jdk1.8.0_102 for amd64 by Oracle on Ubuntu 16 Linux. Since I recently migrated from Windows to Ubuntu, I know that on Windows, the code above works as expected.
The adaptation to Swing using SwingWorker produces the same effect:
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingWorker;
public class GetBoundsBug extends JFrame implements ActionListener {
public static void main(String[] arg) {
GetBoundsBug myJFrame = new GetBoundsBug();
JButton myJButton = new JButton("Click here!");
myJButton.addActionListener(myJFrame);
myJFrame.setContentPane(myJButton);
myJFrame.setSize(300, 300);
myJFrame.setVisible(true);
}
#Override
public void actionPerformed(ActionEvent event) {
SwingWorker<Void, Void> mySwingWorker = new SwingWorker<Void, Void>() {
#Override
public Void doInBackground() {
Rectangle myRectangle = getBounds();
myRectangle.y--;
setBounds(myRectangle);
myRectangle.y++;
setBounds(myRectangle);
return null;
}
};
mySwingWorker.execute();
}
}
Well, in the original bug database entry this is marked as "Won't fix" and explained as a quirk in the window manager, rather than the JDK.
What window manager are you using?
Just an additional note. I noticed that your code failed to do very much on the Event Dispatch Thread. All of Java's drawing APIs are single threaded by design, meaning that your application should not be expected to work correctly unless you dispatch GUI updates to the Event Dispatch Thread.
This means you need to (in your main) create a new Runnable that when evaluated will present your widgets, and submit that to the EDT.
Also, your action listener updates the component state within the action, bypassing the repaint request and ignoring the typical safeties required to ensure dispatch to the EDT.
In both of these ways, you code is not valid GUI code in a Java environment, and the bug that you identify may have nothing to do with your behavior, as your program is violating the GUI toolkit design before you even know if the bug impacts it.
Also, awt only wraps components. If the components lie, then the lie trickles into Java. Not much can be done about that (but I no longer think it's the primary thing to worry about). If you don't like that, use Swing, which is a much more sane / stable environment.
I'm currently working on an application for work that has a main JFrame that always exists. I currently have a child JDialog that shows up on a button press. This frame has a JMenu with an item to "log out of the display." I've been tasked to ensure this child JDialog goes away when the log out of the display option is pressed. When the logout occurs, the main display is set invisible via:
mainFrame.setVisible(false);
The child JDialog has the default close operation:
DISPONSE_ON_CLOSE
When the user logs back in, the first thing that's done is:
mainFrame.setVisible(true);
When this happens, the child dialog shows back up. Looking at the JDialog Javadoc, this seems to be expected behavior. However I haven't found a way to break the parent/child releationship or completely destroy the child JDialog. It also seems like the JDialog will remain until it has been GC, which may not happen in a timely manner.
Here is a sample program that simulates the behavior I'm seeing:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JToggleButton;
import javax.swing.SwingUtilities;
public class WindowTest {
public static void createAndShowGUI() {
JFrame aFrame = new JFrame("LAUNCHER");
final JFrame aParent = new JFrame("PARENT");
final JDialog aChild = new JDialog(aParent);
aParent.setSize(200,200);
final JToggleButton showParentButton = new JToggleButton("HIDE");
showParentButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
showParentButton.setText(!showParentButton.isSelected() ? "SHOW": "HIDE");
aParent.setVisible(!showParentButton.isSelected());
}
});
aChild.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
aChild.setSize(200,200);
aParent.addComponentListener(new ComponentAdapter() {
public void componentHidden(ComponentEvent e) {
aChild.dispose();
aChild.setVisible(false);
}
});
aFrame.setContentPane(showParentButton);
aFrame.pack();
aFrame.setVisible(true);
aParent.setVisible(true);
aChild.setVisible(true);
}
public static void main(String [] args) {
SwingUtilities.invokeLater(new Runnable(){
public void run() {
createAndShowGUI();
}
});
}
}
When the parent is hidden, the child is disposed. When the parent is shown, the child shows back up. What's really weird is that when I press the X on the child: when the parent is hidden and then shown again, the child does not show back up.
The only difference I see is that clicking the X also fires a WindowClosing event. I tried the dispatch the even, in the componentHidden method above by:
//Added into the constructor
//add to the imports: import java.awt.event.WindowEvent;
aParent.addComponentListener(new ComponentAdapter() {
public void componentHidden(ComponentEvent e) {
aChild.dispose();
aChild.setVisible(false);
WindowEvent closingEvent =
new WindowEvent(aChild, WindowEvent.WINDOW_CLOSING);
aChild.dispatchEvent(closingEvent);
}
});
And that didn't solve the problem.
Currently it looks like my only option is to change the type of child to a JFrame. I just wanted to know if there was a proper way of disposing a child JDialog.
I'm currently running with Java version: 1.7.0_76 64 bit on Redhat Enterprise Linux Server release 6.4.
I wasn't aware the naming conventions affected the compile.
It doesn't. Conventions are done for consistency and readability and maintainability. The person who writes the code is not always the person that maintains the code. So if you want other people to read your code, especially when asking for help, follow the standards.
You can start with Java Programming Style Guidelines
I'm copying the code by hand from another screen per my companies standards.
This is a complete waste of time. There is nothing proprietary about your code. Again when you ask a question, the code should be in the form of a SSCCE so it demonstrates the problem. This allows you to remove all the unnecessary code.
it would be straight forward to figure out the imports.
Exactly, so you should do it. You want us to help you, so why should we spend the time figuring it out??? Make is as easy as possible for people to want to help you.
Adding the imports did not help. The code you posted still does not compile so I don't know if it accurately reflects the problem you are attempting to describe.
Again the point of posting code is so that we can copy/paste/compile/test. Until you post a proper SSCCE I will not provide the answer.
Edit:
From my testing, if the visibility of the child window is changed by the visibility of the parent when the parent is made non-visible, then the visibility of the child is also changed by the parent when it is made visible. So it looks like the parent is retaining the state of the child windows when the visibility changes.
So the solution is to make the child window non-visible before the parent:
showParentButton.setText(!showParentButton.isSelected() ? "SHOW": "HIDE");
aChild.setVisible(false); // add this
aParent.setVisible(!showParentButton.isSelected());
If you don't have a reference to the child window then I guess you can use the Windows.getOwnedWindows() method to access all the child windows.
Another edit:
As a hack I created a custom dialog that can't be shown again once it is disposed:
final JDialog aChild = new JDialog(aParent)
{
private boolean disposed = false;
#Override
public void dispose()
{
super.dispose();
disposed = true;
}
#Override
public void show()
{
if (disposed)
return;
super.show();
}
};
I found the method addAWTKeyListener in the class Toolkit, but I can't get it to work properly, whether or not the window has focus. My code is as follows:
import java.awt.AWTEvent;
import java.awt.Toolkit;
import java.awt.event.AWTEventListener;
import java.awt.event.KeyEvent;
public class KeyTest {
public static void main(String[] args){
Thread t = new Thread(){
#Override
public void run() {
System.out.println("STARTING");
Toolkit kit = Toolkit.getDefaultToolkit();
kit.addAWTEventListener(new AWTEventListener(){
#Override
public void eventDispatched(AWTEvent event) {
System.out.println("EVENT");
if(event instanceof KeyEvent){
KeyEvent kEvent = (KeyEvent) event;
System.out.println(kEvent.getKeyCode());
}
}
}, AWTEvent.KEY_EVENT_MASK);
while(true);
}
};
t.start();
}
}
Is there something I'm doing wrong? I get to the point that STARTING prints and there are no errors. The even is simply not called.
I may be wrong as I'm certainly not an expert, but as far as I know what you're trying to do isn't possible in Java.
Are you trying to capture a key click using a Java program, but without creating a window? Part of Java's security, and this is what I may be wrong on, is that it can only listen to events inside Java windows created by that particular Java program.
So if you were trying to make something key-logger-esque that runs in the background and captured a key press, it wouldn't be able to do that.
I wish I could give you a more concrete answer but I hope this helped.
Just a guess, but you your sample doesn't have any AWT windows in it, so I'm guessing that is why the event never gets fired.
When you say "whether or not the window has focus" does your real app have windows that you have chopped out, or are you talking about a java console window or similar?
I am currently learning java and would like to know how to control state in a OO way. I implemented a Pong app. If I wanted multiple states like gameplay and menu, and each one of these states had to execute start, stop and run how would I achieve this and how would I switch between these states.
I know I could simply throw in a big switch statement but what's the best way to implement this?
I want to be able to switch to the menu state in the gameplay state and vice versa.
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
public class Pong extends Applet implements Runnable, KeyListener{
public void start ()
{
setSize(screen);
setFocusable(true);
Thread th = new Thread (this);
th.start ();
}
public void stop()
{
}
//Etc..
}
You can simulate a basic FSM (Finite State Machine) using enums:
public enum State {
ONE {
#Override
public Set<State> possibleFollowUps() {
return EnumSet.of(TWO, THREE);
}
},
TWO {
#Override
public Set<State> possibleFollowUps() {
return EnumSet.of(THREE);
}
},
THREE // final state
;
public Set<State> possibleFollowUps() {
return EnumSet.noneOf(State.class);
}
}
While the code to generate this will be very verbose if things get more complicated, the nice part is that you get compile-time safety, thread-safety and high performance.
You don't have to do it yourself, here is a very simple but powerful state machine implementation based on Java8 that you can utilize directly:
https://github.com/swiftech/SWState