I have a 4x4 gridlayout and I'm trying to add 2 title bars above the tables I've created. I'm creating panels for title bars but because of the gridlayout it fills up all the space. Here's the code:
private WebScrollPane createPosRiskPanelWindow(int w, int h)
{
//Content area
posRiskPanel = new WebPanel((new GridLayout(2,2)));
posRiskPanel.setBackground(Color.WHITE);
//Add title bars
WebPanel posTitle = new WebPanel(new WebLabel("Current Positions"));
posRiskPanel.add(posTitle);
WebPanel riskTitle = new WebPanel(new WebLabel("Risk Exposure"));
posRiskPanel.add(riskTitle);
//Panels
CreatePositionPanel(posRiskPanel);
CreateRiskParamsPanel(posRiskPanel);
//Scroll content
posRiskScroll = new WebScrollPane (posRiskPanel, false);
posRiskScroll.setPreferredSize (new Dimension (w, h));
return posRiskScroll;
}
And here's what it looks like:
Is there a way I can resize those top 2 boxes?
Don't use GridLayout for the overall layout, since the only thing it knows to do is to create cells that are all exactly the same size. Since you don't want this, your GUI will require a different layout. Instead use GridBagLayout or else you could use nested JPanels with differing layouts, but I think that GridBagLayout for the overall layout is likely your best bet here. Other considerations include MigLayout if you're willing to use a 3rd party library.
I found it easier to just put the tables in their own panel and a titled border like so:
Related
I have multiple JTextAreas inside a JPanel. I am using a BoxLayout to make them align vertically and fill the width of the container.
It works, but they seem to expand to fill the entire height as well.
What I really want is simple - a text area that wraps text where I can control the width but allow the height to scale dynamically as more lines are added. The above method was just my best attempt at it. If there is a solution that uses a different layout manager, different text component, etc, that works.
minimal verifiable example below:
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setPreferredSize(new Dimension(300, 300));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel textAreas = new JPanel();
textAreas.setLayout(new BoxLayout(textAreas, BoxLayout.Y_AXIS));
JTextArea area1 = new JTextArea();
area1.append("this is a string");
area1.setLineWrap(true);
area1.setWrapStyleWord(true);
textAreas.add(area1);
JTextArea area2 = new JTextArea("and another that is much longer, so that it wraps to the next line");
area2.setLineWrap(true);
area2.setWrapStyleWord(true);
textAreas.add(area2);
JScrollPane scrollPane = new JScrollPane();
scrollPane.setViewportView(textAreas);
frame.add(scrollPane);
frame.pack();
frame.setVisible(true);
}
I have done research on this topic on my own, including looking at different layout managers (http://docs.oracle.com/javase/tutorial/uiswing/layout/visual.html), and checking other questions on the site, but I haven't had much luck.
TLDR: Can I make it so each element of a layout has a height that scales to its content but a fixed width? If so how?
What I really want is simple - a text area that wraps text where I can control the width but allow the height to scale dynamically as more lines are added.
The BoxLayout respects the maximum size so the text area grows to fill all the space available in the panel. You can override the getMaximumSize() method to return the preferred height by using something like:
JTextArea area1 = new JTextArea()
{
public Dimension getMaximumSize()
{
Dimension d = super.getMaximumSize();
d.height = getPreferredSize().height;
return d;
}
};
It works...
Not really. Make the frame wider and the text will unwrap. Then shrink the frame and the scrollbar will appear. That is the text will not wrap again
What you need to do is force the panel added to the scroll pane to be the same width as the viewport. This will allow wrapping to work properly.
You do this by implementing the Scrollable interface on the panel. Specifically you need to override the getScrollableTracksViewportWidth() method to return true.
Or an easier solution is to use the Scrollable Panel class which allows you to set properties of the panel to control this behaviour.
You can replace a JPanel with the ScrollablePanel:
//JPanel textAreas = new JPanel();
ScrollablePanel textAreas = new ScrollablePanel();
textAreas.setScrollableWidth( ScrollablePanel.ScrollableSizeHint.FIT );
Edit:
If there is a solution that uses a different layout manager
Without overriding the getMaximumSize() method of the text areas and when using the Scrollable Panel you should be able to use the following layout managers.
The GridBagLayout allows you to specify the "weightx" constraint. This will allow the component to fill all the available space in the panel.
Or if you don't like specifying all the constrains of the GridBagLayout you could use the Relative Layout which support vertical/horizontal layout of components at their preferred size.
You would just need to use the following to force the component to fill the horizontal space:
//textAreas.setLayout(new BoxLayout(textAreas, BoxLayout.Y_AXIS));
RelativeLayout rl = new RelativeLayout(RelativeLayout.Y_AXIS);
rl.setFill( true );
textAreas.setLayout(rl);
I'm adding a quantity of JTextField to a panel, and all of them are added but, the last one added takes the whole panel and seems all other text boxes added on the last one..... here is the code
public JPanel crearCartonFormulario() {
panel = new JPanel();
panel.setLayout(new BorderLayout());
JTextField[] textBoxes = new JTextField[25];
int cont = 0;
int posX = 10;
int posY = 0;
llenarArreglo();
while (cont <= 4) {
for (int i = 0; i <= 4; i++) {
if (cont == 2 && i == 2) {
textBoxes[i] = new JTextField("");
} else {
textBoxes[i] = new JTextField(String.valueOf(numeros[cont][i]));
}
textBoxes[i].setBounds(i + posX, 15 + posY, 40, 40);
textBoxes[i].setEditable(false);
panel.add(textBoxes[i]);
posX += 50;
}
posY += 50;
posX = 10;
cont++;
}
return panel;
}
This is returned at a panel where I keep multiple panels of this one, it works but in this one the last JTextField takes the whole panel space....
The new JFrame that contains the panels created by the method, adopt the last JTextField size and that text box doesn't take the bounds indicated by the method, but all the other text boxes still inside and correctly added.
panel.setLayout(new BorderLayout());
You are using a BorderLayout.
panel.add(textBoxes[i]);
When you use the add() method the default is to add the component to the CENTER of the BorderLayout. However, only a single component can be added to the center so the layout manager will only manage the size/location of the last component added. The rules of the BorderLayout is to make the component take up all the available space.
However, you have also used the setBounds() methods for the other text fields which is causing a problem. You should NOT attempt to use a layout manager and manage the bounds of the components yourself.
The solution is to just use a layout manager and let the layout manager do its job. Read the section from the Swing tutorial on Using Layout Managers for more information and use a more appropriate layout manager.
Update:
its a bingo table
Then maybe you shouldn't even be using JTextFields. Maybe a JTable would be a better component to use. The tutorial also has a section on How to Use Tables.
Your problem is here:
panel.setLayout(new BorderLayout());
You set the layout to BorderLayout and yet add components to the JPanel as if it were a GridLayout. Understand that when you add components to a BorderLayout-using container in a default way, the components get added in the BorderLayout.CENTER position which fills this position, covering anything added prevsiously.
Perhaps you wish to use a GridLayout instead? You will want to read the layout manager tutorial for more.
This is because you are using BorderLayout and BorderLaout Always requires a parameter like BorderLayout.CENTER, BorderLayout.WEST, BorderLayout.EAST, BorderLayout.NORTH and BorderLayout.SOUTH.
So basically BorderLayout only has 5 position where a component can go. And if you do not specify where when adding a component it defaults to BorderLayout.CENTER. And as there can only be one component at a time in the BorderLayout.CENTER position it only really adds the last one. So I'd suggest an other layout manager like GridLayout( if you want all the components to be equally sized).
I hope this helps :).
P.S. If you want me to give some explination on GridLayout just ask.
I have a simple Class StatPanel that extends JPanel and has a few JTextFields, a JCheckBox, and a couple JLabels. The panel is going to be used as a series of panels used to display information and allow the user to edit the data in some of the JTextFields and I will probably have about 40 of them all stacked together on the side of the program in a JScrollPane JPanel. The layout I am using is a GridLayout(0,1).
I have them working but when the are in the scroll panel they are spaced too far apart vertically. I have tried changing the margins, changing the spacing in the GridLayout and changing the margins of the various items. Nothing I do seems to make them closer.
This is the constructor for the StatPanel class:
public StatPanel(String statName, String statAbility){
super();
this.skillName = statName;
this.setAlignmentY(CENTER_ALIGNMENT);
isClassSkill = new JCheckBox();
statLabel = new JLabel(skillName);
statTotalField = new JTextField(maxLength + 1);
statTotalField.setHorizontalAlignment(JTextField.CENTER);
statAbilityLabel = new JLabel("= " + statAbility + " ");
statAbilityModField = new JTextField(maxLength);
statAbilityModField.setHorizontalAlignment(JTextField.CENTER);
statSeperator1 = new JLabel(" + ");
statRanksField = new JTextField(maxLength);
statRanksField.setHorizontalAlignment(JTextField.CENTER);
statSeperator2 = new JLabel(" + ");
statMiscModField = new JTextField(maxLength);
statMiscModField.setHorizontalAlignment(JTextField.CENTER);
this.add(isClassSkill);
this.add(statLabel);
this.add(statTotalField);
this.add(statAbilityLabel);
this.add(statAbilityModField);
this.add(statSeperator1);
this.add(statRanksField);
this.add(statSeperator2);
this.add(statMiscModField);
}
}
When I use it in the program it looks like this:
As I am going to stack so many of them I want them pretty much one on top of the other but I can seem to remove the gap between them.
How is this done?
Thank you for your help.
Check out the FlowLayout API. By default a JPanel uses a FlowLayout with default horizontal/vertical gap of 5 pixels. You will want to change the vertical gap used by the layout manager. So at the top of your method you will want to add:
setLayout( new FlowLayout(...) );
Edit:
Once you change the gap you will also lose the gap at the top/bottom of the main panel so you might want to add an EmptyBorder to the panel.
I've a big problem with Swing in Java, I used BoxLayout for this but still it looks bad.
Any suggestions about my usage of layouts, or how to change it to look like in assumptions? (here are assumptions)
Container main = new Container();
Container left = new Container();// here goin buttons
Container right = new Container(); // here goin tabs + more buttons, textfields and other stuff
BoxLayout lewyL = new BoxLayout(left, BoxLayout.Y_AXIS);
left.setLayout(lewyL);
left.add(rastrowa); //radiobutton
left.add(wektorowa);//radiobutton
left.add(apDwuliniowa);//checkbox
left.add(wczytaj);//button
left.add(zapisz);//obutton
left.add(wyczysc);//button
BoxLayout prawyL = new BoxLayout(right, BoxLayout.Y_AXIS);
right.setLayout(prawyL);
right.add(zakladki);// tabs (mostly i use BoxLayout but for last one i need something more "complicated")
EDIT: I almost solve this problem, I need to move all elements to left (how it look like)but I have no idea how ;/ Here is constructor of this class.
JLabel label = new JLabel("O wektor");
JLabel labelA = new JLabel("a:");
JLabel labelB = new JLabel("b:");
JButton wykonaj = new JButton("Wykonaj");
JTextField a = new JTextField(5);
JTextField b = new JTextField(5);
add(label);
add(labelA);
add(a);
add(labelB);
add(b);
add(wykonaj);
There's nothing wrong with the way it looks (in my opinion), but if you want it to look a little better, why don't you convert the left panel (which is 6x1) into a 3x2 panel, with the checkboxes/radiobuttons on the left, and buttons on the right? Sounds like a job for GridLayout - one of my favorite classes...
JPanel leftPanel = new JPanel(new GridLayout(3,2));
leftPanel.add(rastrowa); //radiobutton
leftPanel.add(wczytaj); //button
leftPanel.add(wektorowa); //radiobutton
leftPanel.add(zapisz); //obutton
leftPanel.add(apDwuliniowa); //checkbox
leftPanel.add(wyczysc); //button
Note that the 3,2 defines the number of rows,columns. When adding panels, they are added to the grid from left-to-right, and top-to-bottom. GridLayout also auto-sizes the components, so all the buttons etc will be the same width and height, making it look more consistent.
The GridLayout documentation might be useful, and the Visual Guide to Layout Managers is a great place to see other layout managers that might work better for your different situations. I personally find BorderLayout and GridLayout to be the most useful, and cover about 95% of the situations I ever need for my GUIs.
I have a problem with resizing some of my components in my java application. When I resize my main JFrame they keep their previous size instead of filling out the surrounding component.
For example I have in my program a JTabbedPane within a tab of another JTabbedPane (which is located within the main JFrame). I make tabs added to the inner JTabbedPane fill the whole surrounding space via various .setPreferredSize(). And then when I resize the JFrame by dragging the corner of the window, the tabs out the outer JTabbedPane resizes just fine but the JTabbedPane located within it stays the same old size.
The same thing with happens when I test it with a JScrollPane: the outer JTabbedPane resizes by the JScrollPane stays the same size.
Here below is the code for creating the tabbed panels in case you can see something obvious I missed. It's the tabPane/jsp objects in createEndGamePane() than wont resize when the JFrame is resized. mainTabPane resizes as it should.
class MyFrame extends JFrame {
private JTabbedPane mainTabPane;
private JPanel endGameInfo;
//....
private void createTabbedCenterPane(){
this.mainTabPane = new JTabbedPane();
this.endGameInfo = new JPanel();
this.createEndGamePane();
this.mainTabPane.addTab("Turneringschema", null, this.scheduleHolder, "Spelschemat för turneringen");
this.mainTabPane.addTab("Grupper & Pooler", null, this.poolInfo, "Information om grupper, lag och pooler");
this.mainTabPane.addTab("Slutspelsträd", null, this.endGameInfo, "Information om slutspelen");
this.add(this.mainTabPane, BorderLayout.CENTER);
}
private void createEndGamePane(){
JTabbedPane tabPane = new JTabbedPane();
tabPane.setPreferredSize(this.endGameInfo.getSize());
for (int i = 0; i < this.tournament.data.getGroups().size(); i++) {
EndGame e = this.tournament.data.getEndGames().get(i);;
//Create the gameTree
EndGameTreeCanvas gameTree = new EndGameTreeCanvas(e, this.endGameInfo.getSize());
//Create the ScrollPane
JScrollPane jsp = new JScrollPane(gameTree);
jsp.setPreferredSize(tabPane.getSize());
jsp.setBorder(BorderFactory.createEmptyBorder());
//Add to the endGameIndo panel
tabPane.addTab(this.tournament.data.getGroups().get(i).getName(), jsp);
}
this.endGameInfo.add(tabPane);
}
}
If you want the components to resize dynamically, you should avoid telling Swing what their size is. Instead, how about this:
JTabbedPane tabs = new JTabbedPane();
JScrollPane inner1 = new JScrollPane(myOtherComponent);
tabs.add("Scroll", inner1);
JTabbedPane inner2 = new JTabbedPane();
tabs.add("Tabs", inner2);
And that's all. No setPreferredSize().
You should read the swing layout tutorial :
http://java.sun.com/docs/books/tutorial/uiswing/layout/index.html
The layout manager i prefer is the gridbaglayout that allow maximum flexibility
( http://java.sun.com/docs/books/tutorial/uiswing/layout/gridbag.html ).
In particular, you should not use the BorderLayout.CENTER if you wish the component to fill all the available space around him.
an example with a gridbaglayout manager :
this.add(this.mainTabPane,
new GridBagConstraints(
0,0, // position
1,1, // size
1.0,1.0, // fill ratio
GridBagConstraints.CENTER, GridBagConstraints.BOTH, // position inside the cell
new Insets(2,2,2,2),0,0)); // margins
As others have said, you need to be using layout managers to handle your GUI's layout requirements.
However I recommend that your primary layout manager be a table-based layout like MatrixLayout, MigLayout, TableLayout, or any of a number of other free ones.
Using a table-based layout will simplify your GUI coding by about an order of magnitude, because it will vastly reduce the amount of layout nesting required. I find that 90% of my GUI is done with one layout manager, and the remaining 10% draws on the simpler layout managers provided with Java.
I have never had cause to use GridBagLayout and I absolute do not recommend it - it's unnecessarily complicated and make ongoing maintenance harder.