I want to enable the drag and drop feature over a JLabel by overriding mouse events over it , but when I define the drag and drop in mousePressed event ,the mouseReleased does not take effect on that JLabel. Am I doing something wrong ?
Thumbnails[I_Loop].setText("1");
Thumbnails[I_Loop].setTransferHandler(new TransferHandler("text"));
Thumbnails[I_Loop].addMouseListener( new MouseAdapter() {
public void mouseReleased(MouseEvent me) {
System.out.println("here mouse released");
}
public void mousePressed(MouseEvent me) {
System.out.println("here mouse pressed");
JComponent comp = (JComponent) me.getSource();
TransferHandler handler = comp.getTransferHandler();
handler.exportAsDrag(comp, me, TransferHandler.COPY);
});
*Thumbnails is array of JLabel
When running the program , the drag and drop works but the statement "here mouse released" does not get printed. However, When I remove the code responsible for DND from the mousePressed() method, "here mouse released" is printed.
What is the wrong in this code?
#Thomas is correct, but two alternatives are worth noting:
This example shows how to drag a component using JLayeredPane; this variation expands on the concept; this more recent example uses a similar approach.
The code below shows how to use a MouseMotionListener; this more complex example uses the same principle.
Code:
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import javax.swing.JFrame;
import javax.swing.JPanel;
/** #see https://stackoverflow.com/a/5312702/230513 */
public class MouseDragTest extends JPanel {
private static final String TITLE = "Drag me!";
private static final int W = 640;
private static final int H = 480;
private Point textPt = new Point(W / 2, H / 2);
private Point mousePt;
public MouseDragTest() {
this.setFont(new Font("Serif", Font.ITALIC + Font.BOLD, 32));
this.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
mousePt = e.getPoint();
repaint();
}
});
this.addMouseMotionListener(new MouseMotionAdapter() {
#Override
public void mouseDragged(MouseEvent e) {
int dx = e.getX() - mousePt.x;
int dy = e.getY() - mousePt.y;
textPt.setLocation(textPt.x + dx, textPt.y + dy);
mousePt = e.getPoint();
repaint();
}
});
}
#Override
public Dimension getPreferredSize() {
return new Dimension(W, H);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
int w2 = g.getFontMetrics().stringWidth(TITLE) / 2;
g.drawString(TITLE, textPt.x - w2, textPt.y);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame f = new JFrame(TITLE);
f.add(new MouseDragTest());
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
});
}
}
Well, if I remember correctly, the drag and drop machinery catches all mouse events and processes them itself. Thus, the normal MouseEvents are not thrown anymore. You'd need to register a DropTargetListener on the JLabel's DropTarget.
Does it have to be a JLabel? I made a class with a string that might get you started..
import java.awt.Graphics;
import java.awt.MouseInfo;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class mainProgram extends JPanel implements Runnable
{
private static final long serialVersionUID = 1L;
public static boolean MOUSE_DOWN = false;
public static String str;
public mainProgram()
{
JFrame win = new JFrame("Window");
win.add(this);
win.setSize(700,500);
win.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
win.setVisible(true);
str = "Drag me!";
new Thread(this).start();
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
if(MOUSE_DOWN)
{
g.drawString(str, MouseInfo.getPointerInfo().getLocation().x, MouseInfo.getPointerInfo().getLocation().y);
}
}
#Override
public void run()
{
Thread t = Thread.currentThread();
this.addMouseListener(new MouseListener()
{
#Override
public void mouseClicked(MouseEvent arg0)
{
}
#Override
public void mouseEntered(MouseEvent arg0)
{
}
#Override
public void mouseExited(MouseEvent arg0)
{
}
#Override
public void mousePressed(MouseEvent arg0)
{
MOUSE_DOWN = true;
}
#Override
public void mouseReleased(MouseEvent arg0)
{
MOUSE_DOWN = false;
}
});
while(t==Thread.currentThread())
{
if(MOUSE_DOWN)
repaint();
try {Thread.sleep(10);}
catch (InterruptedException e) {e.printStackTrace();}
}
}
}
Related
I am trying to write a program that draws a line of circles with mouseDragged, like MS paint does. I have successfully gotten my program to draw a circle when I click. I have also been successful in getting my program to draw a circle when I drag the mouse; however, this doesn't leave a line of circles behind wherever I dragged. It simply drags the same circle around. I am trying to get my program to leave a trail of circles behind where I am dragging but I am pretty confused on why my program wont do so.
package assignment_11;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import javax.swing.*;
public class Canvas extends JComponent implements MouseListener, MouseMotionListener{
private int x, x1;
private int y, y1;
public Canvas() {
addMouseMotionListener(this);
addMouseListener(this);
}
public static void main(String[] args) {
//creates new JFrame, sets Exit On Close, sets visible
JFrame window = new JFrame();
window.add(new Canvas());
window.pack();
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setVisible(true);
}
public Dimension getPreferredSize() {
return new Dimension(640,480);
}
#Override
public void mouseClicked(MouseEvent arg0) {
System.out.println(arg0);
x = arg0.getX();
y = arg0.getY();
repaint();
}
#Override
public void mouseEntered(MouseEvent arg0) {
System.out.println(arg0);
}
#Override
public void mouseExited(MouseEvent arg0) {
System.out.println(arg0);
}
#Override
public void mousePressed(MouseEvent arg0) {
System.out.println(arg0);
}
#Override
public void mouseReleased(MouseEvent arg0) {
System.out.println(arg0);
}
public void paintComponent(Graphics g) {
g.fillOval(x, y, 10, 10);
g.fillOval(x1, y1, 10, 10);
}
#Override
public void mouseDragged(MouseEvent arg0) {
System.out.println(arg0);
x1 = arg0.getX();
y1 = arg0.getY();
repaint();
}
#Override
public void mouseMoved(MouseEvent arg0) {
System.out.println(arg0);
}
}
Any help is appreciated!
Painting is destructive. That is, every time paintComponent is called, you are expected to repaint the entire state of the component.
This raises the issue - you need some way to store the state you want to paint every time paintComponent is called.
For this, a simple ArrayList would do the job nicely. It would allow you to store all the points you're interested and allow you to repaint them each time paintComponent is called, for example...
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JComponent;
import javax.swing.JFrame;
public class Canvas extends JComponent implements MouseListener, MouseMotionListener {
private List<Point> points;
public Canvas() {
points = new ArrayList<>(25);
addMouseMotionListener(this);
addMouseListener(this);
}
public static void main(String[] args) {
EventQueue.invokeLater((new Runnable() {
#Override
public void run() {
JFrame window = new JFrame();
window.add(new Canvas());
window.pack();
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setVisible(true);
}
}));
}
public Dimension getPreferredSize() {
return new Dimension(640, 480);
}
#Override
public void mouseClicked(MouseEvent arg0) {
System.out.println(arg0);
points.add(arg0.getPoint());
repaint();
}
#Override
public void mouseEntered(MouseEvent arg0) {
System.out.println(arg0);
}
#Override
public void mouseExited(MouseEvent arg0) {
System.out.println(arg0);
}
#Override
public void mousePressed(MouseEvent arg0) {
System.out.println(arg0);
}
#Override
public void mouseReleased(MouseEvent arg0) {
System.out.println(arg0);
}
public void paintComponent(Graphics g) {
for (Point p : points) {
g.fillOval(p.x, p.y, 10, 10);
}
}
#Override
public void mouseDragged(MouseEvent arg0) {
System.out.println(arg0);
points.add(arg0.getPoint());
repaint();
}
#Override
public void mouseMoved(MouseEvent arg0) {
System.out.println(arg0);
}
}
Now, as the complexity of your problem grows, you could instead store "shapes" in the List which have some kind of notion of how to paint themselves, allowing to add in more complex shapes
You should also have a look at Painting in AWT and Swing to gain a better understand of how painting in Swing actually works
Im having some trouble using repaint.The code is supposed to draw a line behind your cursor.
package javaapplication6;
import java.awt.*;
import javax.swing.JFrame;
import java.awt.event.*;
class Test extends Canvas implements MouseListener, MouseMotionListener {
int x[]=new int[1024];
int y[]=new int[1024];
int size=0;
public void MouseDemo(){
addMouseListener(this);
addMouseMotionListener(this);
}
public void paint (Graphics g){
g.setColor(Color.red);
for (int i=1;i<size;i++) g.drawLine(x[i],y[i],x[i-1],y[i-1]);
}
public void mousePressed(MouseEvent e){
x[size]=e.getX();
y[size]=e.getY();
size++;
}
public void mouseDragged(MouseEvent e){
y[size]=e.getY();
x[size]=e.getX();
size++;
repaint();
}
public void mouseEntered(MouseEvent e){
size=0;
y[size]=e.getY();
x[size]=e.getX();
repaint();
}
public void mouseExited (MouseEvent e){
size=0;
repaint();
}
public void mouseReleased (MouseEvent e){}
public void mouseClicked (MouseEvent e){
}
public void mouseMoved (MouseEvent e){}
}
public class JavaApplication6 {
public static void main(String[] args) {
JFrame win= new JFrame ("Target");
win.setSize(600,500);
win.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
win.add(new Test());
win.setVisible(true);
}}
This same code worked at the school computer but when I got home and tried to do another example and it didn't really work so I decided to test this one and it doesn't work either.I would really appreciate some help and an explanation as to why repaint doesn't trigger.
Your primary problem is here...
public void MouseDemo() {
addMouseListener(this);
addMouseMotionListener(this);
}
This is a method, not a constructor, so it will never register your listeners. Instead, change it to...
public MouseDemo() {
addMouseListener(this);
addMouseMotionListener(this);
}
Or, based on you actually example code...
public Test() {
addMouseListener(this);
addMouseMotionListener(this);
}
java.awt.Canvas is a heavy weight component, AWT components don't always play nice with Swing, as they have no concept of z-ordering in the way that Swing implements it.
You'd be better off starting with a JPanel.
By convention, you should then override the paintComponent method and perform your custom painting within it, remembering to call super.paintComponent first
Because frame borders are inserted into the visible area of the frame, you "useable" area will be less then that specified by setSize, instead, you should override the getPreferredSize method of the JPanel and specify the "usable" area you prefer. From there, you can pack the frame around it.
To avoid any possible issues with threads, you should use EventQueue.invokeLater to start you UI in
For example...
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test extends JPanel implements MouseListener, MouseMotionListener {
int x[] = new int[1024];
int y[] = new int[1024];
int size = 0;
public Test() {
addMouseListener(this);
addMouseMotionListener(this);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(600, 500);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.red);
for (int i = 1; i < size; i++) {
g.drawLine(x[i], y[i], x[i - 1], y[i - 1]);
}
}
#Override
public void mousePressed(MouseEvent e) {
x[size] = e.getX();
y[size] = e.getY();
size++;
}
public void mouseDragged(MouseEvent e) {
y[size] = e.getY();
x[size] = e.getX();
size++;
repaint();
}
public void mouseEntered(MouseEvent e) {
System.out.println("Entered");
size = 0;
y[size] = e.getY();
x[size] = e.getX();
repaint();
}
public void mouseExited(MouseEvent e) {
size = 0;
repaint();
}
public void mouseReleased(MouseEvent e) {
}
public void mouseClicked(MouseEvent e) {
}
public void mouseMoved(MouseEvent e) {
}
public static void main(String[] args) {
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 Test());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
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.
Here,is something I wanted to show for the use of MouseEvents of one class in another ...by creating an object of the former class...
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.lang.*;
public class MyPagalpanti extends JPanel implements MouseListener
{Point a,b;
boolean drawLin,drawOvl,drawOvl2;
MyPagalpanti(){a=new Point(0,0);b=new Point(0,0);drawLin=false;drawOvl=false,drawOvl2=false;;setSize(300,300);addMouseListener(this);}
public void mouseClicked(MouseEvent m)
{if(!drawOvl){a=new Point(m.getX(),m.getY());drawOvl=true;drawOvl2=false;}
else {b=new Point(m.getX(),m.getY());drawOvl=true;drawOvl2=true;repaint();}//record("clicked",m);}
}
public void mouseEntered(MouseEvent m)
{
}
public void mousePressed(MouseEvent m)
{a=new Point(m.getX(),m.getY());repaint();}
public void mouseReleased(MouseEvent m)
{b=new Point(m.getX(),m.getY());}
public void mouseExited(MouseEvent m)
{}
public void paintComponent(Graphics g)
{if(drawLin){g.setColor(Color.yellow);g.drawLine((int)a.getX(),(int)a.getY(),(int)b.getX(),(int)b.getY());}//d=0;}
else if(drawOvl&&drawOvl2){g.setColor(Color.red);int width=(int)Math.abs(b.getX()-a.getX());
int h=(int)Math.abs(b.getY()-a.getY());
g.drawOval((int)a.getX(),(int)a.getY(),width,h);
}}
}
the class in which an object of MyPagalpanti is formed:
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
//import java.swing.JPanel.*;
public class Mithu extends JFrame// implements MouseListener
{JTextArea jta1,jta2;
Mithu(String title)
{
super(title);
MyPagalpanti p1=new MyPagalpanti();
jta1=new JTextArea();
jta2=new JTextArea();
p1.setOpaque(true);
jta1.setEditable(false);
jta2.setEditable(false);
setForeground(Color.blue);
p1.setPreferredSize(new Dimension(600,600));
p1.setLayout(new GridLayout(3,1,0,0));
getContentPane().add(p1);
pack();
setVisible(true);
}
void record(String s,MouseEvent e)
{jta1.setText(jta1.getText()+"\n"+s+""+e.toString());}
public void mouseClicked(MouseEvent m)
{record("clicked",m);}
public void mouseEntered(MouseEvent m)
{record("entered",m);}
public void mousePressed(MouseEvent m)
{record("pressed",m);}
public void mouseReleased(MouseEvent m)
{ record("released",m);}
public void mouseExited(MouseEvent m)
{record("exited",m);}
public static void main(String args[])
{Mithu m=new Mithu("HI ! Karamvir");
m.setVisible(true);}
}
please don't go word by word...I know my code has many other bugs...coz I am still working on it...but for those who have say that "the MouseEvents will only be delivered to the MouseListener from the component it registered to " ,I guess you are talking correctly but if we see closely, I have used this concept only...in this code..
To add it JBNizet's answer...
MouseListeners will only be delivered to components that are displayable and have registered for notification. Creating a component that is listening for mouse events and adding it you component won't magically make those events delivered to your component.
Then, in top of that, you are adding two components to the default (CENTER) position of a component managed by BorderLayout...
getContentPane().add(panelTop);
//...
getContentPane().add(p1);
This effectively makes the first component invisible, meaning it's not displayable...
You shouldn't be calling show as it's deprecated, use setVisible instead.
You should be calling super.paintComponent in your paintComponent method before doing any custom painting, otherwise you'll end up with no end of painting problems
There is no need for paintComponent to be public as you never want anybody to be able to call it directly...
Updated
Unless you register interest in been notified about events, you will never receive notification, regardless of what objects you create or interfaces you implement.
It's like saying "I'm interested in this movie", but unless you go to the cinemas, you'll never see it...
In order for your Mithu class to receive mouse event notification, it must register a MouseListener against the component that it's interested in monitoring.
The following example registers a a MouseListener in the Mithu class against the instance of MyPagalpanti, which allows it to receive mouse events that are generated by the instance of MyPagalpanti
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class TestMouseListener {
public static void main(String[] args) {
new TestMouseListener();
}
public TestMouseListener() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
Mithu m = new Mithu("HI ! Karamvir");
m.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
m.pack();
m.setLocationRelativeTo(null);
m.setVisible(true);
}
});
}
public class Mithu extends JFrame implements MouseListener
{
JTextArea jta1;
Mithu(String title) {
super(title);
MyPagalpanti p1 = new MyPagalpanti();
p1.addMouseListener(this);
jta1 = new JTextArea();
p1.setOpaque(true);
jta1.setEditable(false);
setForeground(Color.blue);
setLayout(new GridLayout(2, 1));
getContentPane().add(jta1);
getContentPane().add(p1);
pack();
setVisible(true);
}
void record(String s, MouseEvent e) {
jta1.append("\n" + s + "" + e.toString());
}
public void mouseClicked(MouseEvent m) {
record("clicked", m);
}
public void mouseEntered(MouseEvent m) {
record("entered", m);
}
public void mousePressed(MouseEvent m) {
record("pressed", m);
}
public void mouseReleased(MouseEvent m) {
record("released", m);
}
public void mouseExited(MouseEvent m) {
record("exited", m);
}
}
public class MyPagalpanti extends JPanel implements MouseListener {
Point a, b;
boolean drawLin, drawOvl, drawOvl2;
MyPagalpanti() {
a = new Point(0, 0);
b = new Point(0, 0);
drawLin = false;
drawOvl = false;
drawOvl2 = false;
setSize(300, 300);
addMouseListener(this);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
public void mouseClicked(MouseEvent m) {
if (!drawOvl) {
a = new Point(m.getX(), m.getY());
drawOvl = true;
drawOvl2 = false;
} else {
b = new Point(m.getX(), m.getY());
drawOvl = true;
drawOvl2 = true;
repaint();
}//record("clicked",m);}
}
public void mouseEntered(MouseEvent m) {
}
public void mousePressed(MouseEvent m) {
a = new Point(m.getX(), m.getY());
repaint();
}
public void mouseReleased(MouseEvent m) {
b = new Point(m.getX(), m.getY());
}
public void mouseExited(MouseEvent m) {
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.RED);
FontMetrics fm = g.getFontMetrics();
if (a != null && b != null) {
g.drawString(a + "-" + b, 0, fm.getHeight());
}
if (drawLin) {
g.setColor(Color.yellow);
g.drawLine((int) a.getX(), (int) a.getY(), (int) b.getX(), (int) b.getY());
}//d=0;}
else if (drawOvl && drawOvl2) {
g.setColor(Color.red);
int width = (int) Math.abs(b.getX() - a.getX());
int h = (int) Math.abs(b.getY() - a.getY());
g.drawOval((int) a.getX(), (int) a.getY(), width, h);
}
}
}
}
Before you go to much further, you really should read through...
Performing Custom Painting
Painting in AWT and Swing
As you are going to have some very nasty suprises if you keep following your current approach.
Also, it wouldn't hurt to read through How to Write a Mouse Listener
Your class has mouseClicked(), mouseReleased() etc. methods, but it doesn't implement MouseListener. And even if it was, it's never added as a MouseListener to any component.
So, make your class implement MouseListener:
public class MouseEvtEx2 extends JFrame implements MouseListener {
and add itself as mouse listener to the component you want to listen to:
panelTop.addMouseListener(this);
And of course, to help yourself read and understand your own code, indent it properly.
I made couple of changes to make it work. you need to implement MouseListener on your MouseEvtEx2 Frame and also you need to add it as the MouseListener to your panel p1
public class MouseEvtEx2 extends JFrame implements MouseListener {
private JTextArea txtArea;
public MouseEvtEx2(String title) {
super(title);
Panel p1 = new Panel();
MyPanel panelTop = new MyPanel();
panelTop.setBackground(new Color(0.98f, 0.97f, 0.85f));
panelTop.setOpaque(true);
panelTop.setPreferredSize(new Dimension(400, 200));
panelTop.setBorder(BorderFactory.createRaisedBevelBorder());
getContentPane().add(panelTop);
txtArea = new JTextArea();
txtArea.setEditable(false);
JScrollPane pane = new JScrollPane(txtArea);
pane.setPreferredSize(new Dimension(400, 200));
p1.setLayout(new GridLayout(2, 1, 0, 0));
getContentPane().add(p1);
p1.addMouseListener(this);
p1.add(pane);
// txtArea.setText
// revalidate();
setSize(600, 600);
show();
}
public void record(String st, MouseEvent et) {
txtArea.setText("" + st + "" + et.toString());
}// setVisible(true);}
public void mouseClicked(MouseEvent evt) {
record("Mouse clicked # of mouse clicks: " + evt.getClickCount(), evt);// +
// " "
// +
}
public void mouseEntered(MouseEvent evt) {
record("Mouse entered ", evt);// .toString());
}
public void mouseExited(MouseEvent evt) {
record("Mouse exited ", evt);// .toString());
}
public void mousePressed(MouseEvent evt) {
record("Mouse pressed # of mouse clicks: ", evt);// .getClickCount() +
// " " +
}
public void mouseReleased(MouseEvent evt) {
record("Mouse released ", evt);
}
public static void main(String[] args) {
new MouseEvtEx2("Mouse events");
}
}
Hope this helps.
Go ahead, test the code. When the program is running, you can draw on the panel, but whenever it resized, the paint disappears. Any idea why or how to solve this? I would love the help!
Window.java
--The GUI class
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JSeparator;
import javax.swing.JToolBar;
public class Window extends JFrame implements ComponentListener {
public Window(){
this.setSize(700, 700);
this.setDefaultCloseOperation(frame.EXIT_ON_CLOSE);
this.setJMenuBar(menubar);
this.add(new PaintPanel());
this.setTitle("JPaint");
this.setBackground(Color.WHITE);
this.add(TOOL_BAR, BorderLayout.NORTH);
TOOL_BAR.add(BUTTON);
this.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
this.add(PAINT_PANEL);
menubar.add(FILE);
FILE.setMnemonic(KeyEvent.VK_F);
FILE.add(NEW);
FILE.add(NEW_OPEN_SEPARATOR);
FILE.add(OPEN);
FILE.add(SAVE);
FILE.add(SAVE_AS);
FILE.add(SEPARATOR);
FILE.add(EXIT);
menubar.add(Box.createHorizontalGlue());
menubar.add(HELP);
HELP.add(ABOUT);
HELP.add(GNU_PUBLIC_LICENSE);
this.setVisible(true);
NEW.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
PAINT_PANEL.repaint();
}
});
OPEN.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
final JFileChooser FILE_CHOOSER = new JFileChooser();
int CHOSEN_FILE = FILE_CHOOSER.showOpenDialog(FILE_CHOOSER);
}
});
SAVE.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
final JFileChooser SAVE_FILE_CHOOSER = new JFileChooser();
SAVE_FILE_CHOOSER.showSaveDialog(null);
Container c = frame.getContentPane();
BufferedImage SAVED_IMAGE = new BufferedImage(c.getWidth(), c
.getHeight(), BufferedImage.TYPE_INT_ARGB);
c.paint(SAVED_IMAGE.getGraphics());
try {
ImageIO.write(SAVED_IMAGE, "PNG", new File("test.png"));
} catch (IOException e1) {
// If unable to save image for 'Exception' reason.
e1.printStackTrace();
}
}
});
EXIT.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
System.exit(0);
}
});
ABOUT.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
JOptionPane
.showMessageDialog(frame,
"Created by Matthew Hanzelik for "
+ "open source use!");
}
});
GNU_PUBLIC_LICENSE.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(frame, "gpl.txt");
}
});
}
/**
* Serial Version
*/
private static final JFrame frame = new JFrame();
private static final long serialVersionUID = 5259700796854880162L;
private static final JMenuBar menubar = new JMenuBar();
private static final JMenu FILE = new JMenu("File");
private static final JMenu HELP = new JMenu("Help");
private static final JMenuItem SAVE = new JMenuItem("Save");
private static final JMenuItem EXIT = new JMenuItem("Exit");
private static final JSeparator SEPARATOR = new JSeparator();
private static final JSeparator NEW_OPEN_SEPARATOR = new JSeparator();
private static final JMenuItem NEW = new JMenuItem("New");
private static final JMenuItem OPEN = new JMenuItem("Open");
private static final JMenuItem SAVE_AS = new JMenuItem("Save as...");
private static final JMenuItem ABOUT = new JMenuItem("About");
private static final JMenuItem GNU_PUBLIC_LICENSE = new JMenuItem(
"GNU Public License");
private static final JToolBar TOOL_BAR = new JToolBar();
private static final JButton BUTTON = new JButton("Test");
private static final PaintPanel PAINT_PANEL = new PaintPanel();
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
Window GUI = new Window();
}
});
}
#Override
public void componentHidden(ComponentEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void componentMoved(ComponentEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void componentResized(ComponentEvent arg0) {
// TODO Auto-generated method stub
System.out.println("resized");
}
#Override
public void componentShown(ComponentEvent arg0) {
// TODO Auto-generated method stub
}
}
PaintPanel
--The class that contains the panel on which to paint on
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import javax.swing.JPanel;
#SuppressWarnings("serial")
public class PaintPanel extends JPanel {
MouseMotionListener theListener;
Graphics g;
MouseListener theListening;
int x, y, x1, y1;
boolean inside;
public PaintPanel() {
x = 0;
y = 0;
x1 = -99;
y1 = -99;
inside = false;
theListener = new MouseMotionListener() {
public void mouseDragged(MouseEvent arg0) {
if (inside) {
repaint();
}
}
public void mouseMoved(MouseEvent arg0) {
}
};
theListening = new MouseListener() {
public void mouseClicked(MouseEvent arg0) {
}
public void mousePressed(MouseEvent arg0) {
}
public void mouseReleased(MouseEvent arg0) {
x1 = -99;
y1 = -99;
}
public void mouseEntered(MouseEvent arg0) {
inside = true;
x1 = -99;
y1 = -99;
}
public void mouseExited(MouseEvent arg0) {
inside = false;
x1 = -99;
y1 = -99;
}
};
this.setBackground(Color.WHITE);
this.setVisible(true);
this.addMouseMotionListener(theListener);
this.addMouseListener(theListening);
}
#Override
public void paint(Graphics g) {
try {
if (x1 == -99) {
x = getMousePosition().x;
x1 = x;
y = getMousePosition().y;
y1 = y;
} else
{
x = getMousePosition().x;
y = getMousePosition().y;
g.drawLine(x, y, x1, y1);
x1 = x;
y1 = y;
}
} catch (Exception ex) {
}
}
}
Two things: first, when extending a JComponent, you should really override paintCompontent, not paint.
Secondly, inside of your paintComponent, you need to render all of the lines that the user has drawn. This means that you need to store them as they are drawn, and then render them all inside of paintComponent every time. This is because paintComponent gets called any time the window needs to be re-rendered (for example, when the window has been minimized and then restored). Swing does not "remember" which pixels you've set to which colors in this case. Instead, it calls paintComponent and expects you to re-create them.
Also, when you override paintComponent, you will most likely want to call super.paintComponent before doing any of your rendering work.
, but whenever it resized, the paint disappears. Any idea why or how to solve this?
If you want to do incremental painting then there are two common approaches:
Keep an ArrayList of the Objects you want to paint and then repaint all the Object every time the component is repainted.
Paint your objects directly to a BufferedImage. Then the BufferedImage will be repainted automatically every time.
See Custom Painting Approaches for more information and working examples of each approach.