In my applet I have a method paint that paints on screen.
public void init() {
addMouseMotionListener(new MouseMotionAdapter() {
#Override
public void mouseMoved(MouseEvent evt) {
storeCoordinates(evt,Graphics g); // results in error
}
});
}
public void paint(Graphics g) {
// do something
}
public void storeCoordinates(MouseEvent evt , Graphics g) {
// from this method i want to modify the scene painted by paint
}
Now in another method I want to modify a bit of a scene that was painted by the paint method. How can I do this ? Like I want to draw blue lines using g.drawLine(.,.,.,.) from another method.
The above snippet generates an error saying ) expected ; expected , cannot find symbol variable Graphics when i call the function from mouseMoved
In response to edits:
So what I would do in this case is not use the graphics right there. Instead, I would do something like this... Keep a list of your points, and when you click, add the point to your list. Then when you draw, draw your points. (If you're only going to be drawing on click, you could just store the last point, draw a line between the current point and the last point, and set the last point to the current point. But this is more extensible.)
List<Point> points = new ArrayList<Points>();
public void init() {
addMouseMotionListener(new MouseMotionAdapter() {
#Override
public void mouseMoved(MouseEvent evt) {
storeCoordinates(evt); // graphics removed
}
});
}
public void paint(Graphics g) {
for(int i = 1; i < points.size(); i++) {
Point first = points.get(i - 1);
Point second = points.get(i);
g.setColor(Color.BLUE);
g.drawLine(first.getX(), first.getY(), second.getX(), second.getY());
}
}
public void storeCoordinates(MouseEvent evt) {
int x = evt.getX();
int y = evt.getY();
points.add(new Point(x,y));
}
.
Old Answer
Pass your graphics object as a parameter to that other method.
public void paint(Graphics g) {
externalPaint(g);
}
private void externalPaint(Graphics g) {
g.drawLine(1,2,3,4);
}
Now in another method I want to modify a scene on that was painted by the paint method. How can I do this?
Call Component.repaint(int,int,int,int) or JComponent.repaint(Rectangle).
Related
The code I made won't change the coordinates of the ball every time I click on it.
public class AimTrainerPanel extends JPanel implements MouseListener {
static final int WIDTH = 1300;
static final int HEIGHT = 750;
static final int SIZE = 10;
Random rand;
JLabel cd;
int x;
int y;
boolean running = false;
Timer timer;
AimTrainerPanel() {
rand = new Random();
this.setPreferredSize(new Dimension(WIDTH, HEIGHT));
this.setBackground(Color.black);
this.setFocusable(true);
this.setLayout(null);
this.addMouseListener(this);
startGame();
}
public void startGame() {
newDot();
running = true;
timer = new Timer();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
draw(g);
}
public void draw(Graphics g) {
if (running) {
g.setColor(Color.white);
g.fillOval(x, y, SIZE, SIZE);
}
}
public void newDot() {
x = rand.nextInt((int)(WIDTH/SIZE)) * SIZE;
y = rand.nextInt((int)(HEIGHT/SIZE)) * SIZE;
}
#Override
public void mouseClicked(MouseEvent e) {
int mx = e.getX();
int my = e.getY();
if (mx >= x && mx <= x + 10) {
if (my >= y && my <= y + 10) {
newDot();
}
}
}
#Override
public void mousePressed(MouseEvent e) {
}
#Override
public void mouseReleased(MouseEvent e) {
}
#Override
public void mouseEntered(MouseEvent e) {
}
#Override
public void mouseExited(MouseEvent e) {
}
}
The newDot() method is suppose to create new coordinates every time it is called but the ball won't change places. I don't know if it's because I misswrote something or because my what I did doesn't change the coordinates or if I'm suppose to add something.
I'm not sure what your Timer is supposed to be doing, but it doesn't appear to be a Swing Timer, and since this is a Swing GUI I'd get rid of it.
Now to the crux of your problems:
You're using mouseClicked which isn't called if the mouse moves even slightly between mouse pressed and mouse released, and so often it is better to use mousePressed or mouseReleased methods and not mouseClicked
You don't call repaint() after changing the state of your program. Swing won't know that a repaint is needed unless you suggested, and so in your mouseListener or in code called by it, you should call this method after changing GUI state. Here you can call it at the end of the newDot(...) method or in the mouse listener after you call the same method.
Your if blocks within your mouse listener appear to be quite restrictive as to where they will allow the listener to respond to a mouse click -- is it too restrictive? I don't know since I'm not familiar with your requirements, but possibly.
I cannot figure out why I need to call repaint two times as in the below program. I expected that the first repaint will keep the rectangle as it was when I click in another position, and so now there are two rectangles in the window. But it actually removes the first rectangle. Can someone explain this?
class MyPanel extends JPanel {
private int squareX = 50;
private int squareY = 50;
private int squareW = 20;
private int squareH = 20;
public MyPanel() {
setBorder(BorderFactory.createLineBorder(Color.black));
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
moveSquare(e.getX(),e.getY());
}
});
addMouseMotionListener(new MouseAdapter() {
public void mouseDragged(MouseEvent e) {
moveSquare(e.getX(),e.getY());
}
});
}
private void moveSquare(int x, int y) {
int OFFSET = 0;
if ((squareX!=x) || (squareY!=y)) {
//repaint(squareX,squareY,squareW+OFFSET,squareH+OFFSET);
repaint(squareX,squareY,squareW,squareH);
squareX=x;
squareY=y;
repaint(squareX,squareY,squareW+OFFSET,squareH+OFFSET);
//repaint(squareX,squareY,squareW,squareH);
}
}
public Dimension getPreferredSize() {
return new Dimension(250,200);
}
protected void paintComponent(Graphics g) {
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.BLUE);
g.drawRect(squareX,squareY,squareW,squareH);
}
}
It's all about timing. You are scheduling two different repaint requests, one for the area which the rectangle use to occupy and one for the area that the rectangle now occupies.
The repaint requests are pushed to the Event Queue (via the RepaintManager), which means that they occur some time in the future and are not immediately handled (within the method that is calling them).
This ensures that you are "erasing" the area where the rectangle "use" to be before you paint the area where the rectangle now is.
By using repaint(int, int, int, int) you reduce the amount of area which needs to be painted and can make the paint process more efficient.
Take a look at Painting in AWT and Swing for more details
This is my first GUI exercise. I am trying to draw a line using a for loop but for some reason I haven't figured out why I'm getting only its last dot (pixel). I guess repaint() does something different than what I thought but I can't figure out yet what it is.
here is my code:
package com.mycompany;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class MousePanel extends JPanel implements MouseListener{
int pointX, pointY, oldX, oldY;
public MousePanel(){
super();
addMouseListener(this);
}
public void mouseClicked(MouseEvent mouse){
// Tell the panel that we need to redraw things.
oldX=pointX;
oldY=pointY;
// Get the location of the current mouse click.
pointX = mouse.getX();
pointY = mouse.getY();
// Tell the panel that we need to redraw things.
for (int i=0 ; i<50 ; i++)
{
pointX ++;
repaint();
}
System.out.println("x:"+pointX+", y:"+pointY);
}
public void paintComponent(Graphics g){
g.fillOval(pointX, pointY, 5, 5);
}
public void mouseEntered(MouseEvent mouse){ }
public void mouseExited(MouseEvent mouse){ }
public void mousePressed(MouseEvent mouse){ }
public void mouseReleased(MouseEvent mouse){ }
public static void main(String arg[]){
JFrame frame = new JFrame("MousePanel");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(640,400);
MousePanel panel = new MousePanel();
frame.setContentPane(panel);
frame.setVisible(true);
}
}
the
Java Code:
for (int i=0 ; i<50 ; i++)
{
pointX ++;
repaint();
}
I'm getting only its last dot (pixel).
That is all you paint in your paintComponent() method.
If you want all the ovals then you need to repaint all the ovals every time the paintComponent() method is invoked.
See Custom Painting Approaches for the two common ways to do this:
Keep track of all the objects to be painted in an ArrayList and then iterate through the List every time paintComponent() is invoked
Paint your objects to a BufferedImage and then just paint the BufferedImage in the paintComponent() method.
The repaint will always draw the fixed end-state of the component..
And, since you request the repaint in a single callback, you will get the following
x=1
repaint
x=2
repaint
...
etc.
The repaint itself does not occur until you have finished the loop, and the next UI event can be processed (which is your repaint request). The 50 or so repaint requests are probably conflated into one, which again calls your paintComponent.
Now the paint see that it should paint a 5px oval using your current x value, and does so.
So you would probably replace the for loop with a single repaint request, and change the paintComponent to paint between oldX,oldY and pointX,pointY
You are repainting the oval 50 times. I'm not very sure what you want to do. If you wish to fill an oval with a width/height of 50 pixels, you could update the method paintComponent
public void paintComponent(Graphics g){
g.fillOval(pointX, pointY, 50, 50);
}
In this case the for loop is not necessary, only a repaint is enough.
If you want to draw a line, there is the method drawLine. I see you have the old pixels position stored so you could go for
public void paintComponent(Graphics g){
g.drawLine(pointX, pointY, oldX, oldY);
}
Again, only a repaint is necessary and no loop. I've posted the code below
public class MousePanel extends JPanel implements MouseListener {
int pointX, pointY, oldX, oldY;
public MousePanel(){
super();
addMouseListener(this);
}
public void mouseClicked(MouseEvent mouse){
// Tell the panel that we need to redraw things.
oldX=pointX;
oldY=pointY;
// Get the location of the current mouse click.
pointX = mouse.getX();
pointY = mouse.getY();
// Tell the panel that we need to redraw things.
repaint();
System.out.println("x:"+pointX+", y:"+pointY);
}
public void paintComponent(Graphics g){
g.drawLine(pointX, pointY, oldX, oldY);
}
public void mouseEntered(MouseEvent mouse){ }
public void mouseExited(MouseEvent mouse){ }
public void mousePressed(MouseEvent mouse){ }
public void mouseReleased(MouseEvent mouse){ }
public static void main(String arg[]){
JFrame frame = new JFrame("MousePanel");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(640,400);
MousePanel panel = new MousePanel();
frame.setContentPane(panel);
frame.setVisible(true);
}
}
I am trying to code a simple animation like a moving circle. I have tried using getGraphics() and work with that but it's not dynamic and it's painted for just one time
So please help me and guide me to code a dynamic graphic program.
I mean for example defining a function and every time when it called, it draws a line on a label.
Here is how to make a growing rectangle:
public class MovingRectangle extends JPanel {
private Timer timer = new Timer(500, new ActionListener() {
public void actionPerformed(ActionEvent event) {
rectWidth += 100;
repaint();
}
};
private int rectWidth = 100;
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawRect(0, 0, 100. rectWidth);
}
public void start() {
timer.start();
}
public void stop() {
timer.stop();
}
public void reset() {
rectWidth = 100;
repaint();
}
}
you should override the paintComponent(Graphic g).
This method is called every time the repaint() is called, so you should periodic calling that method.
You should also set DoubleBuffering on true: setDoubleBuffered(true)
It will prevent possible flicker of your animation
so I am trying to make a simple program where you click on the screen and it creates a block that falls and collides with a larger block beneath and sticks to it. Kind of like a simple collision program. The problem is when I create one block it deletes the block previously. I made an array, but it still does this. Do any of you know what Im doing wrong? Im sure its a simple fix.
public class Screen extends JPanel implements Runnable {
public static JLabel statusbar; //displays a status bar showing what mouse movements are taking place
private Image cat; //image of the cat
public int xCoord ; //get the coordinates of the mouse pressed
public int yCoord ;
public int xCreate;
public int yCreate;
public Rectangle Ground;
public Rectangle Block;
public boolean isClicked = false;
public int clickCount = 0;
Rectangle blocks[] = new Rectangle[10];
int blocknum = 0;
public Screen(Frame frame) {
loadPic(); //calls the loadPic method above
Handlerclass handler = new Handlerclass(); //creates a new class to use the mouse motion listener
System.out.println("mouse works!");
addMouseListener(handler);
addMouseMotionListener(handler);
statusbar = new JLabel("default");
add(statusbar);
}
public void run(){ //this is the game run loop
System.out.println("this is running");
try{
} catch(Exception e) {} //exception handling
}
public void loadPic(){ //loads the picture from the other project but its the same pic
cat = new ImageIcon("C:\\Users\\Camtronius\\Documents\\NetBeansProjects\\Moving Block Proj\\src\\MovingBlock\\catIcon1.png").getImage(); //gets the image
System.out.println("Image Loaded!");
}
#Override public void paintComponent(Graphics g){
super.paintComponent(g); //paints the component, the picture, on top
Graphics2D g2d = (Graphics2D) g.create();
g2d.drawImage(cat, xCoord, yCoord, null);
g2d.setColor(Color.BLUE);
Ground = new Rectangle(0,450,550,50);
g2d.fillRect(0,450, 550, 50);
for(Rectangle blocknum : blocks){
if (blocks != null) {
g2d.setColor(Color.RED);
g2d.fillRect(xCreate,yCreate,50,50);
System.out.println(blocknum);
}
}
//move();
}
public void move(){
if(yCreate<400){
yCreate+=1;
}else{
}
if(Ground.intersects(blocks[blocknum])){
yCreate=400;
System.out.println("contains!");
}
}
private class Handlerclass implements MouseListener, MouseMotionListener{
public void mouseClicked(MouseEvent event){
}
public void mousePressed(MouseEvent event){
}
public void mouseReleased(MouseEvent event){
if(blocknum<blocks.length){
xCreate=event.getX();
yCreate=event.getY();
blocks[blocknum] = new Rectangle(50,50, xCreate, yCreate);
repaint();
}
blocknum=blocknum+1;
}
public void mouseEntered(MouseEvent event){
}
public void mouseExited(MouseEvent event){
}
public void mouseDragged(MouseEvent event){
}
public void mouseMoved(MouseEvent event){
statusbar.setText(String.format("Coordinates are: %d, %d", event.getX(),event.getY()));
xCoord=event.getX();
yCoord=event.getY();
}
}
}
Painting is a destructive process. That is, when a new paint cycle runs, the previous contents of the Graphics context should be cleared...
So, in you paintComponent method you are only painting the last block...
if(isClicked = true){
blocks[blocknum] = new Rectangle(50,50, xCreate, yCreate);
g2d.setColor(Color.RED);
g2d.fillRect(xCreate,yCreate,50,50);
System.out.println(blocknum);
repaint(); // THIS IS A BAD IDEA
}
DO NOT call any method that might cause repaint to be called. This will put you in a potential cycle of death that will consume your CPU.
Instead, you should loop through the blocks array and paint each one...
for (Rectangle block : blocks) {
if (block != null) {
g2d.setColor(Color.RED);
g2d.fill(block);
}
}
And in you mouseReleased method, you should be adding the new rectangles...
public void mouseReleased(MouseEvent event){
blocknum=blocknum+1;
if (blocknum < blocks.length) {
xCreate=event.getX();
yCreate=event.getY();
blocks[blocknum] = new Rectangle(xCreate, yCreate, 50, 50);
}
}
I'd suggest you take a look at Custom Painting, Painting in AWT and Swing and Concurrency in Swing for more details