The JCombobox's "content" window has this blue highlight that i don't know how to get rid of, please help.
Here is an example of the problem:
package example;
import java.awt.CardLayout;
import java.awt.Color;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Example {
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(1);
frame.setSize(500, 500);
frame.setLayout(new CardLayout());
frame.setVisible(true);
JPanel panel=new JPanel();
panel.setLayout(null);
frame.add(panel);
String[] model = {"pres.", "PPS.", "P. inp.", "P. mais q."};
JComboBox combox;
combox = new JComboBox(model);
combox.setBounds(100, 100, 145, 30);
combox.setBackground(new Color(215, 211, 165));
combox.setFocusable(false);
panel.add(combox);
panel.updateUI();
}
}
The combo box is a complex components that uses multiple components internally. The UI determines how the components interact with one another.
For example change your code to the following:
JComboBox combox;
combox = new JComboBox(model);
combox.setBorder( new LineBorder(Color.YELLOW) );
BasicComboBoxRenderer renderer = new BasicComboBoxRenderer();
renderer.setBorder( new LineBorder(Color.RED) );
combox.setRenderer(renderer);
And you will notice that the blue highlight is not a border of the combo box or its render, implying there is another internal container we don't have access to.
If you really want to solve the problem then you will need to customize the MetalComboBoxUI class, which is never an easy task because many of the painting methods will be private. But take a look at the code of the class to see if it can be done.
Other issues with your code:
Don't use updateUI(). The method is invoked internally in Swing when the LAF is changed. You are not changing the LAF
Components should be added to the frame BEFORE the frame is visible. This will eliminate the need for the updateUI().
How do I make a JLabel text vertically and horizontally aligned to the center?
I have to make use of setHorizontalTextPosition and setVerticalTextPosition. Can this be achieved by using these 2?
I have tried but the text remains at the top itself.
import java.awt.FlowLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingConstants;
public class label extends JFrame
{
private JLabel label;
public label() //constructor
{
super("Simple GUI");
setLayout(new FlowLayout());
label=new JLabel("Centered JLabel");
label.setHorizontalTextPosition(SwingConstants.CENTER);
label.setVerticalTextPosition(SwingConstants.CENTER);
add(label);
}
}
I have tried but the text remains at the top itself.
You have two problems:
Andrew addressed the first problem. You are using the wrong method.
Next you are using the wrong layout. The FlowLayout only display components on a single line so the component will always be at the top. Don't change the layout manager. The default layout manager for a JFrame is the BorderLayout. When you add a component to the CENTER (which is the default when you don't specify a constraint), the component will be sized to fill the entire frame. Then the "alignment" properties will control the position of the text within the size allocated to the label.
Or a different option is to use a GridBagLayout. Then you don't need to play with alignment options of the component:
setLayout( new GridBagLayout() );
add(label, new GridBagConstraints());
Try both options as both may be effective in different situations.
Read the Swing tutorial on Layout Managers to better understand how each layout manager works.
I'm very sorry to don't know why the setHorizontalTextPosition method and the setVerticalTextPosition method doesn't work.
But, I'll let you know that there're several ways to sort the text in the label by inserting parameters an alignment with String when we create the label.
First of all, camickr's answer is the best answer, Because Swing was designed to be used with layout managers!!
Please remember that the most recommended method is to apply GridBagLayout() to the Layout of JFrame by camickr.
This answer is intended to inform you that
This method is also possible, but not recommended in the normal case
Using this method is not recommended because changing the size of the frame
keeps the components in place, but it could give you a little help
when it is indicated that the size and location of components in the
container are used in a way that can be used in special cases, such as
when they need to be fixed without external impact.
To get a better idea of the problem, I'll simply change the code that you uploaded to me so that it can be executed.
import java.awt.FlowLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingConstants;
import java.awt.Color;
public class StackOver extends JFrame
{
private JLabel label;
public StackOver() //constructor
{
super("Simple GUI");
setLayout(null);
setSize(500,300);
label=new JLabel("Centered JLabel", JLabel.CENTER);
/*
label.setHorizontalTextPosition(SwingConstants.CENTER);
label.setVerticalTextPosition(SwingConstants.CENTER);*/
add(label);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
new StackOver();
}
}
Hmm, let's put some color in JLabel's background to find out more.
label.setOpaque(true); //Transparency Settings
label.setBackground(Color.pink); //Specify background color
//to use 'Color' class, We must import java.awt.Color;
the JFrame setting was set to FlowLayout()which makes the location and size of components were fixed, so we couldn't see it working!
So now we're going to go through the next two processes.
1) Changing JFrame's layout to null to use Absolute Layout ("not recommended, just a case")
2) Changing the size and location of the JLabel
after the progress we can see that the text alignment works!
1) Changing JFrame's Layout
the following link: Layout Manager shows that there are so many Layouts outside of FlowLayout.
Swing is designed to use the layout manager, so of course you should use one of the Layout above link.
But, to use an interesting way that fix the location and size of components absolutely We will switch to setLayout(null);!
2) Changing the size and location of the JLabel
We can directly change the size and position of JLabel with setBounds(int startX, int startY, int Width, int Height) method!
import java.awt.FlowLayout;
import java.awt.Rectangle;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingConstants;
import java.awt.Color;
public class StackOver extends JFrame
{
private JLabel label;
public StackOver() //constructor
{
super("Simple GUI");
setLayout(null);
setSize(500,300);
label=new JLabel("Centered JLabel", JLabel.CENTER);
// Since it also sets the size of the JLabel,
//let's use the constructor to set the alignment of the text inside the JLabel.
label.setOpaque(true); //Transparency Settings
label.setBackground(Color.pink); //Specify background color
//to use 'Color' class, We must import java.awt.Color;
Rectangle r = this.getBounds(); //to get Frame Size
label.setBounds(r.x+100, r.y+100, r.width-200, r.height-200);
/*
label.setHorizontalTextPosition(SwingConstants.CENTER);
label.setVerticalTextPosition(SwingConstants.CENTER);*/
add(label);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
new StackOver();
}
}
Now we can see the text of JLabel in the middle as intended!
This method can directly fix the size and location of all components (ex buttons), but the location and size of the components are fixed even if the window size of the JFrame changes after the program runs.
so If you really want set components Absolutely by this way, you rather to set JFrame Resizable false by adding below code on JFrame's code
this.setResizable(false);
I hope the answer was helpful to you and have a peaceful day!
I am using MigLayout for a very long window.
and I wish to "push" the second and fourth column to fill all the length of the whole window, but I cannot achieve it. There's no push option in column constraint, only grow and fill.
Here's a SCCEE, as someone once suggested, whose name I already forgot:
package com.WindThunderStudio.MigLayoutTest;
import java.awt.Cursor;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import net.miginfocom.swing.MigLayout;
public class MigLayoutTest extends JFrame{
private JFrame mainFrame;
private JPanel panel;
private JLabel lblResumenAuto;
private JLabel lblResumenAutoResult;
private JLabel lblResumenRazonSocial;
private JLabel lblResumenRazonSocialResult;
private JLabel lblResumenPeriodo;
private JLabel lblResumenPeriodoResult;
private JLabel lblResumenFechaHora;
private JLabel lblResumenFechaHoraResult;
public MigLayoutTest(){
run();
}
public void run(){
mainFrame = new JFrame();
mainFrame.setBounds(0, 0, 1250, 500);
mainFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
JPanel p = new JPanel();
p.setSize(mainFrame.getSize());
p.setLayout(new MigLayout("fill","[max!, grow]","[50:20:30]10[100::]10[20::]10[50!]10[20!]"));
mainFrame.setContentPane(p);
panel = new JPanel();
panel.setLayout(new MigLayout("fillx", "[left, 15%]10[left, grow, 35%]10[left, 15%]10[left, grow, 35%]", "[center]10[center]"));
lblResumenAuto = new JLabel("MY LABEL 1111111111111");
lblResumenAutoResult = new JLabel("1111111111111111111111");
panel.add(lblResumenAuto);
panel.add(lblResumenAutoResult);
lblResumenRazonSocial = new JLabel("MY LABEL 2222222222");
lblResumenRazonSocialResult = new JLabel("2222222222222222222222");
panel.add(lblResumenRazonSocial);
panel.add(lblResumenRazonSocialResult,"wrap");
lblResumenPeriodo = new JLabel("MY LABEL 33333333333333");
lblResumenPeriodoResult = new JLabel("3333333333333333333333333333333333333333333333333333333");
panel.add(lblResumenPeriodo);
panel.add(lblResumenPeriodoResult);
//poner el texto como html puede tener otra linea, porque es muy largo
lblResumenFechaHora = new JLabel("<html>MY LABEL <br /> 4444444444444444</html>");
lblResumenFechaHoraResult = new JLabel("4444444444444444444444444");
panel.add(lblResumenFechaHora);
panel.add(lblResumenFechaHoraResult);
p.add(panel,"cell 0 0");
getContentPane().setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
setBounds(0, 0, 1250, 500);
getContentPane().add(mainFrame.getContentPane());
pack();
setVisible(true);
setLocationRelativeTo(null);
setResizable(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
MigLayoutTest test = new MigLayoutTest();
}
});
}
}
If you run the code, you can note that the columns' width increases as its containing text's length changes. But it never fills the whole width of its container.
What's desirable, is to fix the column 0 and 2 by 15% of the whole width, and let column 1 and 3 to ocupy the rest, 35%, with the first two columns occupying the 50% size of the whole width.
Am I missing something here? I don't want to specify the width of every column, setting pre:min:max, because it is bad practice, as suggested by this post, which gets lots of vote up.
panel.setLayout(new MigLayout("fillx",
"[left, 15%]10[left, grow, 35%]10[left, 15%]10[left, grow, 35%]",
"[center]10[center]"));
But, if I set pref:min:max, it can fill the whole width.
First the code, then explanation. Try this:
import java.awt.Cursor;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import net.miginfocom.swing.MigLayout;
public class MigLayoutTest extends JFrame {
private JPanel panel;
private JLabel lblResumenAuto;
private JLabel lblResumenAutoResult;
private JLabel lblResumenRazonSocial;
private JLabel lblResumenRazonSocialResult;
private JLabel lblResumenPeriodo;
private JLabel lblResumenPeriodoResult;
private JLabel lblResumenFechaHora;
private JLabel lblResumenFechaHoraResult;
public MigLayoutTest() {
run();
}
public void run() {
panel = new JPanel();
panel.setLayout(new MigLayout("debug, fill",
"[left, 15%]10[left, 35%]10[left, 15%]10[left, 35%]", "[center]10[center]"));
lblResumenAuto = new JLabel("MY LABEL 1111111111111");
lblResumenAutoResult = new JLabel("1111111111111111111111");
panel.add(lblResumenAuto, "sg label");
panel.add(lblResumenAutoResult, "sg value");
lblResumenRazonSocial = new JLabel("MY LABEL 2222222222");
lblResumenRazonSocialResult = new JLabel("2222222222222222222222");
panel.add(lblResumenRazonSocial, "sg label");
panel.add(lblResumenRazonSocialResult, "sg value, wrap");
lblResumenPeriodo = new JLabel("MY LABEL 33333333333333");
lblResumenPeriodoResult = new JLabel("3333333333333333333333333333333333333333333333333333333");
panel.add(lblResumenPeriodo, "sg label");
panel.add(lblResumenPeriodoResult, "sg value");
// poner el texto como html puede tener otra linea, porque es muy largo
lblResumenFechaHora = new JLabel("<html>MY LABEL <br /> 4444444444444444</html>");
lblResumenFechaHoraResult = new JLabel("4444444444444444444444444");
panel.add(lblResumenFechaHora, "sg label");
panel.add(lblResumenFechaHoraResult, "sg value");
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
getContentPane().setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
getContentPane().add(panel);
pack();
setVisible(true);
setLocationRelativeTo(null);
setResizable(true);
}
public static void main(String[] args) {
MigLayoutTest test = new MigLayoutTest();
}
}
The explanation of my changes:
Now except for simplifying the code and layout I used “debug” within the layout constraints to see what actually happens to the layout. I suggest using it anytime things go wrong with the layout - it makes MigLayout draw the borders of components and cells, thus visualizing potential problems.
I removed the unnecessary mainframe and p - if you really need it for a nested layout try to add it once you have solved the inner layout to your liking.
As to p and panel - it might be that you need here two different layouts, one nested in another, but this is the actual source of your problem. p had also its own grid layout, with
p.add(panel,"cell 0 0");
you put panel in the top left cell of the p - this is why panel was not distributed over the whole window but sat in the upper left corner.
As you see without p it positions nicely in the middle of the screen without any constant size, still showing all components, but more importantly it has 50% of the window size for the first and 50% for the last two columns. This was achieved by giving the components a “sizegroup”:
Gives the component a size group name. All components that share a
size group name will get the same BoundSize (min/preferred/max). It is
used to make sure that all components in the same size group gets the
same min/preferred/max size which is that of the largest component in
the group. An empty name "" can be used.
And it also resizes like it should!
The nested layout might also had been the root of another problem – don’t know if you didn’t notice it or it just didn’t show up on your machine, but if I tried to resize your window the panel got wider and wider (never narrower) even if I shrunk the window. At some point it got wider than the window itself and even then growed further on each resize.
Next - setting the dimensions to a constant value didn’t make sense, since after pack the layout manager starts sizing everything based on preferred sizes of the window and its content. Besides, you never know which size is your users’ screen, so any constant size could be equally bad if effectively used. Better to drive the size through the content and available runtime environment. With your code on my machine it took all available horizontal space of my two screens (2 x 1280) and did’t look pretty.
I also think that you do not need to start the frame using EventQueue.invokeLater, just create a MigLayoutTest and that’s it.
EDIT after OP's own answer
Setting the size using setBounds(0, 0, 1250, 500) before pack is not working correctly (by this I mean making the window be that size). Even in the screenshot below OP's own answer it is not 500px high. Here is what I get on Windows 7 running JDK 1.8.0_91:
The size of my screen is 1280 x 1024, the size of the programm's window is 914 x 301.
I'd suggest using one of the following:
To set it to the constant size of 1250 x 500 px move the setSize between pack and setVisible:
...
pack();
setSize(1250, 500);
I'd use setSize, setBounds doesn't make sense, since by calling setLocationRelativeTo(null) you centering the programm's window on the screen anyway, so the origin is being dismissed immediately.
To maximize horizontally and let the height be 500 px set main window's preferred size before pack:
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
setPreferredSize(new Dimension(screenSize.width, 500));
And to maximize horizontally and let the preferred height as it was originally:
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
setPreferredSize(new Dimension(screenSize.width, getPreferredSize().height));
Of course you can make the window 1250 x 500 big by setting its preferred size instead of using setSize, too.
The resize problem is not so big now, but it's still there - make the window wider, than narrow it just a little bit. You'll notice that the panel gets wider even if the window got narrowed. The problem is that panel component doesn't get big enough to fill the one column of p initially (BTW you can add the 'debug' flag to each MigLayout, also that of the panel - it will then outline all of the inner components as well).
To make it fill the parent container add it like this:
p.add(panel, "cell 0 0, grow");
Now it is the full width of p from the very beginning and resizing works as expected.
Regarding starting the JFrame using invokeLater - we start our main windows usually without it and had never had problems, since there were no interactions with Swing until the first frame was visible, yet I have just noticed that it is regarded to be the best practise - even in Oracle's tutorials. It looks like I had learned something here, too :-).
Comparision of the frame's window with and without adding with "grow"
Test scenario: start the application and resize it to be wider.
As you see in the first screenshot the component size is smaller than the column width - it looks like the component were lying behind the column size while resizing. On the second screenshot the component width remains the same as the column width at all times. As I said previously the reason might be the Java and/or operating system combination, I don't know. But obviously it behaves differently and on my machine less than optimal.
Thanks to #Tomasz Stanczak, I have solved it finally. However, I found part of what he said is relevant, and others are not. For future readers who may see this, I have to made it clearer.
The final working code is:
import java.awt.Cursor;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import net.miginfocom.swing.MigLayout;
public class MigLayoutMySCCEE extends JFrame{
private JFrame mainFrame;
private JPanel panel;
private JLabel lblResumenAuto;
private JLabel lblResumenAutoResult;
private JLabel lblResumenRazonSocial;
private JLabel lblResumenRazonSocialResult;
private JLabel lblResumenPeriodo;
private JLabel lblResumenPeriodoResult;
private JLabel lblResumenFechaHora;
private JLabel lblResumenFechaHoraResult;
public MigLayoutMySCCEE(){
run();
}
public void run(){
JPanel p = new JPanel();
p.setLayout(new MigLayout("debug, fill","[grow]","[50:20:30]10[100::]10[20::]10[50!]10[20!]"));
panel = new JPanel();
panel.setLayout(new MigLayout("fillx", "[left, 15%]10[left, grow, 35%]10[left, 15%]10[left, grow, 35%]", "[center]10[center]"));
lblResumenAuto = new JLabel("MY LABEL 1111111111111");
lblResumenAutoResult = new JLabel("1111111111111111111111");
panel.add(lblResumenAuto);
panel.add(lblResumenAutoResult);
lblResumenRazonSocial = new JLabel("MY LABEL 2222222222");
lblResumenRazonSocialResult = new JLabel("2222222222222222222222");
panel.add(lblResumenRazonSocial);
panel.add(lblResumenRazonSocialResult,"wrap");
lblResumenPeriodo = new JLabel("MY LABEL 33333333333333");
lblResumenPeriodoResult = new JLabel("3333333333333333333333333333333333333333333333333333333");
panel.add(lblResumenPeriodo);
panel.add(lblResumenPeriodoResult);
//poner el texto como html puede tener otra linea, porque es muy largo
lblResumenFechaHora = new JLabel("<html>MY LABEL <br /> 4444444444444444</html>");
lblResumenFechaHoraResult = new JLabel("4444444444444444444444444");
panel.add(lblResumenFechaHora);
panel.add(lblResumenFechaHoraResult);
p.add(panel,"cell 0 0");
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
getContentPane().setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
setBounds(0, 0, 1250, 500);
getContentPane().add(p);
pack();
setVisible(true);
setLocationRelativeTo(null);
setResizable(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
MigLayoutMySCCEE test = new MigLayoutMySCCEE();
}
});
}
}
And the window looks like:
Some notes:
The debug trick is very useful and urges me to read DOC again. I wish it can gain more attention and importance in the Quick Start page, however.
The unnecessary nesting is a problem and Tomasz make me to review the hierarchy, great! I changed the nesting part to make it clearer. But it's irrelevant.
The sizeGroup part is great idea and I decide to use it in future development as much as possible, but it's irrelevant to my case. I solved it without using it.
I have found the wider-and-wider problem after Tomasz's tip, but it is due to [max!] combined with adding the panel to the first cell of grid layout, not frame/panel nesting. I removed [max!] and changed it to [grow] and the width is not expanding anymore. I didn't touch the p.add(panel, "cell 0 0") part. As observed and by definition,
p.setLayout(new MigLayout("debug, fill","[grow]","[50:20:30]10[100::]10[20::]10[50!]10[20!]"));
the first line of the panel has only one column, if I understand well.
EDIT after Tomasz's edit
I surely have learned more than you did :) I tried to get rid of setBounds() part and to change add(panel, "cell 0 0") to add(panel, "grow"), but I cannot see much difference, am I missing something here? Yet "grow" is almost always the better choice and desirable.
Here's 2 GIFs showing what I got: (by ScreenToGif, a light-weighted but powerful tool, especially useful for showcase)
I would like to have in my app text fields that span multiple rows. It seems to be no problem to get the desired result in Eclipse design viewer using GridBagLayout:
However, when I export it to jar, I see the window like this:
My code:
import java.awt.Color;
import java.awt.Container;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JFrame;
import javax.swing.JTextField;
#SuppressWarnings("serial")
public class TestFrame extends JFrame {
GridBagConstraints constraints;
JTextField text0;
public TestFrame() {
super("Test window");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
Container container = getContentPane();
container.setLayout(new GridBagLayout());
container.setBackground(new Color(240,240,240));
JTextField editableTextField;
editableTextField = new JTextField("Enter text here");
constraints = new GridBagConstraints();
constraints.fill=GridBagConstraints.BOTH;
constraints.gridheight=2;
constraints.gridx=0;
constraints.gridy=0;
container.add(editableTextField, constraints);
pack();
}
public static void main(String args[]) {
new TestFrame();
}
}
I am using Eclipse 4.4.1 under MacOS 10.9.3.
Can anyone explain me, where the difference in view comes from and how can I get the proper text field height in jar?
how can I get the proper text field height in
You don't do anything. The Swing layout managers will determine the proper height for the text field based on the font of the text field.
In your case you only have a single component added to the frame so you can't tell the text field to have a gridHeight of 2 because there is only one row. That constraint is used when you have multiple rows of components in the frame. Then you can specify that a component spans two rows.
If you want extra space around the text field than you can change the Border:
JTextField textField = new JTextField(30);
Border empty = new EmptyBorder(10, 10, 10, 10);
Border compound = new CompoundBorder(textField.getBorder(), empty);
textField.setBorder(compound);
Read the section from the Swing tutorial on How to Use Borders for more information and examples.
The tutorial also has a section on How to Use GridBagLayout you should check out for more information about GridBagConstraints.
here's an SSCCE:
import java.awt.Color;
import java.awt.Dimension;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class BoxLayoutTest extends JFrame {
public BoxLayoutTest(){
JPanel main = new JPanel();
main.setLayout(new BoxLayout(main, BoxLayout.Y_AXIS));
main.setBackground(Color.red);
this.add(main);
JPanel northPanel = new JPanel();
JPanel middle = new JPanel();
middle.setLayout(new BoxLayout(middle, BoxLayout.X_AXIS));
middle.add(new JButton("FOO"));
middle.add(Box.createHorizontalGlue());
JPanel aPanel = new JPanel();
aPanel.setBackground(Color.black);
JComboBox b = new JComboBox();
//b.setPreferredSize(new Dimension(100,16)); //uncomment this to see the layout I would like to achieve
//b.setMaximumSize(new Dimension(100,16));
//middle.add(b); //uncomment this line
middle.setBackground(Color.green);
northPanel.setBackground(Color.blue);
main.add(northPanel);
main.add(middle);
main.add(Box.createVerticalGlue());
this.setSize(800,600);
this.setResizable(true);
this.setVisible(true);
}
public static void main(String[] args) {
new BoxLayoutTest();
}
}
I'm trying to refactor some classes I wrote some time ago, when I didn't know that using setXXXSize methods on components is wrong.
Using a resizable frame ,the result I want to achieve is the following:
The northPanel should stay on top and change it's size accordingly to the frame size modifications (seems to work fine)
The green panel where I put the JButton should keep the maximum dimension of the JButton and stay just below the blue panel above (this works fine if I only put JButtons inside that panel).
The problem arise if I put a JComboBox inside the green panel (try to uncomment the line in the SSCCE). I guess JComboBox hasn't a maximum size specified, so it stretches with the frame. In the previous wrong version of my code I was using setxxxSize methods on the JComboBox to limit it's dimension(try to uncomment the line on setXXXSize methods to see it).
My question are:
Is it possible to achieve the same result using BoxLayout without invoking setXXXSize() methods?
If yes, how?
Is there any other LayoutManager that can I use to get that effect?
Please put me in the right direction
JComboBox is misbehaving (the same as JTextField) in reporting an unbounded max height: should never show more than a single line. Remedy is the same: subclass and return a reasonable height
JComboBox b = new JComboBox() {
/**
* #inherited <p>
*/
#Override
public Dimension getMaximumSize() {
Dimension max = super.getMaximumSize();
max.height = getPreferredSize().height;
return max;
}
};
just for fun, here's a snippet using MigLayout (which is my personal favorite currently :-)
// two panels as placeholders
JPanel northPanel = new JPanel();
northPanel.setBackground(Color.YELLOW);
JPanel southPanel = new JPanel();
southPanel.setBackground(Color.YELLOW);
// layout with two content columns
LC layoutContraints = new LC().wrapAfter(2)
.debug(1000);
AC columnContraints = new AC()
// first column pref, followed by greedy gap
.size("pref").gap("push")
// second
.size("pref");
// three rows, top/bottom growing, middle pref
AC rowContraints = new AC()
.grow().gap().size("pref").gap().grow();
MigLayout layout = new MigLayout(layoutContraints, columnContraints,
rowContraints);
JPanel main = new JPanel(layout);
main.setBackground(Color.WHITE);
// add top spanning columns and growing
main.add(northPanel, "spanx, grow");
main.add(new JButton("FOO"));
// well-behaved combo: max height == pref height
JComboBox combo = new JComboBox() {
#Override
public Dimension getMaximumSize() {
Dimension max = super.getMaximumSize();
max.height = getPreferredSize().height;
return max;
}
};
// set a prototype to keep it from constantly adjusting
combo.setPrototypeDisplayValue("somethingaslongasIwant");
main.add(combo);
// add top spanning columns and growing
main.add(southPanel, "spanx, grow");
I have always seen using the layout managers in the jdk are not easy. They are either too simple and inflexible or the gridbaglayout is just too much trouble. Instead I started using the jgoodies form layout and never looked back since.. Have a look at it. Its very simple and easy to use. Here's a link:
http://www.jgoodies.com/freeware/forms/
Make sure you go through the white paper.
And now, we also have google providing us a WYSISWG editor for the formlayout as a plugin for eclipse. This just makes life a lot lot easier.
http://code.google.com/javadevtools/wbpro/palettes/swing_palette.html