Graphics question

C

Chris

I'm trying to write an app that allows a user to draw basic shapes on
a JPanel. I would like have the shape updated as the mouse is
dragged. For instance, if the user is drawing a line, the line would
be redrawn each time the mouse is moved until the endpoint of the line
is clicked. What I can't figure out is how to avoid redrawing every
item on the screen each time the mouse is moved. If I separate the
drawing into two methods, one for what has already been drawn and
another for what is being drawn, the previously drawn items are not
shown while the new item is being drawn.
 
F

Fred L. Kleinschmidt

Chris said:
I'm trying to write an app that allows a user to draw basic shapes on
a JPanel. I would like have the shape updated as the mouse is
dragged. For instance, if the user is drawing a line, the line would
be redrawn each time the mouse is moved until the endpoint of the line
is clicked. What I can't figure out is how to avoid redrawing every
item on the screen each time the mouse is moved. If I separate the
drawing into two methods, one for what has already been drawn and
another for what is being drawn, the previously drawn items are not
shown while the new item is being drawn.

Use XOR drawing mode while the user is creating or dragging the line,
then draw it for real using XCopy mode once the user specifies the
endpoint. This way you do not have to worry about redraws of other items
already in the picture.
 
S

Steve Burrus

Andrew said:
Wonderful! Feel free to post if
you have any questions.
Well Andrew ("Big Shot!" :)), here is at least 1 "implied" [sic]
question of his' which you could easily have "spotted" if you had of
REALLY read this post : >>"What I can't figure out is how to avoid
redrawing every item on the screen each time the mouse is moved."<< He
at least needs some help/assistance with that particular problem of
his'!! Didn't you see that?
 
C

Chris

Fred L. Kleinschmidt said:
Use XOR drawing mode while the user is creating or dragging the line,
then draw it for real using XCopy mode once the user specifies the
endpoint. This way you do not have to worry about redraws of other items
already in the picture.

I found setXORMode in the api as a method for Graphics, but haven't
seen anything on XCopy. Would I still do the drawing in the
paintComponent method or is it done in a buffer and transferred
somehow?
 
C

Chris

I found setXORMode in the api as a method for Graphics, but haven't
seen anything on XCopy. Would I still do the drawing in the
paintComponent method or is it done in a buffer and transferred
somehow?

I think that maybe I should restate the question. How do keep the
screen from being cleared each time the paintComponent method is
called?
 
A

Andrew Thompson

....
I think that maybe I should restate the question.

Or provide a code example, perhaps..
..How do keep the
screen from being cleared each time the paintComponent method is
called?

It is hard to say where you are going wrong, but
have a look at the code for this rendering example..
<http://www.physci.org/launcher.jsp?class=/codes/AnimateBalls/JAnimateFrame#80>
It can be launched using the applet at
the top of the page..

If you cannot fix the problem using ideas
from that, I recommend a code example..
 
C

Chris

Andrew Thompson said:
Or provide a code example, perhaps..


It is hard to say where you are going wrong, but
have a look at the code for this rendering example..
<http://www.physci.org/launcher.jsp?class=/codes/AnimateBalls/JAnimateFrame#80>
It can be launched using the applet at
the top of the page..

If you cannot fix the problem using ideas
from that, I recommend a code example..


I looked at your code. It appears that you redraw the grid every time
you update the ball positions. I don't want to update the background
because I will redrawing the object on every mousemove event and the
background will be very complex.
 
A

Andrew Thompson

....
...I don't want to update the background
because I will redrawing the object on every mousemove event and the
background will be very complex.

You do not have to. You could get
the grid (or whatever) from a
separate method that draws it only
the first time, then afterwards
has it pre-rendered.
.......
Still waiting on that example of
your broken code..
 
C

Chris

Andrew Thompson said:
You do not have to. You could get
the grid (or whatever) from a
separate method that draws it only
the first time, then afterwards
has it pre-rendered.
...
..
Still waiting on that example of
your broken code..


Sorry for the delay, I was on travel last week. I have reduced the
program to a minimal example. It draws a moving square over a grid
background. I would like to make it so the grid does not have to be
redrawn every time the mouse is moved.



import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class CadTest {
public static void main(String[] args) {
Frame frame1 = new Frame();
frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame1.setLocation(200, 200);
frame1.show();
}
}

class Frame extends JFrame {
public Frame() {
setSize(800, 800);
Panel panel = new Panel();
Container contentPane = getContentPane();
contentPane.add(panel);
}
}

class Panel extends JPanel {
public Panel() {
addMouseMotionListener(new MouseMotionHandler());
}
private class MouseMotionHandler implements MouseMotionListener {
public void mouseMoved(MouseEvent event) {
x = event.getX();
y = event.getY();
repaint();
}
public void mouseDragged(MouseEvent event) {
}
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
drawGrid(g2);
drawSquare(g2);
}
void drawGrid(Graphics2D g2) {
for (int i = 0; i < 160; i++) {
for (int j = 0; j < 160; j++) {
g2.drawLine(i * 5, j * 5, i * 5, j * 5);
}
}
}
void drawSquare(Graphics2D g2) {
g2.fill(new Rectangle(x, y, 20, 20));
}
int x, y;
}
 
A

Andrew Thompson

Before I answer Chris, a couple of things..

It was probably better to chase this up in
the group (where any of a score of people
might help you) rather than by dropping me
a note.

(shrugs) Firstly I may have simply been
too busy to give time to it, so may have
ignored it.. Second, just 'cos I offer you
some help in the forums, does not create some
'life bond' between us.

Lastly, it seems you are not aware of a
far better group for these type of GUI
and rendering problems, I do not know if
it has been mentioned yet..
<http://www.physci.org/codes/javafaq.jsp#cljg>

There is also a better group for people
who are just learning Java..
<http://www.physci.org/codes/javafaq.jsp#cljh>

** A warning to anybody who would dare
criticize the code I am about to post **

"Don't even *start* on me, with your
'it would be much more efficient to blit
an array to screen..' crap, damn-it!
You had the opportunity over the last *15*
days to demonstrate your cleverness in code.
So provide a better example if you will,
...if you can, but otherwise leave it out!!"
(harumph!)

Now.. (finally) my example that only writes
the grid once..

<sscce>
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;

public class CadTest {
public static void main(String[] args) {
Frame frame1 = new Frame();
frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame1.setLocation(200, 200);
frame1.show();
}
}

class Frame extends JFrame {
public Frame() {
setSize(200, 200);
Panel panel = new Panel();
Container contentPane = getContentPane();
contentPane.add(panel);
}
}

class Panel extends JPanel {

BufferedImage bi;
int width = 800, height = 800;

public Panel() {
addMouseMotionListener(new MouseMotionHandler());
}
private class MouseMotionHandler implements MouseMotionListener {
public void mouseMoved(MouseEvent event) {
x = event.getX();
y = event.getY();
repaint();
} public void mouseDragged(MouseEvent event) {
}
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
drawGrid(g2);
drawSquare(g2);
}
void drawGrid(Graphics2D g2) {
if (bi==null) {
System.out.println( "drawing grid" );
bi = new BufferedImage(width, height,
BufferedImage.TYPE_INT_RGB);
Graphics g1 = bi.getGraphics();

// initialise the background color for the size of the screen
g1.setColor( new java.awt.Color(220,220,220) );
g1.fillRect(0,0,width,height);
g1.setColor( new java.awt.Color(0,0,0) );
for (int i = 0; i < width/5; i++) {
for (int j = 0; j < height/5; j++) {
g1.drawLine(i * 5, j * 5, i * 5, j * 5);
}
}
} else {
System.out.println( "NOT drawing grid" );
}

// write the new graphic to screen in a single pass
g2.drawImage( bi, 0, 0, width, height, null );
}

void drawSquare(Graphics2D g2) {
g2.fill(new Rectangle(x, y, 20, 20));
} int x, y;
}
</sscce>

BTW - that was a good SSCCE *you* posted.. ;-)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,431
Messages
2,571,677
Members
48,796
Latest member
Greg L.

Latest Threads

Top