JFrame repaint() issues - Java - java

I want to be able to draw using Java's paint() on a JFrame. When I click the JFrame (anywhere for now) I want the JFrame to be repainted with the co-ordinates of the click - similar to this Java applet http://www.realapplets.com/tutorial/MouseClickExample.html
Currently Working:
Everything is drawn initially and the JFrame is properly displayed
Not Working:
JFrame does not repaint and update even when repaint() is declared
Here is my code - Please be as stringent as possible with it - I would like to improve my Java programming technique so (if you have time that is) point out every aspect I could improve on.
Any help would be very much appreciated.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class AreaForText extends JPanel implements MouseListener {
int xpos;
int ypos;
JFrame myJFrame = new JFrame();
public void setJFrame() {
myJFrame.setSize(300, 150);
myJFrame.setTitle("Bigger Text!");
myJFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
myJFrame.setVisible(true);
myJFrame.getContentPane().add(new AreaForText());
myJFrame.addMouseListener(new AreaForText());
}
public void mouseClicked(MouseEvent me) {
//Save the coordinates of the click lke this.
xpos = MouseInfo.getPointerInfo().getLocation().x;
ypos = MouseInfo.getPointerInfo().getLocation().y;
System.out.print("Click" + " x: " + xpos + " y: " + ypos);
myJFrame.invalidate();
repaint();
revalidate();
}
public void mouseEntered(MouseEvent e){
}
public void mouseReleased(MouseEvent e) {
}
public void mousePressed(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
public void paint(Graphics g) {
System.out.print("hello");
g.drawString("Hello World", 30, 80);
g.fillRect(20,20,20,20);
g.drawString("("+xpos+","+ypos+")",xpos,ypos);
}
}
class EnlargeText {
public static void main(String args[]) {
AreaForText test = new AreaForText();
test.setJFrame();
}
}

You are creating 2 instances of AreaForText which is not what you want to do. One is added to the JFrame, and one is added to the listener. So the one that actually gets the mouse events and is calling repaint is not the same object that is being displayed.
Some of your code organization is not the best. You have a JPanel subclass that builds its own JFrame and puts itself into the panel. You should just pass in the JFrame if you really need it. I've made a few changes below.
EDIT. I fixed up some of the mouse listener stuff, you were getting the wrong X/Y co-ordinates, and also, you should just add the listener to the panel directly, not the JFrame, that way you don't have to translate the co-ordinates.
EDIT I changed the paint method to paintComponent, which is the preferred method to override here. Have a look at the Swing Paint Tutorial for more information.
import java.awt.EventQueue;
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.JPanel;
class AreaForText extends JPanel implements MouseListener {
private int xpos;
private int ypos;
public AreaForText() {
super();
this.addMouseListener(this);
}
public void mouseClicked(MouseEvent me) {
// Save the coordinates of the click lke this.
xpos = me.getX();
ypos = me.getY();
System.out.print("Click" + " x: " + xpos + " y: " + ypos);
repaint();
}
public void mouseEntered(MouseEvent e) {
}
public void mouseReleased(MouseEvent e) {
}
public void mousePressed(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
System.out.print("hello");
g.drawString("Hello World", 30, 80);
g.fillRect(20, 20, 20, 20);
g.drawString("(" + xpos + "," + ypos + ")", xpos, ypos);
}
}
class EnlargeText {
public static void main(String args[]) {
EventQueue.invokeLater(new Runnable() {
public void run() {
JFrame myJFrame = new JFrame("Bigger Text!");
myJFrame.setSize(300, 150);
myJFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
myJFrame.getContentPane().add(new AreaForText());
myJFrame.setVisible(true);
}
});
}
}

Your not calling the JFrames repaint() you are calling the JPanel repaint method ( the class you are in)
Try:
myJFrame.repaint();

Related

How do i paint a circle where i click [duplicate]

i am writing a program that when the mouse is clicked, a circle will be drawn. The below code i've wrote so far.
import java.awt.*;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.event.*;
import java.awt.geom.*;
public class test extends JFrame implements ActionListener, MouseListener {
Shape circle = new Ellipse2D.Float(10, 10, 10, 10);
public test () {
setSize(250,150);
addMouseListener(this);
}
public static void main(String[] args) {
//TODO code application logic here
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
test frame = new test();
frame.setVisible(true);
}
});
}
public void actionPerformed(ActionEvent ae) {
}
public void drawCircle(int x, int y) {
Graphics g = this.getGraphics();
g.drawOval(x, y, x, y);
g.setColor(Color.BLACK);
g.fillOval(x, y, 2, 2);
}
public void mouseClicked(MouseEvent e) {
drawCircle(e.getX(), e.getY());
repaint();
}
public void mouseExited(MouseEvent e) {
}
public void mousePressed(MouseEvent e) {
}
public void mouseReleased(MouseEvent e) {
}
public void mouseEntered(MouseEvent e) {
}
}
The code is a 400X400 jframe, when clicked open display a circle at a half seconds, The problem is that, when i release the mouse, the circle disappear. why?
Change your mouseClick(...) to:
int x, y;
public void mouseClicked(MouseEvent e) {
x = e.getX();
y = e.getY();
repaint();
}
Override paint(...):
#Override
public void paint(Graphics g) {
drawCircle(x, y);
}
When you call repaint(), the component gets painted again from scratch. You're circle is wiped away. You will want to override paintComponent(Graphics) which is called every time the component is painted.

Drawing a triangle using mouse clicks in java graphics

this is my code. It worked for drawing a circle but I am having troubles drawing a triangle now.. A triangle should appear using mouse clicks but it is showing a triangle immediately after running the application. Please help. Thanks.
package mouse;
import java.awt.*;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.event.*;
import java.awt.geom.*;
public class triangle extends JFrame implements ActionListener, MouseListener {
int xx[]= {20, 50, 80};
int yy[]= {80, 30, 80};
public triangle () {
setSize(2000,2000);
addMouseListener(this);
}
public static void main(String[] args) {
//TODO code application logic here
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
triangle frame = new triangle();
frame.setVisible(true);
}
});
}
public void actionPerformed(ActionEvent ae) {
}
public void drawPolygon(int x, int y, int i)
{
Graphics g = this.getGraphics();
g.setColor(Color.BLACK);
g.drawPolygon(xx, yy, 3);
}
int x, y;
public void mouseClicked(MouseEvent e) {
x = e.getX();
y = e.getY();
repaint();
}
#Override
public void paint(Graphics g) {
drawPolygon(x, y, 3);
}
public void mouseExited(MouseEvent e) {
}
public void mousePressed(MouseEvent e) {
}
public void mouseReleased(MouseEvent e) {
}
public void mouseEntered(MouseEvent e) {
}
}``
The problem you have is that you override the paint method and therefore the drawPolygon method is already called in the initial painting of the JFrame.
For the effect you want to have you should avoid overriding the paint method and only use the drawPolygon method when the MouseListener is invoked.
This should look like this:
#Override
public void mouseClicked(MouseEvent e) {
x = e.getX();
y = e.getY();
drawPolygon(x,y,3);
repaint();
}
In order to paint the triangle where you click with the mouse you need to add the current position to the original triangle coordinates like this:
public void drawPolygon(int x, int y, int i)
{
Graphics g = this.getGraphics();
g.setColor(Color.BLACK);
int[] drawx = {xx[0]+x,xx[1]+x,xx[2]+x};
int[] drawy = {yy[0]+y,yy[1]+y,yy[2]+y};
g.drawPolygon(drawx, drawy, i);
}
I hope this answers you question.
Some general remarks on programming:
You should definitely include a
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
otherwise you program won't terminate on closing the frame and keep on running.
It would also help the readability of your code if you avoid having everything in one class and split your code into several classes.
The MVC model is something that is a very good general guideline for designing class structures.

mouse location and graphics painting

this program is suppose to shift the two rectangles by 10 points to the right each time I click on the screen at the x coordinate 300 or greater, but it doesn't, whats the problem?
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.IOException;
/**
* Created with IntelliJ IDEA.
* To change this template use File | Settings | File Templates.
*/
public class MasterMind extends JComponent implements ActionListener,MouseListener {
//private MouseEvent me;
private int screenX=0;
private int screenY=0;
private ActionEvent e;
private int xX=10;
public MasterMind() throws IOException {
}
public static void main(String [] args) throws IOException {
JFrame window = new JFrame("Master Mind");
MasterMind game= new MasterMind();
window.add(game);
window.pack();
window.setLocationRelativeTo(null);
window.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
window.setVisible(true);
Timer t = new Timer(30, game);
t.start();
window.addMouseListener(game);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(800,600);
}
#Override
protected void paintComponent(Graphics g) {
g.setColor(Color.red);
g.drawRect(xX,30,200,200);
g.setColor(Color.red);
g.drawString("x,y coordinates: "+screenX+" , "+screenY,400,100);
g.setColor(Color.blue);
g.drawRect(xX+3, 33, 194, 194);
}
#Override
public void mousePressed(MouseEvent me) {
}
#Override
public void mouseReleased(MouseEvent me) {
repaint();
}
#Override
public void mouseEntered(MouseEvent me) {
}
#Override
public void mouseExited(MouseEvent me) {
}
#Override
public void mouseClicked(MouseEvent e) {
MouseEvent mouseIvent = (MouseEvent) e;
int screenX = mouseIvent.getX();
int screenY = mouseIvent.getY();
System.out.println("screen(X,Y) = " + screenX + "\t" + screenY);
repaint();
}
#Override
public void actionPerformed(ActionEvent e) {
//To change body of implemented methods use File | Settings | File Templates.
if (screenX>300) {
xX=xX+10; }
//timer animation
repaint();
}
}
I am very new to Java. so please answer in details if I may ask. thank you all.
These lines should be in the mouseClicked method rather than in actionPerformed.
if (screenX > 300) {
xX = xX + 10;
}
immediately before the existing repaint method there. They ensure that X coordinate variable xX is updated for use later in the paintComponent method.
Unrelated but make sure to invoke super.paintComponent(g) as the first statement of paintComponent
Put this ,In your MouseClicked or MousePressed or MouseReleased Method
if(me.getX()>300)
xX=xX+10;
repaint();

Mouse doesn't maintain it's position when frame is moved across the screen

Here is the code.
import java.awt.Color;
import java.awt.Graphics;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.PointerInfo;
import java.awt.Robot;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import javax.swing.JPanel;
public class Paint extends JPanel implements MouseMotionListener, MouseListener {
public Paint() {
setBackground(Color.RED);
addMouseMotionListener(this);
addMouseListener(this);
}
private boolean clicked = false;
public void paintComponent (Graphics g) {
super.paintComponent(g);
PointerInfo a = MouseInfo.getPointerInfo();
Point b = a.getLocation();
int x = (int) b.getX() - 3;
int y = (int) b.getY() - 23;
if (clicked) {
g.drawLine(x, y-5000, x,y+5000);
g.drawLine(x+5000,y,x-5000,y);
g.setColor(Color.white);
}
g.drawLine(x, y-5000, x,y+5000);
g.drawLine(x+5000,y,x-5000,y);
g.setColor(Color.black);
// . . .
}
#Override
public void mouseDragged(MouseEvent e) {
repaint();
}
#Override
public void mouseMoved(MouseEvent e) {
repaint();
}
#Override
public void mouseClicked(MouseEvent e) {
// TODO Auto-generated method stub
}
#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) {
clicked = true;
repaint();
}
#Override
public void mouseReleased(MouseEvent e) {
clicked = false;
repaint();
}
}
public class Frame extends JFrame {
public Frame() {
this.setSize(500,500);
this.setTitle("Test painting");
this.setResizable(false);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
Paint panel = new Paint();
this.add(panel);
this.setVisible(true);
}
public static void main (String[] args) {
new Frame();
}
}
When I run the program, it looks like it works fine when the application is in the default position, but once I move the applet to where I like on the screen, the lines don't maintain the current mouse position on screen.
Can someone show me where I've gone wrong or how to fix this?
Painting is done from the context of the component. The Graphics context for any given component is translated so that the top, left corner is 0x0.
MouseInfo.getPointerInfo().getLocation() is returning the location of the mouse on the screen, not the position relative to the component.
While there is a way to fix it, a better solution would be to simply use a MouseMotionListener instead. The MouseEvent sent to this method has already been translated to the component coordinate space...
public void mouseMoved(MouseEvent me) {
myPoint = me.getPoint();
}
Then in you paintComponent method, simple refer to myPoint instead of trying to use MouseInfo
I think that you will be better off to change your class's state in the MouseAdapter, call repaint() and then have your paintComponent(...) method use this state to help it draw. This seems cleaner and safer to me than using MouseInfo in paintComponent(...).
Other than that, if you need more specific help, consider
telling us more about what it is exactly you're trying to do and how your program isn't working.
creating and posting an sscce, a small compilable and runnable program that demonstrates your problem for us.

Adding mouseListener to my object in java

I'm trying to make an applet which I can simply drag an image. And I want image object to listen events. So here is the applet code which simple run in a thread:
import java.awt.*;
import java.net.URL;
import javax.swing.JApplet;
public class Client extends JApplet implements Runnable {
private static final long serialVersionUID = 1L;
MediaTracker mediaTracker;
Image [] imgArray;
Tas t1;
public void init()
{
mediaTracker = new MediaTracker(this);
imgArray = new Image[1];
URL base = getCodeBase();
imgArray[0] = getImage(base,"okey.png");
mediaTracker.addImage(imgArray[0],1);
try {
mediaTracker.waitForAll();
} catch (InterruptedException e) {
e.printStackTrace();
}
t1 = new Tas(this, new Rectangle(0, 0, imgArray[0].getWidth(this), imgArray[0].getHeight(this)), imgArray[0]);
Thread t = new Thread(this);
t.start();
}
public void paint(Graphics g)
{
t1.paint(g);
}
#Override
public void run() {
while(true){
//System.out.println("run");
repaint();
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
And the class of object which holds image is:
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JPanel;
#SuppressWarnings("serial")
public class Movable extends JPanel implements MouseListener {
public Client mainObj;
public Rectangle rect;
public Image image;
public Movable(Client mainObj, Rectangle rect, Image image) {
this.mainObj = mainObj;
this.rect = rect;
this.image = image;
addMouseListener(this);
}
public void paint(Graphics g) {
g.drawImage(image, rect.x, rect.y, rect.width, rect.height, this);
}
#Override
public void mouseClicked(MouseEvent arg0) {
System.out.println("clicked");
}
#Override
public void mouseEntered(MouseEvent arg0) {
}
#Override
public void mouseExited(MouseEvent arg0) {
}
#Override
public void mousePressed(MouseEvent arg0) {
System.out.println("pressed");
}
#Override
public void mouseReleased(MouseEvent arg0) {
}
}
#SuppressWarnings("serial")
class Tas extends Movable{
public String name = "";
public Tas(Client mainObj, Rectangle rect, Image image) {
super(mainObj, rect, image);
}
}
I can see the image in my applet but nothing happens when I click in or out of the image. So what's wrong with this code.
Assuming that Tas in code #1 is Moveable in code #2...
You don't actually use the Moveable as a Component, but instead ask it to paint itself onto the Applet's graphics context, here:
public void paint(Graphics g)
{
t1.paint(g);
}
Instead you should add an instance of Moveable onto the Applet's container, wherein painting will become automatic, and it will start to receive mouse events. You can also remove that paint() method then too.
First of all you should never override the paint method of a top level container (JApplet, JFrame, JDialog).
Then to do custom painting on other Swing components you override the paintComponent() method of the component, NOT the paint() method. Read the Swing tutorial on Custom Painting. So first fix those problems.
I'm not sure what the point of the Thread is but remove it from your code until you solve your other problems. If you are trying to do animation, then you should be using a Swing Timer, not a Thread.
If you want to see some code for dragging components you can take a look at Moving Windows for some generic code.
This is a working solution. It is not an applet but you can easily convert that. Hope it helps :
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.geom.Point2D;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
#SuppressWarnings("serial")
public class ImagePanel extends JPanel {
Image image;
Point2D axis = new Point2D.Double();
boolean drag = false;
Point2D dragPoint = new Point2D.Double();
public ImagePanel(Image image) {
this.image = image;
setPreferredSize(new Dimension(300,300));
addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
drag = true;
dragPoint = e.getPoint();
}
#Override
public void mouseReleased(MouseEvent e) {
drag = false;
}
});
addMouseMotionListener(new MouseMotionAdapter() {
#Override
public void mouseDragged(MouseEvent e) {
if (drag) {
axis.setLocation(axis.getX()
+ (e.getPoint().x - dragPoint.getX()), axis.getY()
+ (e.getPoint().y - dragPoint.getY()));
dragPoint = e.getPoint();
repaint();
}
}
});
}
#Override
public void paintComponent(Graphics g) {
g.setColor(Color.white);
g.fillRect(0, 0, getWidth(), getHeight());
g.drawImage(image, (int) axis.getX(), (int) axis.getY(), null);
}
public static void main(String[] args) {
try {
JFrame f = new JFrame();
f.getContentPane().add(
new ImagePanel(ImageIO.read(new File("image.jpg"))));
f.pack();
f.setVisible(true);
} catch (IOException e) {
e.printStackTrace();
}
}
}
The simple answer is - you don't have code to do anything in mousePressed() or mouseReleased().
There are lots of other problems in the code though...
Simplest solution I could come up with -
public class Client extends JApplet {
private MouseInputAdapter myMouseListener = new MyMouseListener();
public void init() {
// usually a very bad idea, but needed here
// since you want to move things around manually
setLayout(null);
// assuming this will get used often, so making it a method.
addLabelForImage(getImage(getCodeBase(), "okay.png"));
}
private void addLabelForImage(Image image) {
ImageIcon icon = new ImageIcon(image);
JLabel l = new JLabel(icon);
add(l);
l.setSize(l.getPreferredSize());
// you'll probably want some way to calculate initial position
// of each label based on number of images, size of images,
// size of applet, etc. - just defaulting to 100,100 now.
l.setLocation(100, 100);
l.addMouseListener(myMouseListener);
l.addMouseMotionListener(myMouseListener);
}
// Made this a MouseInputAdapter because I assume you may want to handle
// other types of mouse events later...
private static class MyMouseListener extends MouseInputAdapter {
#Override
public void mouseDragged(MouseEvent e) {
// when the mouse is dragged over a the component this listener is
// attached to (ie - one of the labels) convert the point of the mouse
// event from the internal component coordinates (0,0 is upper right
// corner of each label), to it's parent's coordinates (0,0 is upper
// right corner of the applet), and set the components location to
// that point.
Component theLabel = e.getComponent();
Container theApplet = theLabel.getParent();
Point labelPoint = e.getPoint();
Point appletPoint = SwingUtilities.convertPoint(
theLabel, labelPoint, theApplet );
theLabel.setLocation(appletPoint);
}
}
}

Categories

Resources