New to Java Swing layouts. After much reading, I think that the best layout for me is the box layout. My JDialogBox has a JTabbedPane on it. On the JTabbedPane, there are four JPanels. I am focusing on laying out one of these panels, called pnlDivision.
What I want to do to this panel is to add a series of scrollable panels. The panels will be vertically stacked upon each other and each will consist of a single row. Included in each panel will be horizontally aligned labels, any of which can be selected for editing by the user.
At the moment, I can't even get anything to appear on my tabbed panel. Focusing on the basics first, I have the following code just to get the idea of a box layout set up, with a single scrollable panel containing and a single label. But my tabbed panel is still blank. Can anyone see what is wrong with this basic code? I've read many resources on this, but I can't get unstuck.
Thanks very much !
JScrollPane myScroller = new JScrollPane();
myScroller.setPreferredSize(new Dimension(250, 80));
myScroller.setAlignmentX(LEFT_ALIGNMENT);
JPanel myPane = new JPanel();
myPane.setLayout(new BoxLayout(myPane, BoxLayout.PAGE_AXIS));
JLabel lbl = new JLabel("label 1");
myPane.add(lbl);
myPane.add(Box.createRigidArea(new Dimension(0,4)));
myPane.add(myScroller);
myPane.setBorder(BorderFactory.createEmptyBorder(10,10,10,10));
pnlDivision.add(myPane);
EDIT:
This is the code where I set up the tabbed panel. I used the IDE (NetBeans), so this is generated by NetBeans. I've only pulled out the lines that relate to this issue. If I'm obviously missing any lines, please let me know:
jTabbedPane1 = new javax.swing.JTabbedPane();
pnlDivision = new javax.swing.JPanel();
jTabbedPane1.addTab("division", null, pnlDivision, "Manage Sets for Division Problems");
getContentPane().add(jTabbedPane1);
jTabbedPane1.setBounds(70, 110, 610, 340);
Related
In my code I have a JFrame that opens up a main menu, in that menu you can click options, which will take you to the options menu. On that options menu I want to create a back button that will position itself somewhere in the top left corner of the screen. When I run the program and go to the options menu the JButton does not appear. Something must be wrong with my code. Any help? Below is where I first declare the JButton.
static JButton optionsBackButton = new JButton("<html><font size = 5
color = green>Back</font></html>");
Here is the other part of the code that has to do with the JButton.
//Options Menu
JPanel optionsPanel = new JPanel();
JLabel optionsOptionsTitle = new JLabel("<html><font size = 7 color = blue>Options</font></html>");
JPanel optionsOptionsTitlePanel = new JPanel();
JPanel optionsBackButtonPanel = new JPanel();
optionsPanel.setLayout(null);
optionsBackButton.setBounds(100,100,50,50);
optionsBackButtonPanel.add(optionsBackButton);
optionsOptionsTitlePanel.add(optionsOptionsTitle);
optionsPanel.add(optionsOptionsTitlePanel);
optionsPanel.add(optionsBackButtonPanel);
optionsBackButton.addActionListener(this);
//Add panels to the card
panel.add("Home Screen", homePanel);
panel.add("Options Menu", optionsPanel);
//card.add("Game screen", gamePanel);
cardLayout.show(panel, "HomeScreen");
contentPane.add(panel);
Your problem is stemming from your use of null layouts. Note:
JPanel optionsBackButtonPanel = new JPanel(); // holds the back button
// but never given a size
optionsPanel.setLayout(null); // uh oh,.... bad news
optionsBackButton.setBounds(100,100,50,50); // yes you set the bounds of the button
optionsBackButtonPanel.add(optionsBackButton);
optionsOptionsTitlePanel.add(optionsOptionsTitle);
optionsPanel.add(optionsOptionsTitlePanel);
optionsPanel.add(optionsBackButtonPanel); // again, optionsBackButtonPanel
// has been never given a size or location/bounds
optionsBackButton.addActionListener(this);
So you set the bounds of the button and add it to a JPanel that uses the default FlowLayout, and so the bounds are meaningless. Then you add that JPanel, whose bounds you never set, to a JPanel that uses null layout. So the optionsBackButtonPanel will never show.
Solution: Don't use null layouts, but instead learn and use the layout managers.
While null layouts and setBounds() might seem to Swing newbies like the easiest and best way to create complex GUI's, the more Swing GUI'S you create the more serious difficulties you will run into when using them. They won't resize your components when the GUI resizes, they are a royal witch to enhance or maintain, they fail completely when placed in scrollpanes, they look gawd-awful when viewed on all platforms or screen resolutions that are different from the original one.
Start here: Laying Out Components in a Container Tutorial
I am attempting to create panel, PluginListPanel (extending JPanel), which will show a list of plugin panels which will respect the preferred height of the plugin's panel, but will force the width. I have a solution, but it is slow and has a weird bug. In the screenshot, there are two such panels, one to the left and one to the right:
I don't know different layout manager systems very well, but I know that the TOP field in the BorderLayout does what I want. So, I came up with this 'recursive' solution:
public PluginListPanel(List<PanelContainer> items) {
JPanel body = this;
for (PanelContainer item : items) {
body.setLayout(new BorderLayout(0, 0));
JPanel panel = new PluginOnePanel(item);
body.add(panel, BorderLayout.NORTH);
JPanel newBody = new JPanel();
body.add(newBody, BorderLayout.CENTER);
body = newBody;
}
}
The problem I encounter is when I scroll, the system responds somewhat slowly, and the colour of the SamplePluginPanels is different (see picture below), even if the number of SamplePluginPanels is as low as 8.
The question is, how can I make this more elegant, not slow down the program and not miscolour the panels?
Any insights are highly appreciated.
I think a vertical Box is the answer (actually 2, on both columns):
Box leftBox = Box.createVerticalBox();
Box rightBox = Box.createVerticalBox();
/* put them together */
setLayout(new GridLayout(2,1));
add(leftBox);
add(rightBox);
Also make sure, that the content of the scroll pane implements Scrollable and returns true, to scrollableTracksViewportWidth(). This will force equal widths.
I'm trying to create a JDialog like the Symbol dialog in Microsoft Word that you get by choosing Symbol... from the Insert menu. Basically, it's an n x m (n and m are not known until runtime) grid of small buttons. I've got a first version of this working nicely using a GridLayout. The problem is that when you resize the dialog (and there is a requirement that you should be able to resize it), the size of the buttons changes. I need the size of the buttons to remain constant.
But I want the dimensions of the grid containing the buttons to change. For example, if the dialog gets wider, but stays the same height, the number of rows should lessen, while the number of columns increases.
I've thought of a couple of ways to fix this:
When the dialog is resized, create a new GridLayout and repopulate it with the buttons. I'm going to try this and see how it looks, but it seems like a clumsy way of doing it.
Use some other type of layout such as a FlowLayout. I took a stab at this, but it put all n x m buttons in one row. I do not want to use horizontal scroll-bars and the buttons ran off the right edge. Anyway, it's supposed to be a 2-dimensional grid of buttons.
What is the best way to solve this layout problem?
Create a buttons panel with GridLayout and set a fixed size (could be calculated at runtime of course) to it. The buttons panel should be contained in a panel of BoxLayout.
Check out the BoxLayout Tutorial
Very Very basic example:
public static void main(String[] args) throws Exception
{
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel buttonPanel = new JPanel();
JPanel containerPanel = new JPanel();
buttonPanel.setLayout(new GridLayout(2,2));
buttonPanel.add(new JButton("1"));
buttonPanel.add(new JButton("2"));
buttonPanel.add(new JButton("3"));
buttonPanel.add(new JButton("4"));
buttonPanel.setPreferredSize(new Dimension(300, 400));
containerPanel.add(buttonPanel);
frame.getContentPane().add(containerPanel);
frame.pack();
frame.setVisible(true);
}
if the dialog gets wider, but stays the same height, the number of rows should lessen, while the number of columns increases.
Wrap Layout might be what you are looking for.
I had a similar issue with a single column of buttons, and found that MiGLayout (third-party, available here) was simple and effective for this. It helped both with making a grid and with setting button sizes, although it took me a day or two to get used to its syntax.
But the key is really setting button sizes; GridLayout certainly seems like the way to go for a layout that is, well, a grid. I haven't tested, but I suspect that the built-in setXSize() methods would work just as well. The GridBagLayout tutorial has examples of some things you can do with sizing/positioning.
FlowLayout would be the way to go but you might have some configuration problems. What layout manager does the parent component use?
I have a text field to represent a name, and a combobox for registration type. Then, next to that I have a check box, but it's supposed to be underneath the other two fields. Here is what I have coded:
public RegPanel()
{
//create a new panel
new GridLayout(2,1);
//create one of two subpanels
subPanel = new JPanel(new FlowLayout());
//create a textfield
regTextField = new JTextField(20);
//create a combobox and don't let anyone add to it
regComboBox = new JComboBox(regOptions);
//create a border for the subpanel
subPanel.setBorder(BorderFactory.createTitledBorder("Registrant's Name & Type"));
//add regTypePanel and regBox to the panel
subPanel.add(regTextField);
subPanel.add(regComboBox);
//create a second subpanel with a flowlayout
subPanel2 = new JPanel(new FlowLayout());
//create a checkbox
regCheckBox = new JCheckBox("Dinner and Keynote Speech");
subPanel2.add(regCheckBox);
//add the subpanels to the main panel
add(subPanel);
add(subPanel2);
}
Any ideas what I am missing? Sorry for the crappy layout, I can't figure out how to fix the view.
So I realized I hadn't set the GridLayout right, so I changed that to "setLayout(new GridLayout(2,1));
But now on my gui, it totally screwed up the position of all the other elements.
Anyway new GridLayout(...) do nothing unless you use it in setLayout(...).
You can try using Box.createVerticalBox() (sample) instead of GridLayout to have your components in vertical alignment.
In your case, you are using
RegPanel (which layout?)
subPanel (FlowLayout)
regTextField
regComboBox
subPanel2 (FlowLayout)
regCheckBox
Which layout does your main RegPanel have? It has the default JPanel layout (if RegPanel is a subclass of JPanel), which is a FlowLayout. So, your RegPanel shows the two subPanels besides each other, which looks similar as if you had only one Panel with all the components. So, your RegPanel needs a LayoutManager, too - the GridLayout(2,1) seems okay (if you don't want to align the components in the two lines).
In my current project, I'm only ever using GroupLayout (apart from one occasional BorderLayout). It takes a bit to get used to (and a wrapper class to make the code easier to write and read), but for such form stuff, it seems ideal (when limited to the build-in Layout managers).
Also you might want to use a BorderLayout and realize that you nest one layout in another layout to achieve a different effect.
Have to mention MigLayout here as a great all-purpose layout manager -- it is extremely flexible and easy to use once you get to know it.
JPanel pMeasure = new JPanel();
....
JLabel economy = new JLabel("Economy");
JLabel regularity = new JLabel("Regularity");
pMeasure.add(economy);
pMeasure.add(regularity);
...
When I run the code above I get this output:
Economy Regularity
How can I get this output, where each JLabel starts on a new line? Thanks
Economy
Regularity
You'll want to play around with layout managers to control the positioning and sizing of the controls in your JPanel. Layout managers are responsible for placing controls, determining where they go, how big they are, how much space is between them, what happens when you resize the window, etc.
There are oodles of different layout managers each of which allows you to layout controls in different ways. The default layout manager is FlowLayout, which as you've seen simply places components next to each other left to right. That's the simplest. Some other common layout managers are:
GridLayout - arranges components in a rectangular grid with equal-size rows and columns
BorderLayout - has one main component in the center and up to four surrounding components above, below, to the left, and to the right.
GridBagLayout - the Big Bertha of all the built-in layout managers, it is the most flexible but also the most complicated to use.
You could, for example, use a BoxLayout to layout the labels.
BoxLayout either stacks its components on top of each other or places them in a row — your choice. You might think of it as a version of FlowLayout, but with greater functionality. Here is a picture of an application that demonstrates using BoxLayout to display a centered column of components:
An example of code using BoxLayout would be:
JPanel pMeasure = new JPanel();
....
JLabel economy = new JLabel("Economy");
JLabel regularity = new JLabel("Regularity");
pMeasure.setLayout(new BoxLayout(pMeasure, BoxLayout.Y_AXIS));
pMeasure.add(economy);
pMeasure.add(regularity);
...
I read this piece of code:
pMeasure.setLayout(new BoxLayout(pMeasure, BoxLayout.VERTICAL));
It seems BoxLayout doesn't have VERTICAL. Upon searching, this will work using the following code:
pMeasure.setLayout(new BoxLayout(pMeasure, BoxLayout.Y_AXIS));
Here is what you need to use:
JLabel economy = new JLabel("<html>Economy<br>Regularity</html>");
A quick way is to use html within the JLabel.
For instance include the <br/> tag.
Otherwise, implement a BoxLayout.
Make a separate JPanel for each line, and set the dimensions to fit each word:
JLabel wordlabel = new JLabel("Word");
JPanel word1 = new JPanel();
word1.setPreferredSize(new Dimension(#,#);
This should work for each word. You can then add each of those JPanels to your main JPanel. This also allows you to add other components next to each word.