Skip to main content

Local Coordinate Spaces

7 replies [Last post]
Anonymous

I have a frame (800 by 600) with 2 panels in it, one above the other. The top panel is 800 by 550 and the bottom panel is 800 by 50. I did drawString at (0,10) in the bottom panel, hoping to see some text, but there was nothing there. I switched it so the skinny panel was on the top instead and the text appeared. I switched the panels back and tried to render the text lower (0,550) and it worked.

So I was thinking that graphics object that is sent to the paintComponent method of the panel has a coordinate system relative to the whole window instead of just the panel, except I noticed the contents of my 2 panels don't line up right. What's up? How do coordinates work in awt and swing?

Also, I changed my frame from a Frame to a JFrame in order to take advantage of the double buffering and now the big top panel has increased in size and is encroaching on my skinny bottom panel. Has anyone encountered this sort of thing before? How do I fix it?

Thanks,
Millie

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
shan-man
Offline
Joined: 2006-02-17

Hi Millie,

Zander's suggestion of using setLayout(null) on the content pane should solve most of your problems. I tried your code with his fixes and I saw the text in the bottom panel.

However, I would like to give you a couple more pointers about your code. First of all, you should be overriding "paintComponent(Graphics g)" and NOT "paint(Graphics g)". Overriding "paint" was an AWT-ism that we don't recommend any more. In fact, I beleive doing so interferes with double-buffering.

The second thing is that you don't need to call "getRootPane().setDoubleBuffered(true)" to turn on double-buffering. It's on by default.

The last thing: Even after Zander's changes, the top panel is getting clip bounds of 792 x 550 on my machine even though you tell it to be 800 x 550. The reason you'r getting 792 instead of 800 width is that you've set the JFrame width to 800 and the JFrame needs space to draw its edges.

Instead of calling setSize() on the JFrame, I recommend providing your own content pane with a preferred size set. Then you can call "pack()" on the JFrame and it will size itself accordingly. Something like:
[code]
JPanel p = new JPanel();
p.setLayout(null);
p.setPreferredSize(new Dimension(800, 600));
jframe.setContentPane(p);

// add and position items on the content pane

jframe.pack();
frame.show(); // setVisible(true) is preferred here
[/code]
Regards,
Shannon

Anonymous

Thanks for the help, y'all. I think I get it now :)

-Millie

zander
Offline
Joined: 2003-06-13

Did you override the 'paint(Graphics)' method? That one should get the correct coordinates.

If that does not help; please post the trimmed down sourcecode; just enough code to show the problem but still be runnable.

Anonymous

Here's the code. See how it changes when you switch between Frame and JFrame? Also, why is the clipping bounds of the top frame not 800 x 550?

[code]
import java.awt.*;
import javax.swing.*;

public class Thingy extends JFrame{

private class eViewPanel extends JPanel{
public eViewPanel() {
super();
}

public void paint(Graphics graphics) {
super.paint(graphics);
graphics.setColor(new Color(0,0,0));
graphics.setFont(new Font("Helvetica", Font.PLAIN, 22));
String msg="Clip bounds = (" + graphics.getClipBounds().width +","+graphics.getClipBounds().height+")";
graphics.drawString(msg,100,100);
}
}

private class eStatusPanel extends JPanel{
public eStatusPanel(){
super();
}

public void paint(Graphics graphics){
super.paint(graphics);
graphics.setColor(new Color(255,255,255));
graphics.setFont(new Font("Helvetica", Font.PLAIN, 22));
String msg="Hello";
graphics.drawString(msg,20,555);
}
}

public Thingy() {
super("My Thingy");
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice gs = ge.getDefaultScreenDevice();
GraphicsConfiguration gc = gs.getDefaultConfiguration();

eViewPanel view = new eViewPanel();
eStatusPanel status = new eStatusPanel();

Rectangle bounds = gc.getBounds();
setLocation(10 + bounds.x, 10 + bounds.y);
setSize(800,600);

view.setBounds(0,0,800,550);
view.setBackground(new Color(255,255,255));
status.setBounds(0,550,800, 50);
status.setBackground(new Color(0,0,0));
view.setCursor(new Cursor(Cursor.HAND_CURSOR));
status.setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR));

//** Switch these when changing between Frame and JFrame
//add(view);
//add(status);
getContentPane().add(view);
getContentPane().add(status);
getRootPane().setDoubleBuffered(true);

show();
}

public static void main(String[] args) {
new Thingy();
}

}
[/code]

Message was edited by: Millie

zander
Offline
Joined: 2003-06-13

Add this line:
[code]
getContentPane().setLayout(null);
[/code]

Since you are using setBounds you assumed a NullLayout, but in a JFrame the default has some Swing internal layout manager.
The above resets that again.

Anonymous

Hm. Good point but that didn't seem to actually change any of the visual results.

zander
Offline
Joined: 2003-06-13

hmm?
I changed this to get the local coordinate space; like you asked.
I see the text in the bottom part.

[pre]
--- Thingy.old 2003-11-30 12:47:33.000000000 +0100
+++ Thingy.java 2003-11-30 12:46:32.000000000 +0100
@@ -27,7 +27,7 @@
graphics.setColor(new Color(255,255,255));
graphics.setFont(new Font("Helvetica", Font.PLAIN, 22));
String msg="Hello";
- graphics.drawString(msg,20,555);
+ graphics.drawString(msg,20,20);
}
}

@@ -54,6 +54,7 @@
//** Switch these when changing between Frame and JFrame
//add(view);
//add(status);
+ getContentPane().setLayout(null);
getContentPane().add(view);
getContentPane().add(status);
getRootPane().setDoubleBuffered(true);
[/pre]