|
||||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |
java.lang.Objectjava.awt.Component
java.awt.Container
javax.swing.JComponent
javax.swing.JPanel
bb.gui.LinePanel
public class LinePanel
A Swing container that resembles the AWT container Box
:
it always lays out its Components in a single line (that can be either horizontal or vertical),
and it does not allow the LayoutManager to be changed from what it was constructed with.
Besides being an AWT widget, Box is not as easy to use as it could be.
In particular, it usually requires the user to add a Border
to it to effect spacing with its parent Container.
Likewise, it requires the user to add explicit "glue", "strut" or "rigid areas" Components inside it
to effect spacing and sizing among its contents.
In contrast, this class is always configured to automatically insert gaps between Components that touch the edge of the parent Container, as well as gaps between Components inside it. Consequently, usage is trivial: an instance is created via one of the factory methods, and then you simply add those Components you really care about to it. For example, here is how you can create a Container that holds a horizontal row of buttons:
JButton jbutton1 = new JButton("jbutton1");
JButton jbutton2 = new JButton("jbutton2");
// then do whatever configuration is need on those buttons, like add ActionListeners
// can easily create a Container to hold all those buttons as follows:
LinePanel linePanel = LinePanel.makeHorizontal();
linePanel.add( jbutton1 );
linePanel.add( jbutton2 );
Some layout issues have been seen with this class.
The first issue is that have seen instances get shrunk much more than seems reasonable. This class currently uses GroupLayout for its LayoutManager, and this issue seems to only happen when this class is used in a GUI with other Containers that have different LayoutManagers. It appears to be caused by older LayoutManagers or Components doing screwy things with preferred and maximum sizes. The cure is to always use this class, or at least always use GroupLayout (or some other modern LayoutManager?) in other Containers.
The second issue that have seen is sometimes a JTextArea embedded inside a JScrollPane will stretch far more than it ought to (e.g. to the point where the scroll bars are outside the window). This only seems to happen when the text gets really large (in either rows or columns). This is a bug with GroupLayout (see this bug report as well as my JScrollPaneDemo class in my singleShotPrograms project). One cure is to limit the preferred size of the JScrollPane with code like this:
private JComponent buildTextArea(String text) {
JTextArea jtextArea = new JTextArea();
//jtextArea.setXXX(...); // do whatever configuration is needed
JScrollPane jscrollPane = new JScrollPane(jtextArea);
jscrollPane.setPreferredSize( SwingUtil.screenSize() ); // CRITICAL: if do not call this, have seen the JScrollPane get made WAY bigger than the window, which is bad, since cannot see the scroll bars plus other components get pushed off screen
return jscrollPane;
}
Like typical Java GUI code, this class is not multithread safe:
it expects to only be called by EventQueue
's dispatch thread
.
This threading limitation is checked in every public method.
Nested Class Summary | |
---|---|
static class |
LinePanel.Axis
Enum of the possible orientations of the axis that components will be laid out along. |
static class |
LinePanel.UnitTest
See the Overview page of the project's javadocs for a general description of this unit test class. |
Nested classes/interfaces inherited from class javax.swing.JPanel |
---|
JPanel.AccessibleJPanel |
Nested classes/interfaces inherited from class javax.swing.JComponent |
---|
JComponent.AccessibleJComponent |
Nested classes/interfaces inherited from class java.awt.Container |
---|
Container.AccessibleAWTContainer |
Nested classes/interfaces inherited from class java.awt.Component |
---|
Component.AccessibleAWTComponent, Component.BaselineResizeBehavior, Component.BltBufferStrategy, Component.FlipBufferStrategy |
Field Summary | |
---|---|
private LinePanel.Axis |
axis
Contract: is never null. |
private GroupLayout |
groupLayout
Contract: is never null. |
private GroupLayout.Group |
groupParallel
Contract: is never null. |
private GroupLayout.Group |
groupSequential
Contract: is never null. |
private static long |
serialVersionUID
|
Fields inherited from class javax.swing.JComponent |
---|
accessibleContext, listenerList, TOOL_TIP_TEXT_KEY, ui, UNDEFINED_CONDITION, WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, WHEN_FOCUSED, WHEN_IN_FOCUSED_WINDOW |
Fields inherited from class java.awt.Component |
---|
BOTTOM_ALIGNMENT, CENTER_ALIGNMENT, LEFT_ALIGNMENT, RIGHT_ALIGNMENT, TOP_ALIGNMENT |
Fields inherited from interface java.awt.image.ImageObserver |
---|
ABORT, ALLBITS, ERROR, FRAMEBITS, HEIGHT, PROPERTIES, SOMEBITS, WIDTH |
Constructor Summary | |
---|---|
LinePanel(LinePanel.Axis axis,
boolean isDoubleBuffered)
Constructs a new LinePanel with the specified LinePanel.Axis and buffering strategy. |
Method Summary | |
---|---|
protected void |
addImpl(Component comp,
Object constraints,
int index)
|
private void |
initLayout()
|
static LinePanel |
makeHorizontal()
Returns a new LinePanel with a horizontal GroupLayout layout manager and a double buffer. |
static LinePanel |
makeVertical()
Returns a new LinePanel with a vertical GroupLayout layout manager and a double buffer. |
private void |
readObject(ObjectInputStream ois)
Customizes deserialization. |
void |
setLayout(LayoutManager mgr)
Overrides the superclass version to forbid changing the LayoutManager after construction. |
Methods inherited from class javax.swing.JPanel |
---|
getAccessibleContext, getUI, getUIClassID, paramString, setUI, updateUI |
Methods inherited from class java.lang.Object |
---|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait |
Field Detail |
---|
private static final long serialVersionUID
private final LinePanel.Axis axis
private transient GroupLayout groupLayout
private transient GroupLayout.Group groupParallel
private transient GroupLayout.Group groupSequential
Constructor Detail |
---|
public LinePanel(LinePanel.Axis axis, boolean isDoubleBuffered) throws IllegalArgumentException, IllegalStateException
LinePanel.Axis
and buffering strategy.
axis
- specifes the direction that components will be laid out alongisDoubleBuffered
- a boolean, true for double-buffering, which uses additional memory space to achieve fast, flicker-free updates
IllegalArgumentException
- if axis is null or is not a recognized value
IllegalStateException
- if calling thread is not EventQueue
's dispatch thread
Method Detail |
---|
public static LinePanel makeHorizontal() throws IllegalStateException
GroupLayout
layout manager and a double buffer.
IllegalStateException
- if calling thread is not EventQueue
's dispatch thread
public static LinePanel makeVertical() throws IllegalStateException
GroupLayout
layout manager and a double buffer.
IllegalStateException
- if calling thread is not EventQueue
's dispatch thread
private void initLayout() throws IllegalArgumentException
IllegalArgumentException
private void readObject(ObjectInputStream ois) throws IllegalStateException, ClassNotFoundException, IOException, NotActiveException
Background: the sole issue is that Sun screwed up and failed to make GroupLayout
implement Serializable
.
This class's GroupLayout-related fields are all transient, so no problem here.
Unfortunately, our superlass, JPanel, retains a reference to the layout manager and we have no control over its serialization.
The solution is that we use a GroupLayout2
for groupLayout
, since it is serializable in some sense.
Well, GroupLayout2 does not actually write or read any data during serialization, but at least it does not throw any Exceptions.
This enables serialization of this class to proceed without modification (which is why there is no implementation of writeObject).
To deserialize here, this method first calls ObjectInputStream.defaultReadObject()
,
which restores all of this class's non-transient state as well as its superclass's (including all the components that were added).
Then, since it has its axis
field available, it only need call initLayout
to recreate the GroupLayout-related fields.
IllegalStateException
- if calling thread is not EventQueue
's dispatch thread
ClassNotFoundException
- if the class of a serialized object could not be found
IOException
- if an I/O problem occurs
NotActiveException
protected void addImpl(Component comp, Object constraints, int index)
addImpl
in class Container
public void setLayout(LayoutManager mgr) throws IllegalStateException
setLayout
in class Container
IllegalStateException
- if construction has finished ()
|
||||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |