Reputation: 2630
I am writing a program that allows multiple users the share screenshots. Every time a user connects, everyone who is participating in the "room" (a bunch of users that are able to receive screen shots from one another) becomes able to see a screen shot that the user takes. To be able to see the screen shot, the frame needs to split itself up so that there is a dedicated space for that user's screen shots.
I decided to use a GridLayout because it splits components into equally-sized rectangles which is what I am looking for. The layout does exactly what I need it to, except there is one problem. If I my GridLayout configured that there are two rows and columns, the bottom-most row will still be split into two columns, even when there is only a single component. This is expected behavior, but is there a walk-around, preferably without using a different layout? I really like the simplicity of GridLayout. I have considered using a BorderLayout, but it is limited because there is a set amount of spaces where I can place items.
The format of the pictures wasn't supported, so I could not embed them into this question. Here is how the frame looks like it is full. I substituted the actual screen shots for buttons because I am just testing.
http://cl.ly/0N311g3w061P1B0W1T3s/Screen%20shot%202012-05-13%20at%204.23.25%20PM.png
Now here is how it looks when I remove a button from the bottom-most row: http://cl.ly/2j3Z0V1r3w1S3F160j05/Screen%20shot%202012-05-13%20at%204.23.41%20PM.png
Here is how I would want the bottom-most row to look: http://cl.ly/0J2R2y2L06151F0k0Y0i/Screen%20shot%202012-05-13%20at%204.24.11%20PM.png
How can I make the bottom-most row look like that? Keep in mind I still want the other rows to have two columns, but I only want the bottom-most one to have one column.
Thanks!
Upvotes: 1
Views: 6504
Reputation: 2630
I decided to go with a slightly different approach. Since the separate screens are laid out really nicely using GridLayout when there are an even amount of screens, I decided to simply split up the screens into pages if there is an odd amount of screens.
Upvotes: 1
Reputation: 47617
To my knowledge, you can't. GridLayout is done this way.
But GridBagLayout will do a beautiful job for your program.
Take a look at this small demo that lays out buttons in rows and columns. (Click on a button to remove it).
import java.awt.Component;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class Test4 {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame();
final JPanel root = new JPanel(new GridBagLayout());
frame.add(root);
frame.setSize(600, 600);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
Timer t = new Timer(2000, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
final JButton b = new JButton("Hello" + root.getComponentCount());
b.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
root.remove(b);
updateConstraints(root);
}
});
root.add(b);
updateConstraints(root);
}
});
t.start();
}
});
}
protected static void updateConstraints(JPanel root) {
if (!(root.getLayout() instanceof GridBagLayout)) {
System.err.println("No a gridbaglayout");
return;
}
GridBagLayout layout = (GridBagLayout) root.getLayout();
int count = root.getComponentCount();
int col = (int) Math.round(Math.sqrt(count));
int row = (int) Math.ceil((double) count / col);
GridBagConstraints gbc = new GridBagConstraints();
gbc.fill = GridBagConstraints.BOTH;
gbc.weightx = 1.0;
gbc.weighty = 1.0;
int index = 0;
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
gbc.gridx = j;
gbc.gridy = i;
boolean last = index + 1 == count;
if (last) {
gbc.gridwidth = col - j;
}
Component c = root.getComponent(index);
layout.setConstraints(c, gbc);
if (last) {
break;
}
index++;
}
}
root.doLayout();
}
}
Upvotes: 2
Reputation: 7298
I think you want to use the GridBagLayout
- check out the visual guide to layouts
In particular, with a GridBagLayout
, you add components with a GridBagConstraints
. This allows you to specify where each component should be put, but also what weight each component should have - e.g. see the GridBagLayout tutorial.
Upvotes: 0