Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations derfloh on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Swing object placement

Status
Not open for further replies.

relisys

Programmer
Mar 6, 2003
65
GB
Hey guys,

Quick one (*cough*) for you all!

Am writing an applicaiton that uses skins, and to do this I have overridden the paint method of a JWindow. All items are drawn onto this window using Label.paint(Graphics g) onto the content pane.

This works fine for AWT objects, painting them in the right place from a setx() & sety() method, however Swing objects only paint in the top left corner no matter how you set their position.

I got round this by using the Graphics.create(x, y, width, height) using the getx(), gety(), getheight() and getWidth() methods.

This works for JTextArea and JTextField but now when I try it for JSlider and JCheckBox it causes the display to fail to update on PC and on Mac OS X it crashes the postscript rendering engine.

I use the following for AWT:
if (awayButton.isVisible()) awayButton.paint(offScreenG);

and this for Swing:
Graphics smallBit = offScreenG.create(scroller.getX(),scroller.getY(),scroller.getWidth(),scroller.getHeight());
if(scroller.isVisible()) scroller.paint(smallBit);

Can anyone suggest a better way to place the Swing objects?

Or does anyone know a fix to the update problem?

Cheers!


Relisys



 
>> All items are drawn onto this window using Label.paint
>> (Graphics g) onto the content pane.

That could be the source of your problem. I have not done any swing drawing but i don't think it is designed to use paint() and even in AWT you are not supposed to call paint() directly.


-pete
 
This is certainly not a "Quick one (*cough*) for me". Are you building a (postscript) rendering engine ?

Instead of creating many "Graphics" objects with the create method, can you use "getGraphics()" ?
Can you cast the Graphics object to a Graphics2D object (giving you more functionality) ?
Why do you take this approach ?
What are skins anyway ?

These are more questions then answers ...
If your code is not secret, can you post it ? Then maybe someone can give you answers. I don't want to start from scratch on this.
 
Hi, thanks for your replies. in answer to the questions:

No I'm not writing a postscript rendering engine. MacOS X renders all screen graphics as postscript (which is I'm glad of, otherwise I would never of figured out what was going wrong).

I could cast to a G2D, but I don't think this would help much.

Skins is a way by which different customers can have a different look to their software, because every widget is read from a gif/jpeg file, and located according to a properties file. You may ask why not use PLAF, but this couldn't provide the flexibility needed.


This is why this approach is taken, because I have a custom Layout Manager for loading the images and placing them correctly. I have had to overide the pdate/paint methods of JWindow and hijack the GUI thread because I am using JWinodw instead of JFrame, so as to be able to have no title bar (I know Java 1.4 now has this option, but tht would be a MAJOR rewrite!), but also, it is the only way to invoke the LayoutManager properly.

I know this all looks like a really strange way of doing things, but up to this point it has worked quite well and is quite efficient.

So, any further help would be greatly appreciated. unfortunately, the boss won't let me release anymore code, but there isn't much more going on than in the lines above.

Thanks again for the replies so far.

Relisys
 
Relisys,

I wrote a little pgm to simulate your problem, but I do not get anything in my JFrame, so I must be doing something wrong. If I can't simulate your problem I cannot search for a fix. Can you tell me what you are doing differently ?

Holo

Code:
import javax.swing.*;
import java.awt.*;

/**
 * <p>Title: </p>
 * <p>Description: </p>
 * <p>Copyright: Copyright (c) 2002</p>
 * <p>Company: ECC</p>
 * @author Hologram
 * @version 1.0
 */

public class TestPaint {

  public TestPaint() {
  }

  public static void main(String[] args) {
    TestPaint testPaint = new TestPaint();
    testPaint.doIt();
  }

  public void doIt() {
    MyFrame f = new MyFrame(&quot;Test&quot;);
    f.getContentPane().setLayout(null);
    f.setSize(600, 600);
    f.setVisible(true);
  }

  public class MyFrame extends JFrame {

    public MyFrame(String title) {
      super(title);
    }

    public void paint(Graphics g) {
      super.paint(g);
      JButton b = new JButton(&quot;OK&quot;);
      JTextField t = new JTextField(&quot;JTextField&quot;);
      System.out.println(&quot;Graphics=&quot; + g);
      t.setBounds(100,100,200,20);
      t.paint(g);
      b.paint(g);
      Button ab = new Button(&quot;AWT&quot;);
      ab.setBounds(100,300,200,20);
      ab.paint(g);
    }
  }

}
 
Code:
public void paint(Graphics g) {
      super.paint(g);
      JButton b = new JButton(&quot;OK&quot;);
      JTextField t = new JTextField(&quot;JTextField&quot;);
      System.out.println(&quot;Graphics=&quot; + g);
      t.setBounds(100,100,200,20);
      t.paint(g);
      b.paint(g);
      Button ab = new Button(&quot;AWT&quot;);
      ab.setBounds(100,300,200,20);
      ab.paint(g);
    }
Ok that violates just about every principle that I thought I understood so if there is something I am totally unaware of could someone please clue me in?

-pete
 
Ok guys. Sorry for giving you all such a headache. As far as I know, this is quite common amongst Games programmers to capture the GUI thread, so that they can guarantee the number of frames per second. Otherwise, the screen would only repaint when it wanted to. In fact, I believe this is essentially the same as that very first animation applet that everyone learns. (you know, tumbling jack for Sun people, spinning globe for VisualJ++).

I think that the reason you see nothing is that you are painting to the contentPane. I paint to an offScreen Graphics object, by doing the following:

offScreenImg = this.createImage(d.width, d.height);
offScreenG = offScreenImg.getGraphics();

I paint to offScreenG, then paint offScreenImg on to the main graphics.

This is the same as DoubleBuffering, which Swing now supports natively, but I prefer to have full control of it.

If this is not the reason for why nothing is being displayed, then I can only gess that it is the LayoutManager.

P.S. I am very impressed that you'd go to such lengths to try and help. If I can't figure it out, I'm going to re-write JSlider and JCheckBox to be skinnable themselves. Big task.

Thank you again.

Relisys
 
relisys

Sure, double buffering, been doing that in Java since 1996. The part i have never seen before is creating new Swing components during each paint() cycle AND having them paint themselves to the memory Graphics object. Very interesting, although i would hope the objects would be cached rather than being created each time.

So my question is, why do this? What is the goal? With this approach the components will not generate any events correct? So why do you want them at all? Esentially your creating a picture of them and painting the picture onto the screen.


-pete
 
Ah, no. I'm not creating them each time. That's what hologram did. No, I have them created already and added to JPanel etc. (incidenally, mine extends JPanel not JFrame. my mistake).

I only use this type of code for painting them.

If I don't override paint and add them explicitly, they don't paint at all. Probably because my LayoutManager isn't up to spec. They do generate events correctly, btw.

So, yeah. Creating a picture of them, then painting onto the screen. Because I don't use any Java native widgets (except trying to use JSlider, hence the questions and JTextArea which works) I need to paint my buttons as GIF images. They are not JButtons, they are my own custom SkinButton class that draws the image from a file, and generates events in the way I choose, etc. All this is so that locations and images for all buttons can be loaded from a properties file. as can text for labels, font names, background image, etc.

Does this sound cool, by the way? Have you ever heard of anyone doing this in Java? I know lots of people do it in VisualC++, but that's a lot easier to do (e.g. WinAmp has done this for donkey's years). We do have a genuine customer need for it, because our software will resell to different people, but they don't want it to look like the same piece of software. So buttons in different places, with different images makes a different piece of software as far as they are concerned, but for us it's one file to edit.

Thanks for the continued interest.

Relisys
 
I am in the process of finishing up an app that dynamically creates/ destroys grids of JComponents based on sliders or user input size.

The trick for me was calling validate() and repaint() at the proper points after creating/destroying new components.

If it sounds like I can help, and you want specifics, let me know.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top