MouseListener doesn't recognize first click - java

Here is my code. This code is working with 1 click delay, but i don't know why. Can't find any reason why it's working this way. Can it be something with ArrayList or paintComponent method ?
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
class PaintWindow {
public void createGUI() {
JFrame f = new JFrame("My Canvas");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new MyPanel());
f.setSize(800, 400);
f.setResizable(false);
f.setVisible(true);
f.setLocationRelativeTo(null);
}
}
class MyPanel extends JPanel {
public Point mousePos;
Timer animTimer;
ArrayList<ObjRectangle> arrForRect = new ArrayList<ObjRectangle>();
ObjRectangle ObjRect1;
public MyPanel() {
final ActionListener taskPerformer=new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
for (int i=0;i<arrForRect.size()-1;i++){
arrForRect.get(i).animation();
repaint();
}
}
};
addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
super.mousePressed(e);
System.out.println(getMousePosition());
animTimer=new Timer(100,taskPerformer);
animTimer.start();
mousePos = getMousePosition();
ObjRect1 = new ObjRectangle();
arrForRect.add(ObjRect1);
repaint();
}
});
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
if(arrForRect.size()==0){
return;
}
arrForRect.get(arrForRect.size() - 1).drawObject(mousePos);
for (int i = 0; i < arrForRect.size() - 1; i++) {
arrForRect.get(i).paintSquare(g);
}
} }
class ObjRectangle extends JPanel {
int x, y = 0;
int width = 50;
int height = 20;
public void drawObject(Point coordinates) {
this.x = coordinates.x;
this.y = coordinates.y;
}
public void animation() {
width++;
}
public void paintSquare(Graphics g) {
g.setColor(Color.BLACK);
g.drawRect(x, y, width, height);
}
}
public class MainClass {
public static void main(String[] args) {
PaintWindow kazo=new PaintWindow();
kazo.createGUI();
}}
Would appreciate any help.

As shown by your println, the click detection is fine. Silly bug here:
for (int i=0;i<arrForRect.size()-1;i++){
arrForRect.get(i).animation();
repaint();
}
arrForRect.size()-1 should be arrForRect.size() of course.
Cheers.

Related

Java: How do I edit a JFrame using variables?

I am fairly new to Java programming and I can't figure out why this code always produces a blank JFrame:
mainClass.java:
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
public class mainClass {
public static void main(String[] args) {
drawing d = new drawing();
d.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
d.setSize(1000, 1000);
d.setTitle("Test Game");
d.setVisible(true);
d.repaint();
d.addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
d.repaint();
}
});
}
}
drawing.java:
import java.awt.*;
import javax.swing.*;
import java.util.ArrayList;
import java.util.List;
import java.awt.event.*;
public class drawing extends JFrame implements MouseListener{
public List<units> p1 = new ArrayList<units>();
public List<units> p2 = new ArrayList<units>();
JFrame frame = new JFrame();
public void paint(Graphics g) {
for(units u : p1) {
g.setColor(new Color(0,0,255));
g.drawRect(u.unitX-1, u.unitY-1, u.unitX+1, u.unitY+1);
}
}
public void mousePressed(MouseEvent e) {
int x = e.getX();
int y = e.getY();
p1.add(new units(x,y));
boolean tryPrint = true;
if(p1.size()==10 && tryPrint) {
for(units u : p1) {
System.out.println(u.unitX + "," + u.unitY);
}
tryPrint = false;
}
frame.repaint();
}
public void mouseClicked(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
public void mouseReleased(MouseEvent e) {}
}
units.java:
public class units {
int unitX;
int unitY;
units(int x, int y) {
unitX = x;
unitY = y;
}
}
Sorry for the wordy code. I believe the issue lies somewhere in my handling of the variables or classes. Any help is appreciated.
Also, this code is edited so that may be the reason some comments don't make sense.
First think I advise you to use more cohesive classes. Besides that I would like to say you need to override JFrame's paint method instead of creating a new class for it, see an example here: http://www.gailer-net.de/tutorials/java3/Notes/chap56/ch56_8.html.
I hope you conclude your application.
Regards,
-Rod
It appears that the issue was in my inclusion of the drawing class into a JFrame and where to locate that JFrame. My final, solved code follows:
mainClass.java:
import java.awt.event.*;
import javax.swing.*;
public class mainClass {
private static int x, y;
private static drawing d = new drawing();
public static void main(String[] args) {
JFrame frame = new JFrame("Mouse");
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(1000, 1000);
frame.setResizable(false);
frame.add(d);
d.addMouseListener(new AL());
}
static class AL extends MouseAdapter{
public void mousePressed(MouseEvent e) {
x = e.getX();
y = e.getY();
d.draw(x,y);
}
}
}
drawing.java:
import java.awt.*;
import javax.swing.*;
import java.util.ArrayList;
import java.util.List;
public class drawing extends JPanel {
public void draw(int x, int y) {
p1.add(new ArrayList<Integer>());
p1.get(p1.size()-1).add(x);
p1.get(p1.size()-1).add(y);
repaint();
}
public List<List<Integer>> p1 = new ArrayList<List<Integer>>();
public List<List<Integer>> p2 = new ArrayList<List<Integer>>();
public void paintComponent(Graphics g) {
super.paintComponent(g);
for(List<Integer> u : p1) {
g.setColor(new Color(0,0,255));
g.fillRect(u.get(0)-1, u.get(1)-1, 3, 3);
}
}
}

Jframe not repainting issue

I have a program which is simple in function. On start, it creates a random circle which it places in the window/frame. When that circle is clicked, it should dissappear, and spawn a new circle elsewhere. the issue is, my program does this, but you see all the past circles unless you minimize/reopen the window. I cannot get it to repaint without my help... and I do NOT know why. Here is my code.
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.geom.Ellipse2D;
import java.util.ArrayList;
import java.util.Random;
import javax.swing.JFrame;
public class Core extends JFrame implements MouseListener{
public static ArrayList<Ellipse2D> list = new ArrayList<Ellipse2D>();
Random r = new Random();
public Ellipse2D spawn(){
int x = r.nextInt(this.getWidth());
int y = r.nextInt(this.getHeight());
while(x<75||x>this.getWidth()-150){
x = r.nextInt(this.getWidth());
}
while(y<75||y>this.getHeight()-150){
y = r.nextInt(this.getHeight());
}
System.out.println("MAKING SHAPE at :" + x + " AND " + y);
return new Ellipse2D.Double(x, y, 75, 75);
}
public void mouseClicked(MouseEvent me) {
// Save the coordinates of the click lke this.
if(list.get(0).contains(me.getPoint())){
System.out.println("CLICKED SHAPE!");
list.clear();
list.add(spawn());
}
revalidate();
repaint();
}
public void mouseEntered(MouseEvent e) {
}
public void mouseReleased(MouseEvent e) {
}
public void mousePressed(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
#Override
public void paint(Graphics g) {
if(list.size()==0){
System.out.println("oops");
}
if(!list.isEmpty()){
System.out.println("DRAW");
int x =(int) list.get(0).getX();
int y =(int) list.get(0).getY();
int width = (int) list.get(0).getWidth();
int height = (int) list.get(0).getHeight();
g.setColor(Color.red);
g.drawOval(x,y, width, height);
}
}
public Core(){
setSize(500, 500);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.addMouseListener(this);
list.add(spawn());
setVisible(true);
}
public static void main(String args[]) {
EventQueue.invokeLater(new Runnable() {
public void run() {
new Core();
}
});
}
}
Your code works perfectly fine for me, however...
Don't override paint of top level containers like JFrame, JFrame contains a JRootPane, which contains a contentPane and may also have a visible glassPane, all of which can overpaint what is painted within the paint method. As a general rule, you shouldn't extend from JFrame (or other top level containers), you are locking yourself into a single use case, reducing the re-usability of your component and you're not actually any new functionality to the class. Instead, use a JPanel and override it's paintComponent method
Call super.paint before doing any custom painting. If, however, you use a JPanel, call super.paintComponent. Painting is performed by a series of methods which are chained together to generate the final output. See Painting in AWT and Swing and Performing Custom Painting for more details
Consider using something like x = r.nextInt(this.getWidth() - 150) + 75; and y = r.nextInt(this.getWidth() - 150) + 75; instead of your while loops, I think you might find them safer to use
For example...
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Ellipse2D;
import java.util.ArrayList;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Core {
public static void main(String args[]) {
EventQueue.invokeLater(new Runnable() {
public void run() {
new Core();
}
});
}
public Core() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new CorePane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class CorePane extends JPanel {
private ArrayList<Ellipse2D> list = new ArrayList<Ellipse2D>();
private Random r = new Random();
public Ellipse2D spawn() {
int x = r.nextInt(this.getWidth());
int y = r.nextInt(this.getHeight());
x = r.nextInt(this.getWidth() - 150) + 75;
y = r.nextInt(this.getWidth() - 150) + 75;
System.out.println("MAKING SHAPE at :" + x + " AND " + y);
return new Ellipse2D.Double(x, y, 75, 75);
}
public CorePane() {
addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent me) {
// Save the coordinates of the click lke this.
if (list.get(0).contains(me.getPoint())) {
list.clear();
list.add(spawn());
}
revalidate();
repaint();
}
});
}
#Override
public void invalidate() {
super.invalidate();
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
if (list.isEmpty()) {
list.add(spawn());
}
}
});
}
#Override
public Dimension getPreferredSize() {
return new Dimension(500, 500);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
if (!list.isEmpty()) {
for (Ellipse2D ellipse : list) {
g2d.setColor(Color.red);
g2d.draw(ellipse);
}
}
g2d.dispose();
}
}
}
Or, based on what I believe you're trying to do, you could simply do something like...
public class CorePane extends JPanel {
private Random r = new Random();
private Ellipse2D ellipse;
public Ellipse2D spawn() {
int x = r.nextInt(this.getWidth());
int y = r.nextInt(this.getHeight());
x = r.nextInt(this.getWidth() - 150) + 75;
y = r.nextInt(this.getWidth() - 150) + 75;
System.out.println("MAKING SHAPE at :" + x + " AND " + y);
return new Ellipse2D.Double(x, y, 75, 75);
}
public CorePane() {
addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent me) {
if (ellipse != null && ellipse.contains(me.getPoint())) {
ellipse = spawn();
}
revalidate();
repaint();
}
});
}
#Override
public void invalidate() {
super.invalidate();
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
spawn();
}
});
}
#Override
public Dimension getPreferredSize() {
return new Dimension(500, 500);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
if (ellipse != null) {
g2d.setColor(Color.red);
g2d.draw(ellipse);
}
g2d.dispose();
}
}

mouseMoved Event not working

I've been trying to work this code, it's like when you hover over the start button it should change its color to gray, but whenever i hover over it. nothing happens, can somebody tell me why? i didn't get any error and it seems like my mousemoved listener isn't recognized by the compiler, sorry for my english. I haven't finish it yet but here is the code:
class Contents extends JFrame implements Runnable {
private Image dbi;
private Graphics dbg;
private boolean isStarted, isHovered;
private int x,y,xDir,yDir,bx,by,timer,life,my,mx,mhx,mhy;
private Rectangle startgame = new Rectangle(80,100,150,40);
Contents()
{
super();
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
if(isStarted)
setSize(600,600);
else
{
setSize(300,300);
setBackground(Color.BLUE);
}
setLocationRelativeTo(null);
isStarted = false;
isHovered = false;
addMouseListener(new MouseAdapter()
{
public void mousePressed(MouseEvent e)
{
mx = e.getX();
my = e.getY();
if(mx > startgame.x && mx < startgame.x+startgame.width &&
my > startgame.y && my < startgame.y+startgame.height)
{
isStarted = true;
}
}
public void mouseMoved(MouseEvent e)
{
mhx = e.getX();
mhy = e.getY();
if(mhx > startgame.x && mhx < startgame.x+startgame.width &&
mhy > startgame.y && mhy < startgame.y+startgame.height)
isHovered = true;
else
isHovered = false;
}
});
}
public void paint(Graphics g)
{
dbi = createImage(getWidth(), getHeight());
dbg = dbi.getGraphics();
draw(dbg);
g.drawImage(dbi,0,0,this);
repaint();
}
public void draw(Graphics g)
{
if(!isStarted)
{
if(!isHovered)
g.setColor(Color.GRAY);
else
g.setColor(Color.GREEN);
g.fillRect(startgame.x, startgame.y, startgame.width, startgame.height);
g.setFont(new Font("Serif",Font.BOLD,24));
g.setColor(Color.WHITE);
g.drawString("Start game", startgame.x+20, startgame.y+25);
g.drawString(String.format("hoverx: %d hovery: %d",mhx,mhy), 50,200);
}
else
{
}
}
public void run()
{
} }
public class Game {
public static void main(String[] args)
{
Contents c = new Contents();
} }
Just use Rectangle.contains(Point) to check if the point from the MouseEvent is inside the Rectangle. Here is an example
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.geom.Rectangle2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class PaintedButton extends JPanel {
private static final Color HOVER_COLOR = Color.BLUE;
private static final Color NON_HOVER_COLOR = Color.GREEN;
private static final Rectangle2D RECTANGLE = new Rectangle2D.Double(50, 50,
200, 100);
private Color color = NON_HOVER_COLOR;
public PaintedButton() {
addMouseMotionListener(new MouseMotionAdapter() {
public void mouseMoved(MouseEvent e) {
Point p = e.getPoint();
if (RECTANGLE.contains(p)) {
color = HOVER_COLOR;
} else {
color = NON_HOVER_COLOR;
}
repaint();
}
});
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setPaint(color);
g2.fill(RECTANGLE);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(300, 200);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new PaintedButton());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}

paintComponent () never executes on a JFrame

import javax.swing.SwingUtilities;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.BorderFactory;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseMotionAdapter;
import java.awt.geom.*;
import java.util.*;
public class test1 extends JFrame implements MouseListener {
private JPanel JP = new JPanel();
public test1() {
JP.setBorder(BorderFactory.createLineBorder(Color.black));
JP.addMouseListener(this);
this.setDefaultCloseOperation(this.EXIT_ON_CLOSE);
this.add(JP);
this.pack();
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
test1 frame = new test1();
frame.setSize(400,400);
frame.setVisible(true);
}
});
}
public void mouseClicked(MouseEvent e) {
//drawCircle(e.getX(), e.getY());
//repaint();
ballball ball;
ball = new ballball();
//ball.paintComponent(Graphics g);
System.out.println("ballball");
}
public void mouseExited(MouseEvent e) {
}
public void mousePressed(MouseEvent e) {
//this.mouseX=e.getX();
//this.mouseY=e.getY();
}
public void mouseReleased(MouseEvent e) {
}
public void mouseEntered(MouseEvent e) {
}
}
class ballball extends test1 implements Runnable {
private int squareX = 50;
private int squareY = 50;
private int squareW = 100;
private int squareH = 100;
public boolean draw;
private Vector<Object> v = new Vector<Object>();
public ballball() {
/*addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
draw = true;
//Thread thread1 = new Thread(this.moveSquare(50, 50));
repaint();
//moveSquare(e.getX(),e.getY());
}
});*/
/*addMouseMotionListener(new MouseAdapter() {
public void mouseDragged(MouseEvent e) {
moveSquare(e.getX(),e.getY());
}
});*/
System.out.println("ball created");
this.repaint();
}
public void run() {
}
private void moveSquare(int x, int y) {
int OFFSET = 1;
if ((squareX!=x) || (squareY!=y)) {
repaint(squareX,squareY,squareW+OFFSET,squareH+OFFSET);
squareX=x;
squareY=y;
repaint(squareX,squareY,squareW+OFFSET,squareH+OFFSET);
}
}
public void paint(Graphics g) {
g.drawString("abcasdfasffasfas", 10, 10);
}
//#Override
public void paintComponent(Graphics g) {
//if (draw) {
// existing code
System.out.println("paint");
//super.paintComponent(g);
//g.drawString("This is my custom Panel!",10,20);
//g.setColor(Color.RED);
//g.fillRect(squareX,squareY,squareW,squareH);
//g.setColor(Color.BLACK);
//g.drawRect(squareX,squareY,squareW,squareH);
Shape circle = new Ellipse2D.Float(squareX,squareY,100f,100f);
Graphics2D ga = (Graphics2D)g;
ga.draw(circle);
//}
}
}
The aim of the program is to click to create the circle, the ballball class extends the test1, when test1 detect the mouse click, the ballball object created. But the paint/paintComponent method is never be executed. In my program structure, is it possible to paint the circle to the super class JPanel?
JFrame is not a JComponent, it doesn't have a paintComponent method you can override. Instead you could extend a JPanel and add it to the frame.

Clear painted screen at each click of the mouse?

Can't seem to figure out how to only show one circle. Was trying to //g.clearRect(0, 0, 400, 400); but that clears the background too. Was also trying to just fill the background with yellow again but couldn't get that working either. Any suggestions?
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class JMouseFrame extends JFrame
implements MouseListener {
Container con = null;
int x, y;
int size;
public JMouseFrame() {
setTitle("JMouseFrame");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
con = this.getContentPane();
addMouseListener(this);
}
public void mousePressed(MouseEvent e) {
x = e.getX();
y = e.getY();
}
public void mouseClicked(MouseEvent e) {
int whichButton = e.getButton();
if (whichButton == MouseEvent.BUTTON1) {
size = 15;
} else if (whichButton == MouseEvent.BUTTON3) {
size = 4;
}
repaint();
}
public void mouseEntered(MouseEvent e) {
con.setBackground(Color.yellow);
}
public void mouseExited(MouseEvent e) {
con.setBackground(Color.black);
}
public void paint(Graphics g) {
//g.clearRect(0, 0, 400, 400);
g.drawOval(x - size, y - size, size * 3, size * 3);
}
public static void main(String[] args) {
JMouseFrame mFrame = new JMouseFrame();
mFrame.setSize(400, 400);
mFrame.setVisible(true);
}
public void mouseReleased(MouseEvent e) {
}
}
It looks like you're mixing AWT and Swing painting. Instead, override paintComponent(), as suggested in the example below. See Painting in AWT and Swing for details.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
/** #see http://stackoverflow.com/questions/3898775 */
public class MousePanel extends JPanel {
private static final int SIZE = 20;
Point p = new Point(Short.MAX_VALUE, Short.MAX_VALUE);
public MousePanel() {
this.setPreferredSize(new Dimension(400, 400));
this.setBackground(Color.yellow);
this.addMouseListener(new MouseHandler());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.black);
g.drawOval(p.x - SIZE, p.y - SIZE, SIZE * 2, SIZE * 2);
}
private final class MouseHandler extends MouseAdapter {
#Override
public void mousePressed(MouseEvent e) {
p = e.getPoint();
repaint();
}
}
private void display() {
JFrame f = new JFrame("MousePanel");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(this);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new MousePanel().display();
}
});
}
}
Addendum:
I can't figure out how to make the code you posted work with what I have...
You can restore your mouse methods to the MouseHandler almost verbatim. The only difference is the need to qualify this, e.g.
#Override
public void mouseClicked(MouseEvent e) {
int whichButton = e.getButton();
if (whichButton == MouseEvent.BUTTON1) {
MousePanel.this.size = 15;
} else if (whichButton == MouseEvent.BUTTON3) {
MousePanel.this.size = 4;
}
repaint();
}
#Override
public void mouseEntered(MouseEvent e) {
MousePanel.this.setBackground(Color.yellow);
}
#Override
public void mouseExited(MouseEvent e) {
MousePanel.this.setBackground(Color.black);
}

Categories

Resources