i am in trouble with checking if the mouse has clicked with a JFrame. When i use public void mousePressed(MouseEvent e) to print something and i click with the mouse it doesn't print anything. It doesn't gives a error, it just prints nothing out. Here is my code :
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
public class tuna extends JFrame
{
private JTextArea textArea;
public static void main(String[] args)
{
//Run the program
tuna run = new tuna();
run.setDefaultCloseOperation(3);
run.setSize(1200, 1000);
run.setVisible(true);
}
public tuna()
{
super("Simple JFrame");
//add a simple JScrollPane
textArea = new JTextArea(10,10);
JScrollPane scrollPane = new JScrollPane(textArea);
textArea.setEditable(true);
add(scrollPane);
}
//This doesn't print anything when i am clicking in the JFrame
public void mousePressed(MouseEvent e)
{
if(e.getButton() == MouseEvent.BUTTON1)
{
System.out.println("left");
}
else if(e.getButton() == MouseEvent.BUTTON3)
{
System.out.println("right");
}
}
}
Thank you in advance.
You can make you own Mouse Listener and add it to textArea or another component.
For example like this:
public class tuna extends JFrame
{
private JTextArea textArea;
public static void main(String[] args)
{
//Run the program
tuna run = new tuna();
run.setDefaultCloseOperation(3);
run.setSize(1200, 1000);
run.setVisible(true);
}
public tuna()
{
super("Simple JFrame");
//add a simple JScrollPane
textArea = new JTextArea(10,10);
JScrollPane scrollPane = new JScrollPane(textArea);
textArea.setEditable(true);
textArea.addMouseListener(new CustomListener());
add(scrollPane);
}
//This doesn't print anything when i am clicking in the JFrame
public class CustomListener implements MouseListener {
#Override
public void mouseClicked(MouseEvent mouseEvent) {
if(mouseEvent.getButton() == MouseEvent.BUTTON1)
{
System.out.println("left");
}
else if(mouseEvent.getButton() == MouseEvent.BUTTON3)
{
System.out.println("right");
}
}
#Override
public void mousePressed(MouseEvent mouseEvent) {
}
#Override
public void mouseReleased(MouseEvent mouseEvent) {
}
#Override
public void mouseEntered(MouseEvent mouseEvent) {
}
#Override
public void mouseExited(MouseEvent mouseEvent) {
}
}
}
Well there are few issues, in your concept and source code
First you need a MouseListener, so in your case either you can
create a separate MouseListener or use the current JFrame class
itself, like this
public class Tuna extends JFrame implements MouseListener
Also I would recommend to follow proper naming convention and use Tuna instead of tuna.
Then the element you want to respond on the MouseEvents should be
register with the MouseListener created in first step, in your constructor.
textArea.addMouseListener(this);
Also make sure on what element you want to register your
MouseListener, currently your entire Frame is covered by TextArea,
so registering listener on JFrame won't help, instead add it on
JTextArea
Try using #Override annotation where ever possible, editor shows
appropriate compiler errors then, in your case you just wrote,
public void mousePressed(MouseEvent e)
instead of
#Override
public void mousePressed(MouseEvent e)
As this methods works only if you implement an MouseListener
Refer this link for more understanding,
https://docs.oracle.com/javase/tutorial/uiswing/events/mouselistener.html
Related
I am trying to do something when one of the arrow keys are pressed using the KeyListener in my JPanel class. Here is my code:
public class TestPanel extends JPanel implements KeyListener{
public TestPanel(){
this.addKeyListener(this);
this.setFocusable(true);
this.requestFocusInWindow();
}
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
System.out.println("Right");
}
if (e.getKeyCode() == KeyEvent.VK_LEFT) {
System.out.println("Left");
}
}
public void keyTyped(KeyEvent e) {}
public void keyReleased(KeyEvent e) {}
}
My main method adds a new instance of this panel to a frame and displays it. Do I need to add the keylistener to the JFrame? In my case, this would be difficult and inefficient, so I would like to make it work with this JPanel if possible. Anyone know what I am doing wrong?
EDIT: Key Bindings code that does not work either:
public class GamePanel extends JPanel implements ActionListener{
//Constructor
public GamePanel(){
setupKeyBinding();
this.setFocusable(true);
this.requestFocusInWindow();
}
private void setupKeyBinding() {
int condition = JComponent.WHEN_IN_FOCUSED_WINDOW;
InputMap inMap = getInputMap(condition);
ActionMap actMap = getActionMap();
inMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), "Left");
actMap.put("Left", new leftAction());
}
private class leftAction extends AbstractAction {
public void actionPerformed(ActionEvent e) {
System.out.println("test");
}
}
public void actionPerformed(ActionEvent e) {
//some other game info
}
}
Can someone tell me why this doesnt work either? (my second action listener is for other stuff needed for my game)
If you search this problem, you'll see that it is asked and has been solved many times.
KeyListeners need to be on the focused component to work. One solution is to give your component the focus after first making it focusable.
Better by a long shot however is to use Key Bindings. Google the tutorial on this.
Please have a look at my answer to this question for more on this, including many of the gory details.
For reference, I've create an example using your approach; while it works, it also suggests a focus problem elsewhere in your code. Key Bindings avoid this, as shown here.
Addendum: Here's my working key binding.
private static class TestPanel extends JPanel {
private static final String LEFT = "Left";
private Action left = new AbstractAction(LEFT) {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println(LEFT);
}
};
private static final String RIGHT = "Right";
private Action right = new AbstractAction(RIGHT) {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println(RIGHT);
}
};
public TestPanel() {
this.getInputMap().put(
KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), LEFT);
this.getActionMap().put(LEFT, left);
this.getInputMap().put(
KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), RIGHT);
this.getActionMap().put(RIGHT, right);
}
}
Original SSCCE:
import java.awt.EventQueue;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
/**
* #see https://stackoverflow.com/a/16531380/230513
*/
public class Test {
private void display() {
JFrame f = new JFrame("Test");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new TestPanel());
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
private static class TestPanel extends JPanel implements KeyListener {
public TestPanel() {
this.addKeyListener(this);
this.setFocusable(true);
this.requestFocusInWindow();
}
#Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
System.out.println("Right");
}
if (e.getKeyCode() == KeyEvent.VK_LEFT) {
System.out.println("Left");
}
}
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyReleased(KeyEvent e) {
}
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new Test().display();
}
});
}
}
For receives key events on JPanel you must set focus:
setFocusable(true);
requestFocus();
the JPanel now has focus, so it receives key events
I had to do two things: I added comp.setFocusable(true); to the component comp that listens to key events, and I added comp.requestFocus(); to each action which caused comp to lose the focus.
I'm working on a small personal project.
I have two JFrame windows, Viewer and Console.
Viewer only contains a subclass of JPanel, and it should respond to mouse input (clicking, mostly).
Console contains a button, a JTextField (the input), and a JTextArea (the output).
I need to make sure than when I press keys on my keyboard, the corresponding text appears in the Console JTextField, not only when the focus is held by the JTextField, but also when it's held any other component in my app.
In other words, I want the JTextField to accept input even right after I clicked on the Viewer frame.
Is this feasible?
In case that matters, I'm running win 8 x64 and I don't really care about portability (I'm the only one that will ever look at or use this code).
EDIT: here is an example of my code:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class main {
public static Viewer v;
public static Console c;
public static void main(String[] args) {
v=new Viewer();
c=new Console();
}
static class Viewer extends JFrame {
public Viewer(){
setSize(600,600);
getContentPane().add(new myPanel());
addMouseListener(new mouse());
setVisible(true);
}
}
static class myPanel extends JPanel{
public void paintComponent(Graphics g){
g.setColor(new Color((int)(Math.random()*255),(int)(Math.random()*255),(int)(Math.random()*255)));
g.fillRect(0, 0, 600, 600);
}
}
static class Console extends JFrame {
public Console(){
setSize(600,200);
JTextField text=new JTextField();
getContentPane().add(text);
setVisible(true);
}
}
static class mouse implements MouseListener{
#Override
public void mouseClicked(MouseEvent arg0) {
v.repaint();
}
#Override
public void mouseEntered(MouseEvent arg0) {
}
#Override
public void mouseExited(MouseEvent arg0) {
}
#Override
public void mousePressed(MouseEvent arg0) {
}
#Override
public void mouseReleased(MouseEvent arg0) {
}
}
}
In this example, after I click on the big window to change its color, if I want to write stuff in the other window I have to click on it first.
Can I suggest the KeyboardFocusManager? I've found this to be the easiest way to achieve what I believe you are trying to achieve
KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(
new KeyEventDispatcher() {
public void dispatchKeyEvent(KeyEvent ke) {
//TODO: fill this in
}
});
One inelegant solution is to create a KeyListener, which feeds typed characters to your console, although how exactly this happens depends on how you create your components. For the sake of this example I'll pretend to do it through a static method in your Console class (preferably you'd have access to an instance of Console):
public class ApplicationKeyListener implements KeyListener {
public ApplicationKeyListener() {
}
// Other necessary methods...
public void keyPressed(KeyEvent e) {
char pressed = e.getKeyChar();
Console.feedChar(pressed);
}
}
And then in Console, make sure your JTextField object is global and static, then set up the feedChar() method.
public class Console extends JFrame {
private static JTextField consoleTextField;
public Console() {
consoleTextField = new JTextField();
// ...
}
public static feedChar(char c) {
consoleTextField.setText(consoleTextField.getText() + c.toString());
}
}
Then finally you'd have to add this listener to all JFrames and their children.
public class Viewer extends JFrame {
public Viewer() {
ApplicationKeyListener kl = new ApplicationKeyListener();
addKeyListener(kl);
for (Component child : this.getComponents()) {
child.addKeyListener(kl);
}
}
}
I need help to understand the event propagation in Swing. I know that each event is handled by only one component. Thus, when I have a panel outside with some child panel inside and I add mouseListeners to both of them, the one of inside will be called. That's nice and that's the expected behavior.
But I don't understand the behavior in the following situation:
inside registers a MouseMotionListener and outside registers a MouseListener. I expect inside to consume all MouseMotionEvents and outside to receive the MouseEvents, because there is no listener for normal MouseEvents on inside. But that's not the case, inside somehow consumes all MouseEvents not only the MouseMotionEvents.
The following code illustrates the problem:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class EventTest {
public static void main(String... args) {
SwingUtilities.invokeLater(new Runnable(){
#Override
public void run() {
JComponent inside = new JPanel();
inside.setBackground(Color.red);
inside.setPreferredSize(new Dimension(200,200));
MouseMotionListener mm = new MouseMotionListener() {
#Override
public void mouseDragged(MouseEvent arg0) {
System.err.println("dragged");
}
#Override
public void mouseMoved(MouseEvent arg0) {
System.err.println("moved");
}
};
// next line disables handling of mouse clicked events in outside
inside.addMouseMotionListener(mm);
JComponent outside = new JPanel();
outside.add(inside);
outside.setPreferredSize(new Dimension(300,300));
outside.addMouseListener( new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
System.err.println("clicked");
}
});
JFrame frame = new JFrame();
frame.add(outside);
frame.pack();
frame.setVisible(true);
}
});
}
}
I could work around the problem by registering a listeners on inside for all events the parent component might be interested in and then calling dispatchEvent to forward the event to the parent.
a) can someone point me to some docs, where this behavior is described? The javadocs of MouseEvent made me think that my expectations were right. So, I need a different description to understand it.
b) is there a better solution than the one sketched above?
Thanks,
Kathrin
Edit: It is still unclear, why Swing behaves this way. But as it looks, the only way to get the stuff working is to manually forward the events, I will do it.
a) By design, Java mouse events "bubble up" only if there in no mouse listener on the child component.
b) You can forward events to another component, as shown here and below.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class EventTest {
public static void main(String... args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
final JComponent outside = new JPanel();
JComponent inside = new JPanel();
inside.setBackground(Color.red);
inside.setPreferredSize(new Dimension(200, 200));
inside.addMouseMotionListener(new MouseAdapter() {
#Override
public void mouseDragged(MouseEvent e) {
System.err.println("dragged");
}
#Override
public void mouseMoved(MouseEvent e) {
System.err.println("moved inside");
outside.dispatchEvent(e);
}
});
outside.add(inside);
outside.setPreferredSize(new Dimension(300, 300));
outside.addMouseMotionListener(new MouseAdapter() {
#Override
public void mouseMoved(MouseEvent arg0) {
System.err.println("moved outside");
}
});
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(outside);
frame.pack();
frame.setVisible(true);
}
});
}
}
Very similar to trashgod's answer - you can use a MouseAdapter as your motion listener, and override it to forward any events you want to be handled by the parent. This should only add a minimal amount to your code.
MouseAdapter mm = new MouseAdapter() {
#Override
public void mouseDragged(MouseEvent arg0) {
System.err.println("dragged");
}
#Override
public void mouseMoved(MouseEvent arg0) {
System.err.println("moved");
}
#Override
public void mouseClicked(MouseEvent e) {
outside.dispatchEvent(e);
}
};
// For forwarding events
inside.addMouseListener(mm);
// For consuming events you care about
inside.addMouseMotionListener(mm);
I too couldn't find any way around using the dispatchEvent(e) method. I think you're stuck with that route.
This worked out for me:
Ellipse2D mCircle = new Ellipse2D.Double(x,y,size,size);
void PassMouseEvent(MouseEvent e) {
getParent().dispatchEvent(e);
}
public void mousePressed(MouseEvent arg0) {
if(mCircle.contains(arg0.getX(), arg0.getY())) {
// Do stuff if we click on this object
} else {
// Pass to the underlying object to deal with the mouse event
PassMouseEvent(arg0);
}
}
I am really struggling with making a program that has buttons on it and when a button is clicked, it calls a class to work. I have only been using Java for about 10 weeks now and I get the basics but I have not found any place that gives me an understanding of what I want to do here.
I have tried
public void mouseEntered(MouseEvent e) {
if (e.getButton()== MouseEvent.BUTTON3){
Object triangle;
Frame.class.getClass();
}
}
I have also tried
panel.addMouseListener(new MouseAdapter() {
if (e.getButton()== MouseEvent.BUTTON1) {
Frame.class.getClass(circle); }
Either way I have tried it I usually get an error unable to find object or The method getClass() in the type Objectis not applicable for the arguments (JButton).
Can anyone please help me try to figure out what I am doing wrong?
Thank you.
public class MainFrame extends JFrame {
private JButton button = new JButton("Run AnotherClass");
MainFrame() {
super();
this.setTitle("Demo App");
this.setSize(200,200);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLayout(new FlowLayout());
this.add(button);
button.addActionListener(new ButtonHandler());
}
public class ButtonHandler implements ActionListener {
public void actionPerformed(ActionEvent e) {
new AnotherClass();
}
}
public static void main(String[] args) {
new MainFrame().setVisible(true);
}
}
public class AnotherClass {
public AnotherClass() {
JOptionPane.showMessageDialog(null, "AnotherClass is in operation");
}
}
My problem is when I right click on the JFrame in the example below, the JPopupMenu shows up but if I click anywhere outside the JFrame, the menu does not disappear. I have to click somewhere on the JFrame to get rid of it which is not the expected behavior. Here are the steps to reproduce:
Run the window class from Eclipse (JFrame appears)
Click into the Eclipse workspace (JFrame loses focus and is hidden behind eclipse)
Minimize Eclipse (JFrame appears)
Go with your mouse over JFrame and make a right click (Popup appears)
Click somewhere (Not into JFrame or Popup). The Popup will not disappear
I'm running OS X 10.6.7 and Java full version 1.6.0_24-b07-334
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
class test
{
static class window extends JFrame implements MouseListener,
MouseMotionListener
{
JPopupMenu popMenu;
JPanel panel = new JPanel();
Point location;
MouseEvent pressed;
public window()
{
addMouseListener(this);
addMouseMotionListener(this);
JLabel label = new JLabel("JFrame", JLabel.CENTER);
initPopMenu();
add(label);
setUndecorated(true);
setVisible(true);
// setAlwaysOnTop(true);
setLocationRelativeTo(null);
pack();
}
public void initPopMenu()
{
popMenu = new JPopupMenu();
JMenuItem item;
item = new JMenuItem("Title");
item.setEnabled(false);
popMenu.add(item);
popMenu.addSeparator();
item = new JMenuItem("Item One");
popMenu.add(item);
item = new JMenuItem("Item 2");
popMenu.add(item);
item = new JMenuItem("Item 3");
popMenu.add(item);
}
public void mousePressed(MouseEvent e)
{
pressed = e;
int nModifier = e.getModifiers();
if (((nModifier & InputEvent.BUTTON2_MASK) != 0)
|| ((nModifier & InputEvent.BUTTON3_MASK) != 0))
popMenu.show( this, e.getX(), e.getY() );
}
public void mouseClicked(MouseEvent e)
{
}
public void mouseReleased(MouseEvent e)
{
}
public void mouseDragged(MouseEvent me)
{
}
public void mouseMoved(MouseEvent e)
{
}
public void mouseEntered(MouseEvent e)
{
}
public void mouseExited(MouseEvent e)
{
}
}
public static void main(String[] args)
{
window dw = new window();
}
}
you can add a windowFocusListener, hide the menu when window lost focus
this.addWindowFocusListener(new WindowFocusListener() {
#Override
public void windowLostFocus(WindowEvent e) {
if(popMenu != null){
popMenu.setVisible(false);
}
}
#Override
public void windowGainedFocus(WindowEvent e) {
//System.out.println(e);
}
});