MouseListener on JFrame never being called - java

I'm trying to use a MouseListener to see when something is clicked in my JFrame, but none of the events (mouseClicked, mouseEntered, etc) are ever called. I'm using a Canvas to draw the game onto the JFrame and I'm wondering if that could be the issue, but I'm not sure how to fix it. I was following this tutorial and my code looks almost exactly the same.
Here's my JFrame class:
public class Display extends JFrame implements MouseListener {
public static int width;
public static int height;
public static final int CARD_SIZE = 100;
public static final int BUFFER_SIZE = 25;
public static final int TITLE_SIZE = 50;
private JFrame frame;
private MyCanvas canvas;
public Display (int r, int c, Card[][] b) {
width = c*CARD_SIZE + (c+2)*BUFFER_SIZE;
System.out.println(width);
height = r*CARD_SIZE + (r+1)*BUFFER_SIZE + TITLE_SIZE*2;
System.out.println(height);
frame = new JFrame("Matching Game");
frame.setLayout(null);
frame.setSize(width, height);
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setFocusable(true);
frame.addMouseListener(this);
canvas = new MyCanvas(b);
frame.add(canvas);
frame.setVisible(true);
}
#Override
public void mouseClicked(MouseEvent e) {
System.out.println("Mouse Clicked at X: " + e.getX() + " - Y: " + e.getY());
}
#Override
public void mouseEntered(MouseEvent e) {
System.out.println("Mouse Entered frame at X: " + e.getX() + " - Y: " + e.getY());
}
#Override
public void mouseExited(MouseEvent e) {
System.out.println("Mouse Exited frame at X: " + e.getX() + " - Y: " + e.getY());
}
#Override
public void mousePressed(MouseEvent e) {
System.out.println("Mouse Pressed at X: " + e.getX() + " - Y: " + e.getY());
}
#Override
public void mouseReleased(MouseEvent e) {
System.out.println("Mouse Released at X: " + e.getX() + " - Y: " + e.getY());
}
}

The primary thing you were doing wrong was to extend JFrame and also create an explicit instance of one. Do it as follows.
import java.awt.Dimension;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Display implements MouseListener {
public static int width;
public static int height;
public static final int CARD_SIZE = 100;
public static final int BUFFER_SIZE = 25;
public static final int TITLE_SIZE = 50;
private JPanel canvas;
private JFrame frame;
public static void main(String[] args) {
new Display(3,3,new int[3][3]);
}
public Display (int r, int c, int[][] b) {
width = c*CARD_SIZE + (c+2)*BUFFER_SIZE;
System.out.println(width);
height = r*CARD_SIZE + (r+1)*BUFFER_SIZE + TITLE_SIZE*2;
System.out.println(height);
frame = new JFrame("Matching Game");
// frame.setLayout(null);
// frame.setSize(width, height);
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setFocusable(true);
frame.addMouseListener(this);
canvas = new JPanel();
canvas.setPreferredSize(new Dimension(width,height));
frame.add(canvas);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
#Override
public void mouseClicked(MouseEvent e) {
System.out.println("Mouse Clicked at X: " + e.getX() + " - Y: " + e.getY());
}
#Override
public void mouseEntered(MouseEvent e) {
System.out.println("Mouse Entered frame at X: " + e.getX() + " - Y: " + e.getY());
}
#Override
public void mouseExited(MouseEvent e) {
System.out.println("Mouse Exited frame at X: " + e.getX() + " - Y: " + e.getY());
}
#Override
public void mousePressed(MouseEvent e) {
System.out.println("Mouse Pressed at X: " + e.getX() + " - Y: " + e.getY());
}
#Override
public void mouseReleased(MouseEvent e) {
System.out.println("Mouse Released at X: " + e.getX() + " - Y: " + e.getY());
}
}
Points to consider
don't extend JFrame, just use an instance.
Canvas is old. I recommend using a JPanel to hold the components and/or painting
frame.setLocationRelativeTo(null) centers your frame on the screen.
Since I don't have the Card class I used int[][] to demonstrate this.
Anything else I did, check out the API documentation for explanations.
For more on GUI's, etc, check out the Java Tutorials

Related

Why changing the bg color of a JLabel opens another JFrame

So I'm trying to create a chess game in JAVA (self-learning).
I used JFrame to create a frame, JPanel to add it to the frame and JLabel to define the tiles of the chess board.
I want to change the color of a tile by clicking it and I'm using something like this:
This is the method for mouse click.
#Override
public void mouseClicked(MouseEvent e) {
this.x = e.getX();
this.y = e.getY();
System.out.println("X: " + this.x + "; Y:" + this.y);
GUI GUIOBject = new GUI();
GUIOBject.clickOnTile(this.x, this.y);
}
The function called here, GUIObject.clickOnTile(int x, int y); is this:
public void clickOnTile(int x, int y){
this.labels[x/60 + y/60*8].setBackground(Color.blue);
}
The problem is that doing this I get a new window each time a click somewhere.
So when I click on a tile, it colors the right tile, but by opening a new tile.
Any idea why is this and how can I make changes only in that frame?
This is the entire source code:
Main.java
public static void main(String[] args){
GUI graphic_user_interface = new GUI();
}
GUI.java:
public JFrame frame;
public JPanel panel;
public JLabel[] labels;
public String[] positions = {"a", "b", "c", "d", "e", "f", "g", "h"};
public GUI(){
this.createFrame();
this.createPanel();
this.createLabels();
this.addPanel();
this.addLabels();
this.setFrameVisible();
}
public void clickOnTile(int x, int y){
this.labels[x/60 + y/60*8].setBackground(Color.blue);
}
#Override
public void createFrame() {
this.frame = new JFrame();
this.frame.setSize(500, 500);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
#Override
public void createPanel() {
this.panel = new JPanel();
this.panel.setLayout(new GridLayout(8,8));
JPanel panel = new JPanel();
}
private void createLabels(){
this.labels = new JLabel[64];
for (int i = 0; i < 8; i++) {
for (int j = 0; j <8; j++) {
this.labels[i*8 + j] = new JLabel(this.positions[j] + (i+1));
this.labels[i*8 + j].setBounds(i*10, i*10, 50, 50);
this.labels[i*8 + j].setBorder(BorderFactory.createEtchedBorder(1));
this.labels[i*8 + j].setOpaque(true);
if(i%2 == 0){
if(j%2 == 0){
this.labels[i*8 + j].setBackground(Color.black);
}else{
this.labels[i*8 + j].setBackground(Color.white);
}
}else{
if(j%2 == 1){
this.labels[i*8 + j].setBackground(Color.black);
}else{
this.labels[i*8 + j].setBackground(Color.white);
}
}
}
}
}
private void addPanel(){
this.frame.add(this.panel);
}
private void addLabels(){
for (int i = 0; i < 64; i++) {
this.panel.add(this.labels[i]);
}
}
private void setFrameVisible(){
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
this.frame.setLocation(dim.width/2-this.frame.getSize().width/2, dim.height/2-this.frame.getSize().height/2);
this.frame.getContentPane().addMouseListener(new Mouse());
this.frame.setVisible(true);
}
Mouse.java:
public static int x;
public static int y;
#Override
public void mouseClicked(MouseEvent e) {
this.x = e.getX();
this.y = e.getY();
System.out.println("X: " + this.x + "; Y:" + this.y);
GUI GUIOBject = new GUI();
GUIOBject.clickOnTile(this.x, this.y);
}
#Override
public void mousePressed(MouseEvent e) {
}
#Override
public void mouseReleased(MouseEvent e) {
}
#Override
public void mouseEntered(MouseEvent e) {
}
#Override
public void mouseExited(MouseEvent e) {
}
IGUI (interface):
public void createFrame();
public void createPanel();
Found the problem:
In the Mouse class I've created a new object and then call the function to color the JLabel.
I made the label variable static and just change it in Mouse class and it works just fine.

Why is my rectangle showing up in a strange form in my JPanel?

When I run my code, a rectangle shows up only when the mouse is clicked in the top left corner of the JPanel. When it shows up, it is warped out of shape. If I change fillRect to fillOval, it does not show up at all. My goal is to have a circle filled at the mouse's location when it is clicked. My code is:
import java.awt.event.*;
import java.awt.*;
import javax.swing.*;
public class PaintProgram {
JFrame frame;
JPanel panel;
Point p;
int x;
int y;
int diameter;
public PaintProgram(){
frame = new JFrame();
frame.setSize(500,500);
panel = new JPanel();
diameter = 100;
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
panel.addMouseListener(new MListener());
panel.add(new DrawCircle());
frame.add(panel);
frame.setVisible(true);
}
public static void main(String[] args){
PaintProgram p = new PaintProgram();
}
class UBListener implements ActionListener{
#Override
public void actionPerformed(ActionEvent a){
}
}
class MListener implements MouseListener{
public void mousePressed(MouseEvent e){
p = panel.getMousePosition();
x = (int) p.getX();
y = (int) p.getY();
panel.add(new DrawCircle());
frame.repaint();
frame.revalidate();
System.out.println(x + "," + y);
}
public void mouseReleased(MouseEvent e){
}
public void mouseClicked(MouseEvent e){
}
public void mouseExited(MouseEvent e){
}
public void mouseEntered(MouseEvent e){
}
}
class DrawCircle extends JPanel{
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
g.setColor(Color.orange);
g.fillRect(x,y,diameter,diameter);
System.out.println(x + "," + y);
}
}
}
I think there were a couple issues with your code. First, your JPanel defined in PaintProgram is not necessary and was causing some issues in your code. Basically I have switched to using the JFrame for just about everything. Next, I don't think you want to create a new DrawCircle() in PaintProgram, just on mouse click.
The following code works for me (draws a circle around your cursor whenever you click, which I think is what you wanted). I made a few changes I didn't mention so feel free to ask questions.
import java.awt.event.*;
import java.awt.*;
import javax.swing.*;
public class PaintProgram {
JFrame frame;
Point p;
int x;
int y;
int diameter;
public PaintProgram(){
frame = new JFrame();
frame.setSize(500,500);
diameter = 100;
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.addMouseListener(new MListener());
frame.setVisible(true);
}
public static void main(String[] args){
PaintProgram p = new PaintProgram();
}
class UBListener implements ActionListener{
#Override
public void actionPerformed(ActionEvent a){
}
}
class MListener extends MouseAdapter {
#Override
public void mousePressed(MouseEvent e){
p = frame.getMousePosition();
x = (int) p.getX();
y = (int) p.getY();
frame.add(new DrawCircle());
frame.repaint();
frame.revalidate();
System.out.println(x + "," + y);
}
}
class DrawCircle extends JPanel{
#Override
public void paintComponent(Graphics g){
g.setColor(Color.orange);
g.fillOval(x - 56, y - 77, diameter, diameter);
System.out.println(x + "," + y);
}
}
}

java mouselistener on Line2d vector

I am not very experimented with listeners. I have a Vector of Line2D (representating a floorplan walls). I draw them in a JFrame.
I try to set a listener on those lines to be able to set them (change color etc) on click.
I am lost because I don't really know where to put the listener. I tried many things I found on many forums but nothing works really.
Thanks.
Edit1:
hi thank you for your answer it's a kind of big projects with many classes so i will post the code and describe how it wokrs . First . I import an image with a floorplan. I have a class with Actions that extends AbstractAction. I use opencv for for lines extraction . I store the extracted lines in a Vector of Walls (class i created).
Vector<wall> walls
And here is my wall class
//a wall is represented by 2 points (pInitial and pFInal)
private Point pInitial, pFinal;
private double wallAttenuation;
private int wallType;
public wall(Point p1, Point p2) {
// p1 is lower by the height than p2
if (p1.getY() > p2.getY()) {
pInitial = p2;
pFinal = p1;
} else {
pInitial = p1;
pFinal = p2;
}
}
//method to set the attenuation of the wall
public void setWallAttenuation(double a) {
wallAttenuation = a;
}
//methods to set both ends of the wall
public void setPInitial(Point P1) {
pInitial.x=(int)P1.getX();
pInitial.x=(int)P1.getY();
}
public void setPFinal(Point P2) {
pFinal.x=(int)P2.getX();
pFinal.x=(int)P2.getY();
}
//methods to get wall attributes (attenuation , ends and type)
public double getWallAttenuation() {
return wallAttenuation;
}
public Point getPInitial() {
return pInitial;
}
public Point getPFinal() {
return pFinal;
}
public void setWallType(int type) {
wallType = type;
}
public int getWallType() {
return wallType;
}
now in my importAction class, and after processing I have this vector of walls (each wall defiened by start and end point . After that , I open a new Frame in which i draws the lines. I want to be able to click on each wall for further modifications.
First i tried to create a Frame class with mouse event handling like this :
public class CreateJFrameWindowWithMouseEventHandling extends JFrame implements MouseMotionListener,MouseListener {
private static final long serialVersionUID = 1L;
public CreateJFrameWindowWithMouseEventHandling() {
setTitle("Walls calibration");
addMouseListener(this);
}
#Override
public void mouseClicked(MouseEvent e) {
int x = e.getX();
int y = e.getY();
System.out.println("Mouse Clicked at X: " + x + " - Y: " + y);
}
#Override
public void mouseEntered(MouseEvent e) {
int x = e.getX();
int y = e.getY();
System.out.println("Mouse Entered frame at X: " + x + " - Y: " + y);
}
#Override
public void mouseExited(MouseEvent e) {
int x = e.getX();
int y = e.getY();
System.out.println("Mouse Exited frame at X: " + x + " - Y: " + y);
}
#Override
public void mousePressed(MouseEvent e) {
int x = e.getX();
int y = e.getY();
System.out.println("Mouse Pressed at X: " + x + " - Y: " + y);
}
#Override
public void mouseReleased(MouseEvent e) {
int x = e.getX();
int y = e.getY();
System.out.println("Mouse Released at X: " + x + " - Y: " + y);
}
#Override
public void mouseDragged(MouseEvent e) {
}
#Override
public void mouseMoved(MouseEvent e) {
int x = e.getX();
int y = e.getY();
System.out.println("Mouse at X: " + x + " - Y: " + y);
repaint();
}
private static void createAndShowGUI() {
//Create and set up the window.
JFrame frame = new CreateJFrameWindowWithMouseEventHandling();
//Display the window.
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
but i guess it wasnt the right solution . next thing i tried was to create JPanel browse the vector , draw the current line and add a listener. to check if it works i change the cursor if the mouse is over a line :
JFrame wallsEdit = new JFrame("Walls Calibration");
wallsEdit.add(new JPanel() {
#Override
protected void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D)g;
for(int i=0;i<walls.size();i++)
{
Point p1 = walls.get(i).getPInitial();
Point p2 = editor.walls.get(i).getPFinal();
g2.setColor(Color.black);
g2.setStroke(new BasicStroke(10));
g2.drawLine((int)p1.getX(),(int)p1.getY(), (int)p2.getX(),(int)p2.getY());
walls.get(i).addMouseListener(new MouseAdapter() {
public void mouseMoved(MouseEvent e) {
Point CursorPoint= MouseInfo.getPointerInfo().getLocation();
double x = CursorPoint.getX();
double y = CursorPoint.getY();
Line2D.Double current = new Line2D.Double(p1.getX(),p1.getY(),p2.getX(),p2.getY()) ;
if(current.intersectsLine(x, y, x, y))
{ setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
} else { setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}
repaint();
});
}
}
}, BorderLayout.CENTER);
wallsEdit.setAlwaysOnTop(true);
wallsEdit.setVisible(true);
wallsEdit.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
and of course this doesnt work. so tried another thing. i declared my Wall class extends Component and implements mouseMotionListener and MouseListener. inside I wrote the mouseMoved event like for the panel .
hope that i gave all needed details . any help would be appreciated thank you very much

Constantly updating JFrame text

I am new to java development, and decided to create a simple java project that outputs the X and Y coordinates of where the mouse is inside of a jframe. I am unsure how I would use a listener.
package main;
import java.awt.BorderLayout;
import java.awt.MouseInfo;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingConstants;
public class Main {
public static void main(String[] args) {
jFrame();
}
public static void jFrame() {
JFrame myFrame = new JFrame("Screen Location");
myFrame.setVisible(true);
myFrame.setBounds(0, 0, 300, 100);
JLabel myText = new JLabel(""+ getTotal(),
SwingConstants.CENTER);
myFrame.getContentPane().add(myText, BorderLayout.CENTER);
}
private static String getTotal() {
for (int i = 0; i < 1;) {
int publicScreenValueX = MouseInfo.getPointerInfo().getLocation().x;
int publicScreenValueY = MouseInfo.getPointerInfo().getLocation().y;
String total = new String(publicScreenValueX + ", " + publicScreenValueY);
return total;
}
return null;
}
}
How would I be able to make the project constantly update the coordinates? Could someone provide a reference on how to do this?
Do note, this is without using a button, or without any input from the user, other than moving the mouse.
Here is an image of what this would look like:
Except the coordinates would always be updating.
Basically all you have to do in order to create a JFrame that handles mouse events is:
1 - Create a class that extends JFrame and implements MouseListener
2 - #Override mouseClicked, mouseEntered, mouseExited, mousePressed, mouseReleased to monitor the coresponding events. Now every time one of these events occures, the respective function will fire up.
Use MouseEvent.getX(), MouseEvent.getY() to get the coordinates of the window that the mouse event occurs.
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JFrame;
public class CreateJFrameWindowWithMouseEventHandling extends JFrame implements MouseListener {
private static final long serialVersionUID = 1L;
public CreateJFrameWindowWithMouseEventHandling() {
setTitle("Simple Frame");
addMouseListener(this);
}
#Override
public void mouseClicked(MouseEvent e) {
int x = e.getX();
int y = e.getY();
JOptionPane.showMessageDialog(null, "Mouse Clicked at X: " + String.valueOf(x) + " - Y: " + String.valueOf(y));
}
#Override
public void mouseEntered(MouseEvent e) {
int x = e.getX();
int y = e.getY();
System.out.println("Mouse Entered frame at X: " + x + " - Y: " + y);
}
#Override
public void mouseExited(MouseEvent e) {
int x = e.getX();
int y = e.getY();
System.out.println("Mouse Exited frame at X: " + x + " - Y: " + y);
}
#Override
public void mousePressed(MouseEvent e) {
int x = e.getX();
int y = e.getY();
System.out.println("Mouse Pressed at X: " + x + " - Y: " + y);
}
#Override
public void mouseReleased(MouseEvent e) {
int x = e.getX();
int y = e.getY();
System.out.println("Mouse Released at X: " + x + " - Y: " + y);
}
private static void createAndShowGUI() {
//Create and set up the window.
JFrame frame = new CreateJFrameWindowWithMouseEventHandling();
//Display the window.
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
//Schedule a job for the event-dispatching thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
I would advise on creating a new class that inherits from JFrame and all that, because it's way more Object Oriented friendly.
However, with your code, what you need to do is add a MouseMotionListener to your JFrame, implement all abstract methods and, on the method mouseMoved, change your myText Label's text;
Replace the method below with the one you currently have and it should work.
Please note that, java.awt.event.MouseMotionListener is only going to give you information about mouse movement inside your application window. For events that occur outside that window, you might want to check this other question:
Java mouse motion anywhere on screen
public static void jFrame() {
JFrame myFrame = new JFrame("Screen Location");
myFrame.setLocationRelativeTo(null);
myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // makes the application close when you close the JFrame
myFrame.setVisible(true);
myFrame.setBounds(0, 0, 300, 100);
JLabel myText = new JLabel(""+ getTotal(), SwingConstants.CENTER);
myFrame.getContentPane().add(myText, BorderLayout.CENTER);
myFrame.addMouseMotionListener(new MouseMotionListener(){
#Override
public void mouseDragged(MouseEvent e) {
// don't delete this method
// all abstract methods must be overridden
}
#Override
public void mouseMoved(MouseEvent e) {
myText.setText(getTotal());
}
});
}

When clicking label appear 2 times

I try to do make when we click the frame, it shows the coordinates of the click point. And i did this:
public void mouseClicked(MouseEvent e) {
int x = e.getX();
int y = e.getY();
j1.setLocation(x, y);
j1.setText("(" + x + ", " + y + ")");
}
public void mousePressed(MouseEvent e) {
int x = e.getX();
int y = e.getY();
j1.setLocation(x, y);
j1.setText("(" + x + ", " + y + ")");
}
public void mouseDragged(MouseEvent e) {}
public void mouseMoved(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
public void mouseReleased(MouseEvent e) {}
But when i click it shows the coordinates first at the center then the click point, 2 times. But i just want only one and at the click point. Where did i mistake, what shoul i do?
Just use mousePressed and that's it. When you click the mouse, 3 methods are often called -- mousePressed, mouseReleased and if the mouse does not move between press and release, mouseClicked. You want to respond to just one of these methods.
So change to:
public void mouseClicked(MouseEvent e) {} // leave this empty
public void mousePressed(MouseEvent e) {
int x = e.getX();
int y = e.getY();
j1.setLocation(x, y);
j1.setText("(" + x + ", " + y + ")");
// also be sure to tell your container to re-position components
revalidate();
repaint();
}
As a side recommendation, note that rather than having a class implement MouseListener, you could have it extend MouseAdapter, and that way your class wouldn't have to have all those empty MouseListener interface methods.
For example:
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.*;
#SuppressWarnings("serial")
public class MousePosition extends JPanel {
private static final int PREF_W = 600;
private static final int PREF_H = PREF_W;
// format String for display String
protected static final String FORMAT = "(%d, %d)";
private int xPos = -40;
private int yPos = -40;
private String displayText = "";
public MousePosition() {
addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
xPos = e.getX();
yPos = e.getY();
// use FORMAT String to create our display text
displayText = String.format(FORMAT, xPos, yPos);
repaint();
}
});
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawString(displayText, xPos, yPos);
}
private static void createAndShowGui() {
MousePosition mainPanel = new MousePosition();
JFrame frame = new JFrame("MousePosition");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}

Categories