Graphics2D Problem

Hi all,

I have a program which creates a guitar fretboard by using geometric primitives. I have all that stuff sorted out.

Inside the paint(Graphics g) method of the class, I have a nested class which handles the mouse events. This class works fine.

In the mouseClicked method, I have it set to draw a dot where the mouse was clicked. The dot draws but here is my problem.

When I click on the image drawn by the paint method once, all the lines and what not, turn bold. I think it has something to do with the rendering but I wasn't able to change it.

In the mouseClicked method I tried what worked for me OUTSIDE of the nested method in paint(Graphics g), which was just

g2.fill(new Ellipse(x, y, w, h);

But that did not work.

Currently what I am doing inside the mouseClicked method is:

g2.fill(new Ellipse(x, y, w, h);

repaint();

but this causes the image to change and isn't drawn until the second click.

The first few lines of my paint(Graphics g) method are as follows, I have included the rendering hints

g2 = (Graphics2D) g;

g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

I am not sure why it takes one mouse click to 'initialize' the image, and I'm not sure why the image changes to a bold formatting. Also, I have tried to put another setRendering statement before I draw the ellipse but no success.

Thanks for the help!

Message was edited by:

kerryblue19

[1599 byte] By [kerryblue19a] at [2007-11-27 5:44:14]
# 1

When you say "turn bold" it makes me think you are painting on top of existing graphics repeatedly. But that's just a guess.

Unfortunatley the code snippets you provided do not elucidate enough of your problem to allow more useful answers to be rendered.

You need to create a [url=http://homepage1.nifty.com/algafield/sscce.html]Short, Self Contained, Compilable and Executable, Example Program[/url] (SSCCE) that demonstrates the incorrect behaviour, because we can't guess exactly what you are doing based on the information provided.

cotton.ma at 2007-7-12 15:24:44 > top of Java-index,Java Essentials,Java Programming...
# 2

The best strategy is to do *no* drawing in event handlers -- do no drawing in mouseClicked or mousePressed.

Instead, do all your drawing in paintComponent, and code called from paintComponent.

But how can you get clicking to yeild changes? In your mouse mousePressed

handler, change the state of the component -- add a finger position to its state, then call repaint.

That will cause the component to redraw itself.

Hippolytea at 2007-7-12 15:24:44 > top of Java-index,Java Essentials,Java Programming...
# 3

thanks for the help, I appreciate it!

cotton.m: I dont have my laptop setup at work yet but once I do I will get the SSCCE going. I agree that it is painting on top of the existing graphics, infact I'm positive, and that was a good suggestion.

Hippolyte: I don't quite understand. Right now I have a paint() method that is automatically called, and inside that method is my nested mouse events class. I'm not sure how to change the state of the component with regards to a user clicking on the diagram.

Thanks again!

kerryblue19a at 2007-7-12 15:24:44 > top of Java-index,Java Essentials,Java Programming...
# 4

Demo:

import java.awt.*;

import java.awt.event.*;

import java.util.*;

import javax.swing.*;

public class ComponentExample extends JPanel {

private static final long serialVersionUID = 0;

private java.util.List < Point > points = new ArrayList < Point > ();

private MouseListener ml = new MouseAdapter() {

public void mousePressed(MouseEvent evt) {

points.add(evt.getPoint());

repaint();

}

};

public ComponentExample() {

addMouseListener(ml);

}

protected void paintComponent(Graphics g) {

super.paintComponent(g);

for(Point p : points)

g.drawRect(p.x-5, p.y-5, 5, 5);

}

public static void main(String[] args) {

EventQueue.invokeLater(new Runnable(){

public void run() {

JComponent comp = new ComponentExample();

comp.setPreferredSize(new Dimension(400,300));

JFrame f = new JFrame("ComponentExample");

f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

f.getContentPane().add(comp);

f.pack();

f.setLocationRelativeTo(null);

f.setVisible(true);

}

});

}

}

Hippolytea at 2007-7-12 15:24:44 > top of Java-index,Java Essentials,Java Programming...
# 5

Hey, I have partially solved the problem.

cotton was right in that is was repainting the whole diagram, so what I did was in my paint(Graphics g) method I surrounded all of the code except the mouse listener and the

Graphics2D g2 = (Graphics2D)g;

g2.setRenderingHint(...);

with an if statement such as

if(counter==0){

//create diagram

}

and then in the mouse clicked method, before I repaint i just change the counter to 1 and there is no redrawing, and the dots are drawn.

What still remains though is that I still need to click once on the diagram to 'instantiate' it, it seems, and then from that point on I can click and the ellipses will show up.

I'm not sure why this is.

Message was edited by:

kerryblue19

kerryblue19a at 2007-7-12 15:24:44 > top of Java-index,Java Essentials,Java Programming...
# 6
I'm having a hard time believing that your mouse listener is truly "in" your paintComponent method.
Hippolytea at 2007-7-12 15:24:44 > top of Java-index,Java Essentials,Java Programming...
# 7
I'm confused. I have a nested class in my paint(Graphics g) method.
kerryblue19a at 2007-7-12 15:24:44 > top of Java-index,Java Essentials,Java Programming...
# 8
> I'm confused. I have a nested class in my> paint(Graphics g) method.I don't know if I want to see the whole code, but could you write a sample program that demonstrates what you are trying to do with a nested class there?
Hippolytea at 2007-7-12 15:24:44 > top of Java-index,Java Essentials,Java Programming...
# 9

here is the paint method, the formatting doesn't translate very well.

public void paint(Graphics g) {

g2 = (Graphics2D) g;

g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,

RenderingHints.VALUE_ANTIALIAS_ON);

if(counter==0){

initBoundMap();

//Create Point2D.Double

Point2D.Double point = new Point2D.Double(x1, y1);

//Create Point2D.DoubleX

Point2D.Double point2 = new Point2D.Double(x2, y1);

// DRAWS THE NUT

g2.setStroke(new BasicStroke(nutThick));

g2.draw(new Line2D.Double(point, point2));

// SETS STRING THICKNESS

g2.setStroke(new BasicStroke(stringThick));

// DRAWS THE STRINGS

drawStrings(g2);

// LABELLING THE NOTE AND DEGREE ROWS

g2.setFont(new Font("Dialog", Font.BOLD, 15));

g2.drawString( "Notes: ", x1-labelOffset,

y1+stringLen+letterOffsetY);

g2.drawString( "Degrees: ", x1-labelOffset,

y1+stringLen+letterOffsetY+lineSpace);

// SETS FRET NUMBER LABEL FONT

g2.setFont(new Font("Dialog", Font.PLAIN, 13));

// DRAW AND NUMBER FRETS

numberDrawFrets(g2);

// DOT DRAW

//g2.setPaint(black);

//g2.fill (new Ellipse2D.Double(50, 50, 20, 20));

}

class MouseClickListener implements MouseListener{

public void mousePressed(MouseEvent event) {

int x = event.getX();

int y = event.getY();

double ellipseDim = 15;

for(int i=0; i<boundMap.size(); i++){

if( ((Rectangle2D)(boundMap.elementAt(i))).contains(x, y) ){

g2.fill(new

Ellipse2D.Double(((Rectangle2D)(boundMap.elementAt(i))).getX()+distBnSt/2-ellipseDim/2,

((Rectangle2D)(boundMap.elementAt(i))).getY()+distBnFt/2-ellipseDim/2,

15, 15));

counter=1;

break;

}//end if

}//end for

repaint();

}//end mousePressed

}//end MouseClickListener

MouseClickListener listener = new MouseClickListener();

addMouseListener(listener);

}

}//end paint

>

kerryblue19a at 2007-7-12 15:24:44 > top of Java-index,Java Essentials,Java Programming...
# 10

Is this a good summary of that paint:

public void paint(Graphics g) {

//yada yada

class MouseClickListener extends MouseAdapter {

public void mousePressed(MouseEvent event) {

//yada yada

}

}

MouseClickListener listener = new MouseClickListener();

addMouseListener(listener);

}

My trouble with that is that *every time* paint is called (which is a lot!)

you create another listener and add it to the collection of listeners for

that component. Are you sure you want to do that -- have tons of listeners?

Hippolytea at 2007-7-12 15:24:44 > top of Java-index,Java Essentials,Java Programming...
# 11

hey, great point.

I now have a constructor for my class, and in that i have added the mouseclicklistener, and have moved the MouseClickListener class out of the paint method.

But I still get the annoying, first click initializes, and then every subsequent click creates a dot.

Thanks for the help, i appreciate it

kerryblue19a at 2007-7-12 15:24:44 > top of Java-index,Java Essentials,Java Programming...
# 12
I still don't think you mousePressed method should mention g/g2. See my example -- change the state and call repaint.
Hippolytea at 2007-7-12 15:24:44 > top of Java-index,Java Essentials,Java Programming...
# 13

Is that code for real?!

You do realize that everytime the paint method is called you are adding a new MouseListener to your listener pool right?

Don't believe me?

Just use the mouse to drag the window frame for your application all across the screen and keep doing that until you get an OutOfMemoryError.

You need to have a variable of some kind that keeps track of a state. Have your mouse listener SEPERATE from your paint method and when the mouse is clicked the state is changed. The paint method would then paint differently depending on the state of the variable.

I am also willing to wager that you have to click once to get graphics because your mouse listener contains your graphics context. It will never paint anything to screen until a mouse event is recieved.

maple_shafta at 2007-7-12 15:24:44 > top of Java-index,Java Essentials,Java Programming...
# 14
That's what I've been saying.
Hippolytea at 2007-7-12 15:24:44 > top of Java-index,Java Essentials,Java Programming...
# 15
Okay well that's why I'm here asking how I can fix the one click thing. This is my first time using any sort of paint/mouselistener/graphics stuff.
kerryblue19a at 2007-7-21 21:34:13 > top of Java-index,Java Essentials,Java Programming...
# 16
If you understand reply 4, you know all you need, to correct your code.
Hippolytea at 2007-7-21 21:34:13 > top of Java-index,Java Essentials,Java Programming...
# 17
If you read my posts you would see that the one click issue IS what I'm looking to fix.
kerryblue19a at 2007-7-21 21:34:13 > top of Java-index,Java Essentials,Java Programming...
# 18
Maple_shaft: I do get graphics without having to click, but as I said before, the problem comes when I am trying to click on the diagram so that a dot will appear where I have clicked.
kerryblue19a at 2007-7-21 21:34:13 > top of Java-index,Java Essentials,Java Programming...
# 19

> Maple_shaft: I do get graphics without having to

> click, but as I said before, the problem comes when I

> am trying to click on the diagram so that a dot will

> appear where I have clicked.

Within your class you can specify an anonymous inner class for your mouselistener like so.

MouseListener ml = new MouseAdapter() {

public void mouseClicked(MouseEvent evt) {

//Your code here

repaint();

}

} ;

If you don't know anything about anonymous inner classes then I suggest you learn about them. There are plenty of tutorials that explain the concepts.

The MouseEvent object in the mouseClicked method contains a method that will return the coordinate at which the click was made on your screen. You can assign that coordinate to a Point object. That point object must be a member variable of your class and not your MouseListener so that your paint method will be able to access its data.

The mouse listener can be added ONCE to your button or any component for that matter.

component.addMouseListener(ml);

Dukes?

maple_shafta at 2007-7-21 21:34:13 > top of Java-index,Java Essentials,Java Programming...