Here i have a code which draws a rectangle on the mouseClicked position using the paintComponent.I can get the output message but anything related to graphics and .draw() wont work.
Code:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public final class testclass extends JFrame {
static JPanel p;
Timer t;
int x = 1;
int y = 1;
int xspeed = 1;
int yspeed = 1;
public testclass() {
initComponents();
this.setBounds(100, 300, 500, 500);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
t.start();
this.add(p);
}
public void initComponents() {
final ActionListener action = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
System.out.println("Hello!");
p.repaint();
}
};
t = new Timer(50, action);
p = new JPanel() {
public void paintComponent(Graphics g) {
super.paintComponent(g);
final Graphics2D gD = (Graphics2D) g;
moveBALL();
gD.drawOval(x, y, 25, 25);
p.addMouseListener(new MouseListener() {
@Override
public void mouseReleased(MouseEvent e) {
System.out.println("a");
}
@Override
public void mousePressed(MouseEvent e) {
System.out.println("b");
}
@Override
public void mouseExited(MouseEvent e) {
System.out.println("c");
}
@Override
public void mouseEntered(MouseEvent e) {
System.out.println("d");
}
@Override
public void mouseClicked(MouseEvent e) {
gD.drawRect(e.getX(), e.getY(), 10, 60);
gD.setColor(Color.green);
System.out.println("clicked");
}
});
}
void moveBALL() {
x = x + xspeed;
y = y + yspeed;
if (x < 0) {
x = 0;
xspeed = -xspeed;
} else if (x > p.getWidth() - 20) {
x = p.getWidth() - 20;
xspeed = -xspeed;
}
if (y < 0) {
y = 0;
yspeed = -yspeed;
} else if (y > p.getHeight() - 20) {
y = p.getHeight() - 20;
yspeed = -yspeed;
}
}
};
}
public static void main(String args[]) {
EventQueue.invokeLater(new Runnable() {
public void run() {
new testclass().setVisible(true);
p.setBackground(Color.WHITE);
}
});
}
}
What is the proper way to implement a mouseListener() in this program? Thanks.
Some suggestions on current code:
Watch class naming scheme i.e
testclass
should beTestClass
or even betterTest
(but thats nit picking). All class names begin with capital letter and each new word thereafter is capitalized.Dont extend
JFrame
unnecessarily.Dont call
setBounds
onJFrame
rather use appropriateLayoutManager
and/or overridegetPreferredSize()
ofJPanel
and return dimensions which fits its content.Always call
pack()
onJFrame
before setting it visible (taking above into consideration).Use
MouseAdapter
vsMouseListener
Dont call
moveBall()
inpaintComponent
rather call it in yourTimer
which repaints the screen, not only slightly better design but we also should not do possibly long running tasks in paint methods.As for your problem I think your logic is a bit skewed.
One approach would see the
Rectangle
(orRectangle2D
) get replaced by its own custom class (which will allow us to store attributes like color etc). Your ball would also have its own class which has the methodmoveBall()
and its attributes likex
andy
position etc. On everyrepaint()
yourJPanel
would call the method to move the ball, theJPanel
itself could wrap themoveBall()
in its own public method which we could than call from the timer which repaints the screen.Here is an example of your code with above fixes implemented (please analyze it and if you have any questions let me know):
First of all the paint component is called every time swing needs to redraw the component.
And you are adding a new instance of mouse listener to the panel every time the paint is called.
Just move the line
p.addMouseListener(new MouseListener() {...}
out of the paint component, preferably after the initialization of the panel.
default template is
Hope this helps.