Reputation: 33
I'm writing a GUI in Java using Swing. At the moment, I'm trying to create a "Module" (a yellow block) that has a widget holder (black bar) on the left and right edges. Each holder will hold several small blocks that I'd like to display in a vertical line. Here is a picture:
Example module :
I want to be able to space the magenta/cyan blocks evenly along the widget holders.
I've looked at several tutorials for Swing and have tried implementing the layout of the widget holders as GridLayout and BoxLayout, but both without luck. A single column GridLayout seems to be the natural choice here, but I can't seem to make it work, even though I've written small test programs that properly use a grid.
The fact that the layout managers work in simple examples but not in this slightly more complex program has left me perplexed.
In my program,
On a side note, I was also having trouble with the layout of the Module itself to position the widget holders on the left and right. I tried using a horizontal BoxLayout (holder, horizontal glue, holder), and another time I tried using a BorderLayout (using EAST/WEST for either holder), but no matter what I did the holders would not budge - so as much as I didn't want to, I used setBounds() to position them.
Module Class (widget holders are inputLine and outputLine):
public class Module extends JPanel
{
private static final int MOD_WIDTH = 86;
private static final int MOD_HEIGHT = 60;
private int screenX, screenY, myX, myY;
private boolean moving = false;
// figure out the layout !
private JPanel inputLine, outputLine;
public Module()
{
//super(new BorderLayout());
initPanel();
initWidgets();
initMouse();
setLayout(null);
list();
}
private final void initPanel()
{
this.setSize(new Dimension(MOD_WIDTH, MOD_HEIGHT));
this.setBackground(Color.ORANGE);
}
private void initWidgets()
{
inputLine = new JPanel(new GridLayout(0, 1, 5, 5));
outputLine = new JPanel(new GridLayout(0, 1, 5, 5));
inputLine.setBounds (0, 0, 18, 60);
outputLine.setBounds(68, 0, 18, 60);
this.add(inputLine);
this.add(outputLine);
/* adding IOWidgets to test */
inputLine.add(new InputWidget());
inputLine.add(new InputWidget());
inputLine.add(new InputWidget());
outputLine.add(new OutputWidget());
outputLine.add(new OutputWidget());
outputLine.add(new OutputWidget());
outputLine.add(new OutputWidget());
inputLine.setBackground(Color.BLACK);
outputLine.setBackground(Color.BLACK);
}
Here is the abstract IOWidget class that both type of widgets (input[magenta], output[cyan]) derive from. It will have added functionality later.
public abstract class IOWidget extends JLabel
{
private static final int EDGE_SIZE = 8;
public IOWidget()
{
this.setSize(new Dimension(EDGE_SIZE, EDGE_SIZE));
}
}
Here is the InputWidget class. At the moment, it's identical to OutputWidget until I add the extra functionality, so I'll only post this one :
public class InputWidget extends IOWidget
{
public InputWidget()
{
this.setBackground(Color.MAGENTA);
}
}
In my application, modules are added to a larger JPanel. I would hope that the layout of the module is independent of how it's added to another JComponent, so I will omit the rest of the code.
Here is what the program looks like when run :
For completeness, here's the output of calling list on a single module :
rhopkins.honors.Dataflow.Module[,0,0,86x60,invalid,alignmentX=0.0,alignmentY=0.0,border=,flags=9,maximumSize=,minimumSize=,preferredSize=]
javax.swing.JPanel[,0,0,18x60,invalid,layout=java.awt.GridLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=9,maximumSize=,minimumSize=,preferredSize=]
rhopkins.honors.Dataflow.InputWidget[,0,0,8x8,invalid,layout=java.awt.FlowLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=9,maximumSize=,minimumSize=,preferredSize=java.awt.Dimension[width=8,height=8]]
rhopkins.honors.Dataflow.InputWidget[,0,0,8x8,invalid,layout=java.awt.FlowLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=9,maximumSize=,minimumSize=,preferredSize=java.awt.Dimension[width=8,height=8]]
rhopkins.honors.Dataflow.InputWidget[,0,0,8x8,invalid,layout=java.awt.FlowLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=9,maximumSize=,minimumSize=,preferredSize=java.awt.Dimension[width=8,height=8]]
javax.swing.JPanel[,68,0,18x60,invalid,layout=java.awt.GridLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=9,maximumSize=,minimumSize=,preferredSize=]
rhopkins.honors.Dataflow.OutputWidget[,0,0,8x8,invalid,layout=java.awt.FlowLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=9,maximumSize=,minimumSize=,preferredSize=java.awt.Dimension[width=8,height=8]]
rhopkins.honors.Dataflow.OutputWidget[,0,0,8x8,invalid,layout=java.awt.FlowLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=9,maximumSize=,minimumSize=,preferredSize=java.awt.Dimension[width=8,height=8]]
rhopkins.honors.Dataflow.OutputWidget[,0,0,8x8,invalid,layout=java.awt.FlowLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=9,maximumSize=,minimumSize=,preferredSize=java.awt.Dimension[width=8,height=8]]
rhopkins.honors.Dataflow.OutputWidget[,0,0,8x8,invalid,layout=java.awt.FlowLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=9,maximumSize=,minimumSize=,preferredSize=java.awt.Dimension[width=8,height=8]]
I'd very much like to know what I'm doing wrong. Also, I'm aware I'm new to Swing and GUI development in general, so any criticism about style/conventions/anything is welcome.
Upvotes: 3
Views: 444
Reputation: 324118
Dont use a null layout.
Your main panel should probably be a BorderLayout. You can add your widget holders to the WEST and EAST of your main panel.
The widget panel should be able to use a vertical BoxLayout. You will need to add glue before/after every widget you add to the panel. Since the BoxLayout respects the sizes of the component, you will need to override the getPreferredSize(), getMinimumSize() and getMaximumSize() methods to all return the same value. This way any extra space in the panel should be divided equally among the glue that you add.
Upvotes: 4