jQuery in Action, 2nd edition*
The moose likes Swing / AWT / SWT and the fly likes constructing a component (beginner) Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Swing / AWT / SWT
Bookmark "constructing a component (beginner)" Watch "constructing a component (beginner)" New topic
Author

constructing a component (beginner)

Peter Merker
Ranch Hand

Joined: Oct 18, 2003
Posts: 37
Hi all,

I'm beginning to learn Swing/AWT, so my question might be a bit silly:
We've got the task to write a program which plays the game Tower of Hanoi.
I started with the smallest thing, the disc that will be put on
one of the three towers. This slice should be a rectangle with rounded edges.
So there is this class java.awt.geom.RoundRectangle2D.Double which nearly
completely fulfills my needs. Would it make sense to inherit it? But then the children class wouldn't be either a Component (AWT) nor a JComponent (Swing), or? If so, does this mean that an overridden (or newly implemented)wouldn't be called by the graphic system, so this object would never appear?
Should I therefore instead write a disc class that inherits from JComponent and just put a RoundRectangle2D member variable inside it?
I think I might be on the right track, just need some reassurement (or advice).

Thanks for your replies.
Craig Wood
Ranch Hand

Joined: Jan 14, 2004
Posts: 1535
Some general statements in response to your questions:
1 - When it comes to rendering graphics in java the field of possibliity is wide and deep. To get started consider two possibilities:

Create a JComponent, usually a JPanel but there are other options, override the paintComponent method and draw your graphics in it. Then you can add the component to a container (with or without a layout manager depending on your needs). You can move the components with mouse code — directly if the layout manager is set to null or via the layout manager if you have one.

Create a JComponent, usually a JPanel, and draw your graphics on it (inside its paintComponent method). You can use mouse code to select and move the shapes (lines, ellipses, rectangles, polygons, etc) around.

2 - In drawing we generally work with composition rather than inheritance. This means that we instantiate (make an instance of) the classes we want, eg, Line2D, Polygon, RoundRectangle2D, and put them to work. This keeps things simple, easy to manage and work with.

3 - In Swing (J country) we usually override the paintComponent method for custom graphics/drawing. The paint method in JComponent calls other painting methods and its use for drawing requires special care. Look at the paint method in the Method Summary section of the JComponent api and follow the link into the Method Details section for details.
Craig Wood
Ranch Hand

Joined: Jan 14, 2004
Posts: 1535
Peter Merker
Ranch Hand

Joined: Oct 18, 2003
Posts: 37
Thanks Craig, that seems to be a profound answer. Actually, I meant the
paintComponent method, I just mistyped it.
But I don't understand the choice between those two possibilities. Don't you always have to add the JComponent (in this case JPanel) to the contentPane?
So how should my overall design look like? This game is supposed to be
played/solved by the computer, so no mouse code is necessary.
My idea was/is, that you have a JFrame filled by a game-JPanel with
GridLayout(1,3) which is filled with three tower-JPanels. If the discs would inherit from JComponent, each towerPanel could have a paintComponent method like this:

As you can see, I had the idea of a cascading call routine through all
paintComponent methods. Maybe even starting with

in the gamePanel. Or is this a misleading idea?
Craig Wood
Ranch Hand

Joined: Jan 14, 2004
Posts: 1535
But I don't understand the choice between those two possibilities. Don't you always have to add the JComponent (in this case JPanel) to the contentPane?

Yes. I'll try to clarify. In the second possibility there is only one JPanel and all three towers and all three rings are painted on it. It is added to the center section of the JFrame.

In the first possibility, the one you are working with, each tower is painted in its own panel and all three JPanels are added to another JPanel with GridLayout and this panel is added to the JFrame. Where I went with the earlier idea was that each ring is painted on its own JPanel and the JPanel is added to the appropriate tower JPanel. So there are 6 components not counting the JPanel that holds the three towers. You can set the layout to null in the tower JPanels, add the rings and position them over the towers with setBounds.

You seem to be working on yet another possibility which is to paint the rings in the appropriate tower panel. About the code in your last post. It is unwise to call any paint or repaint method from within a paint or paintComponent method. It results in severe tail–chasing.

But you can have the disc draw itself. You can put a draw method in the Disc class and in your paintComponent method do

The drawing part seems pretty easy as far as it goes. But the code to move and position the rings seems to weigh more heavily as a design consideration.
Peter Merker
Ranch Hand

Joined: Oct 18, 2003
Posts: 37
Your idea with each disk as a different JPanel seems to be the same as mine, except that my disks are not JPanels but JComponents (which shouldn't make any difference, or?). After spending some time understanding how recursive algorithms for the game solution work - a good explanation can be found here
http://www.coderanch.com/t/366574/java/java/gc-string-pool
1
. I now started to think about the layout question. I have a tower which is a JComponent consisted of one filled vertical rectangle and one filled horizontal rectangle as the base. This component should certainly be underneath the disks. It seems that it doesn't work to put one JComponent or JPanel on another in the same cell of a GridLayout. The components will all be ordered in one row, side by side. Consulting my books, I found JLayeredPane. In a LayeredPane you can have components in different layers, so that they can overlap. But it doesn't seem to be possible to use different LayoutManagers inside a LayeredPane the way I would like to do it. I would like to have the tower on an underlying pane without a special LayoutManager or maybe FlowLayout. Then the disks should be ordered on an upper pane by a BoxLayout. But as I understand it, you can only use ONE LayoutManager inside a LayeredPane, and then all components on all Layers will be ordered in a twodimensional way, without overlapping.
So I read further and discovered OverlayLayout and the possibilities of writing your own LayoutManager or working without a LayoutManager by direct
positioning. The various possibilities irritate me a bit. I would like to avoid absolute positioning in order to enable resizing and an adequate look with different screen resolutions. So how can I have an exact relative
positioning of tower and discs? The information I got about OverlayLayout says it does layout components in an inexact way. In this thread
http://www.coderanch.com/t/330272/GUI/java/URL-connection-applet-jdbc
0
I found a custom LayoutManager derived from OverlayLayout. I played around with it, but I can't get it to work. Whereas the original OverlayLayout puts the discs on top of the tower (so that you can't see the tower anymore - I don't know yet how to adjust the size of the discsPanel so that the towerComponent is looking through at the bottom and the top), this variation paints the standard background color on top of my white backgound and nothing else. But is it wise to use an OverlayLayout anyway or should I try out the other before mentioned possibilities?

[ September 08, 2004: Message edited by: Peter Merker ]
[ September 08, 2004: Message edited by: Peter Merker ]
Craig Wood
Ranch Hand

Joined: Jan 14, 2004
Posts: 1535
To set the size of your JPanel or JComponent Disc you can use setPreferredSize or you can override getPreferredSize in the Disc class and return the size you want for the component.


But is it wise to use an OverlayLayout anyway or should I try out the other before mentioned possibilities?

Learning your way around with and through the various layout possibilities and options is cetainly frustrating. But well worth the trouble in the long run. And it can be very satisfying to write a custom layout manager. I like to find the little ins and outs of using java out–of–the–box to get things done with a minimum of custom code. So my recomendations to you are colored and distorted by this preference/chosen limitation.

I hope this doesn't come across as heavy–handed but it feels like what is here to say. Consider some options:
1 - Absolute positioning: I see you have rejected this because of resizing issues. You can set it up so that all components and graphics fluidly resize in proportion to the JFrame or parent component size by specifying their sizes in terms of the current width and height of their parent container.

2 - OverlayLayout is an easy way to overlap components for graphics (and mouse work over multiple components) and avoids some of the problems with GlassPane (see JRootPane api) and JLayeredPane. It seems like you could add the (properly sized) discs to a JComponent or non–opaque JPanel with a GridBagLayout and set this over the tower panel (containing the tower component) in an OverlayLayout. I haven't tried the GridBagLayout placement part but it seems feasible and would relieve you of the details of managing the absolute positioning.

3 - Painting the tower on it's own JPanel/JComponent seems easier than managing the tower as a component. In this case you could use a single JPanel and add the Discs to it with a layout manager (GridBag, custom, ...).
Peter Merker
Ranch Hand

Joined: Oct 18, 2003
Posts: 37
Craig, I really appreciate your help! Makes things less tough...
I now got to the point of using a Box class for the discs. I'm still trying to understand how this whole layout thing works, especially how the component sizes each influence the other. I found out that by adding HorizontalStruts to my Box class I could have the bottom and the top of the tower look through. Trying out your Disc class: The discs kept their defined size, but there is a changing space between them if I resize. I guess, I have to create a chain of links between the sizes of the top level container, a JFrame, over the three towerPanels to the three towerComponents, to the discComponents. Is there a possibility for a JComponent or JPanel to access its containers size, or do I have to pass the container through to all nested JComponents? Seems weird to me, to pass the JFrame... Though it would certainly also be an idea just to pass a Dimension object for the size information. Although the Sun Swing Tutorial describes the way layout management works the other way around: Questioning the smallest components inside a frame for their preferred size and then adding it all up to determine the size of the frame itself. So should I start with the disc and determine their size by a call to Toolkit.getDefaultToolkit().getScreenSize()? But then I have fixed dimensions for the discs and the resize problem again.
This is really tricky... It would be strange to add more HorizontalStruts if the window becomes larger and remove them, if it becomes smaller. Another question: What's the difference between setPreferredSize() and setBounds()? I have read that some LayoutManagers respect the preferred size and give the component that space if it is available. So what is setBounds() for?
[ September 08, 2004: Message edited by: Peter Merker ]
Craig Wood
Ranch Hand

Joined: Jan 14, 2004
Posts: 1535
Once a component has been realized, viz, placed in a top–level Container which has had pack or setVisible called on it, you can freely ask it for it's size (getSize) or preferred size (and minimum/maximum sizes if they have been set).

The setBounds method is most useful for absolute positioning (null layout) in which you must add your component to the container and also specify size and location information for it to be shown. setBounds is also very useful in finding location and size information of components in animations and mouse code that moves/positions components. It doesn't do much for you with respect to layout managers.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: constructing a component (beginner)
 
Similar Threads
Swing and AWT in an Applet
Difference between JFrame and JPanel
a question about the restriction to the assignment
Doubts regarding AWT/Swing Design
Interface or inheritance to ensure a base class