I can't get this MouseListener to work. Why? Nothing happens when I click th mouse
import acm.program.*;
import acm.graphics.*;
import java.awt.event.*;
/** Draws an oval whenever the user clicks the mouse */
public class DrawOvals extends GraphicsProgram implements MouseListener {
public void run() {
addMouseListener(this);
}
public void mouseClicked(MouseEvent e) {
GOval oval = new GOval(100,100,OVAL_SIZE, OVAL_SIZE);
oval.setFilled(true);
add(oval, e.getX(), e.getY());
System.out.println("Got here!");
}
/* Private constants */
private static final double OVAL_SIZE = 20;
/* implements the required methods for mouse listener*/
public void mouseEntered(MouseEvent arg0) {
// TODO Auto-generated method stub
}
public void mouseExited(MouseEvent arg0) {
// TODO Auto-generated method stub
}
}
According to the link you provided in the comments in the OP, you have to call
addMouseListeners();
instead of
addMouseListener(this);
The description says:
"Use the GraphicsProgram itself as a listener for mouse events that occur within the embedded GCanvas. To do so, all the student has to do is define any listener methods to which the program needs to respond and then call addMouseListeners(), which registers the program as both a MouseListener and MouseMotionListener."
The other option is to use
GCanvas canvas = getGCanvas();
canvas.addMouseListener(this);
Related
I want to make a Swing program with icon tiles that play certain sounds when you click on them. For this I created the class:
public class Item extends JLabel implements MouseListener {
public Item(String s) {
// constructor setting background icon and private field with the sound to play
}
public void playSound(); //plays the sound
#Override
public void mouseClicked(MouseEvent e) {
System.out.println("Clicked");
this.playSound();
}
#Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mousePressed(MouseEvent e) {
// TODO Auto-generated method stub
System.out.println("Pressed");
}
#Override
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub
}
}
Then I create a custom JFrame class:
public class Frame extends JFrame {
/**
*
*/
private static final long serialVersionUID = 9221468315661092752L;
public static final int DEFAULT_FRAME_WIDTH=400;
public static final int DEFAULT_FRAME_HEIGHT=400;
private GridLayout gridLayout;
private ArrayList<Item> tiles=new ArrayList<Item>();
public Frame() {
super("Title");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(new Dimension(DEFAULT_FRAME_WIDTH,DEFAULT_FRAME_HEIGHT));
gridLayout=new GridLayout(4,4,10,10);
setLayout(gridLayout);
addItems();
}
public void addItems() {
Item item=new Item("name");
Item item2=new Item("name");
tiles.add(item);
tiles.add(item2);
this.add(item);
this.add(item2);
}
public static void main(String[] args) {
Frame frame=new Frame();
frame.setVisible(true);
}
The tiles show normally in the grid layout, however the problem is that the mouse listener doesn't work. The println() I put at mouseClicked() and mousePressed() is not called.
I could try to add a MouseListener to the Item class, so that Item has a MouseListener, but I wonder what is wrong with the above code.
You have two problems. One, your JLabels do not show (although I'm not sure if that was intentionally left out). Two, you never add a mouse listener. You can accomplish this by adding two statements to the constructor, without making any extra classes:
public Item(String s) {
super(s); //initializes the text and display using JLabel's constructor
addMouseListener(this); //uses the reference of this Item as a MouseListener
}
I made a little color selector using JPanels and mouse listeners, but for some reason the result isn't as responsive as expected and I don't know why.
in order to do so I created a modified JPanel I called ColorPanel, to add it a few properties like color and color name, built in mouse listener, background color defined when instanciated etc:
public class ColorPanel extends JPanel{
private Color color;
private String sColor;
public ColorPanel(Color color, String sColor){
this.color = color;
this.sColor = sColor;
this.setBackground(color);
this.setBorder(BorderFactory.createLineBorder(Color.white));
this.addMouseListener(new appMouseListener());
ColorSelector.panSelector.add(this);
ColorSelector.vPanel.add(this);
}
public Color getColor(){
return this.color;
}
public String getScolor(){
return this.sColor;
}
class appMouseListener implements MouseListener {
#Override
public void mouseClicked(MouseEvent e) {
// TODO Auto-generated method stub
ColorSelector.select((ColorPanel)e.getSource());
}
#Override
public void mouseEntered(MouseEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void mouseExited(MouseEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void mousePressed(MouseEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void mouseReleased(MouseEvent arg0) {
// TODO Auto-generated method stub
}
}
}
this is linked to another object I made meant to instanciate all the panels I need and their countainer, as well as the method to change the selected colorpanels border color and store its coulour into a global variable.
While it works, every so often I got to click several times to select a colorpanel. The program had no responsiveness problem before and that selector is the only thing behaving this way.
public static void select(ColorPanel colorPanel) {
IhmMap.SelectedColor = colorPanel.getColor();
IhmMap.SelectedScolor = colorPanel.getScolor();
for(int i = 0 ; i<vPanel.size(); i++ ){
vPanel.elementAt(i).setBorder(BorderFactory.createLineBorder(Color.white));
}
colorPanel.setBorder(BorderFactory.createLineBorder(Color.red.darker().darker()));
}
This is the method, all the panels are added to a vector upon creation, so I can manipulate them easily.
MouseClicked event only fires if you didn't move the mouse at all between pressing and releasing the mouse. That way if you press the mouse button and move the mouse slightly just by 1 pixel, the mouseClicked won't get called.
I suggest using mouseReleased or a combination of mousePressed, mouseReleased and/or mouseExited. e.g.
private boolean pressed;
#Override
public void mouseExited(MouseEvent arg0) {
pressed = false;
}
#Override
public void mousePressed(MouseEvent arg0) {
pressed = true;
}
#Override
public void mouseReleased(MouseEvent arg0) {
if (pressed) {
//your code here
}
}
That way you can press on the ColorPanel and as long as you don't leave the ColorPanel it will register a click.
Here is a simplified version of my code
public class StateController extends GraphicsProgram {
public Menu menu = new Menu();
public void run() {
addMouseListeners();
addKeyListeners();
}
}
public class Menu {
int x = 0;
public void keyPressed(KeyEvent e) {
System.out.println(x);
}
public void mousePressed(MousEvent e) {
System.out.println(x);
}
}
The program detects when the mouse is pressed, but it does not print X when a key is. Can you see any problems?
Thank very much.
Assuming your code actually compiles and you implemented the KeyListener interface correctly, KeyEvents are only dispatched to components that have focus. Your StateController doesn't have focus.
By default a JPanel is not focusable. So I'm guessing your StateController class is extending JPanel. So you need to:
Make the panel focusable by using setFocusable(true) in the constructor of your class
Invoke panel.requestFocusInWindow() AFTER the GUI has been made visible. You can only request focus on a component in a visible GUI.
If you add listeners to your class, this class has to implement the listener interfaces in order to get the notifications:
public class StateController extends GraphicsProgram implements MouseListener, KeyListener
Or you do it on-the-fly:
yourUiElement.addKeyListener(new KeyListener() {
public void keyTyped(KeyEvent e) {}
public void keyReleased(KeyEvent e) {}
public void keyPressed(KeyEvent e) {
System.out.println(x);
}
});
I have a simple login frame with a JTextField and a JPasswordField. When my frame loads the text of the JTextField is "Typ your login". I want to erase that text when the JTextField gets focus. It's the first element in my frame so it already has focus when I load the frame, but I want it to clear whenever I click on it or start typing in it. I tried a MouseListener, which works fine, but now I'd like to clear the JTextField from the moment I start typing. This is the code involving my problem:
import java.awt.FlowLayout;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JFrame;
import javax.swing.JPasswordField;
import javax.swing.JTextField;
public class TextFields extends JFrame {
private static final long serialVersionUID = 1L;
private JTextField login;
private JPasswordField password;
public TextFields() {
super("Event handling");
setLayout(new FlowLayout());
login = new JTextField("Type your login", 20);
password = new JPasswordField(20);
add(login);
add(password);
LoginHandler handler = new LoginHandler();
login.addMouseListener(handler);
}
private class LoginHandler implements ActionListener, MouseListener {
public void mouseClicked(MouseEvent e) {
login.setText("");
}
#Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mousePressed(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void focusLost(FocusEvent arg0) {
// TODO Auto-generated method stub
}
}
public static void main(String[] args) {
TextFields test = new TextFields();
test.setDefaultCloseOperation(EXIT_ON_CLOSE);
test.setSize(250, 100);
test.setVisible(true);
}
}
I don't know the canonical answer, but I've used a FocusListener for this issue, by calling selectAll() in the focusGained method. Don't use a MouseListener since this will fail if the user tabs into the field.
e.g.,
private class MyFocusListener extends FocusAdapter {
#Override
public void focusGained(FocusEvent fEvt) {
JTextComponent component = (JTextComponent) fEvt.getSource();
component.selectAll();
}
}
and
login.addFocusListener(new MyFocusListener());
Conceptually, what you really want is to set a “placeholder” or “prompt” for your text field, rather than changing the actual text in the field. Such an abstraction would also give you features like being able to style the prompt a light gray color.
A normal JTextField does not support this, but you could write your own subclass, or use a library. This answer explains how to use the SwingX library to accomplish that. Basically, just import org.jdesktop.swingx.prompt.PromptSupport; and add this line:
PromptSupport.setPrompt("Type your login", login);
Which kind of listener do I have to add to a JFrame to detect when it is being hidden or shown via setVisible?
I tried using a WindowListener and the windowOpened and windowClosed methods, but they only work for the first time that a window is opened (windowOpened) or, respectively, when the window is closed using the dispose method (windowClosed). That is not enough for me. I want to be notified every time the window is made visible and invisible on the screen using setVisible.
Is there a standard Swing way to achieve this, or do I need to make my own (by, say, overriding the setVisible method)?
Try a java.awt.event.ComponentListener. You can add one using this code (where window is the name of the JFrame) :
window.addComponentListener(new ComponentAdapter() {
public void componentHidden(ComponentEvent e) {
/* code run when component hidden*/
}
public void componentShown(ComponentEvent e) {
/* code run when component shown */
}
});
1- Create a class that implements ComponentListener Interface, Like the following example:
//---------------------
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
public class winlistenner implements ComponentListener {
public void componentHidden(ComponentEvent arg0) {
// TODO Auto-generated method stub
System.out.print("Hided\r\n");
}
public void componentMoved(ComponentEvent arg0) {
// TODO Auto-generated method stub
System.out.print("Moved\r\n");
}
public void componentResized(ComponentEvent arg0) {
// TODO Auto-generated method stub
System.out.print("Resized\r\n");
}
public void componentShown(ComponentEvent arg0) {
// TODO Auto-generated method stub
System.out.print("Shown\r\n");
}
}
//------------------------------------------------------------------------
2- Now create a getter for your JFrame like this:
public class JMain {
private JFrame frmNetworkshareMoon;
private JTextField textField;
private JTextField textField_1;
private JTextField textField_2;
public JFrame getFrmNetworkshareMoon() {
return frmNetworkshareMoon;
}
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
JMain window = new JMain();
winlistenner listenner= new winlistenner();
window.getFrmNetworkshareMoon().addComponentListener(listenner);
window.frmNetworkshareMoon.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
//......
// the rest of your class code:
//...
}
3- being your main like the above example, you will set JFrame listener the listener you created, and then run the program, you will see messages coming from the listener:
Moved
Resized
Resized
Moved
Shown
Moved
Moved