I have been trying for a while to make this work. I have looked at many tutorials and examples on-line, nothing seems to help.
The combo box and the label are both centered right under each other in the middle of the frame.
I know that there needs to be a GridBagConstraints
and you need to set the gbc every time you add a new component.
I am doing that so I am not sure why it's not working.
Also why would it be in the center? Shouldn't it be in the top left if anything?
public class Application {
ArrayList listOfTickers = new ArrayList();
JFrame frame;
JPanel panel;
JLabel jLabel;
GridBagLayout layout;
GridBagConstraints gbc;
JComboBox comboBox;
Application(ArrayList listOfTickers) throws BadLocationException {
this.listOfTickers = listOfTickers;
setLabels();
setComboBox(listOfTickers);
setFrameAndPanel();
addComponents();
closeFrame();
}
private void addComponents() {
addobjects(jLabel, panel, layout, gbc, 1, 3, 4, 2);
addobjects(comboBox, panel, layout, gbc, 3, 0, 2, 1);
}
private void setLabels() {
jLabel = new JLabel("test");
}
private void closeFrame() {
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
private void setComboBox(ArrayList listOfTickers) throws BadLocationException {
comboBox = new JComboBox(listOfTickers.toArray());
comboBox.addActionListener(e -> {
String ticker = comboBox.getSelectedItem().toString();
});
}
private void setFrameAndPanel() {
frame = new JFrame("JFrame Example");
panel = new JPanel();
layout = new GridBagLayout();
panel.setLayout(layout);
frame.getContentPane().setLayout(layout);
gbc = new GridBagConstraints();
frame.add(panel);
frame.setSize(600, 600);
}
public void addobjects(Component component, Container panel, GridBagLayout layout, GridBagConstraints gbc, int gridx, int gridy, int gridwidth, int gridheight) {
gbc.gridx = gridx;
gbc.gridy = gridy;
gbc.gridwidth = gridwidth;
gbc.gridheight = gridheight;
layout.setConstraints(component, gbc);
panel.add(component, gbc);
}
}
Also why would it be in the center? Shouldnt it be in the top left if anything?
No, this is how GridBagLayout works, GridBagLayout
will layout it's components around the centre of the container
. You can play around with the weightx/y
properties to change how much of the remaining space is allocated to a given cell.
I would also recommend avoid gridwidth
and gridheight
until you have a better understanding of what these do, as they are effecting the position of your components
The following will move the components to the top/left point of the container...
private void addComponents() {
gbc.gridx = 1;
gbc.gridy = 3;
gbc.weighty = 1;
gbc.anchor = GridBagConstraints.NORTHWEST;
panel.add(jLabel, gbc);
gbc.gridx = 3;
gbc.gridy = 0;
gbc.anchor = GridBagConstraints.WEST;
gbc.weightx = 1;
gbc.weighty = 0;
panel.add(comboBox, gbc);
}
Although, since you're applying a GridBagLayout
to the JFrame
itself, I'd be tempted to change the weightx/y
and anchor
properties for the panel
itself when you add it to the frame, it will make it much simpler
so if I wanted to let say build a calculator with positioning the buttons in specific areas, essentially transforming the entire panel into one big grid and plotting my containers inside that grid what would be the best layout to use and how would I do that?
That depends ultimately on what you want the UI to look like. If all you want is for all the buttons to evenly occupy the available space, the maybe GridLayout
would be a better choice...
import java.awt.EventQueue;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class Application {
public static void main(String[] args) {
new Application();
}
public Application() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new GridLayout(4, 3));
String labels[] = new String[] {"7", "8", "9", "4", "5", "6", "1", "2", "3", "", "0", ""};
for (String label : labels) {
if (label.trim().isEmpty()) {
add(new JLabel());
} else {
add(new JButton(label));
}
}
}
}
}
Note, I had to allow for two empty spaces around the 0 button, this is a requirement of GridLayout
, as you don't get control over which cells the components actually appear, they are simply laid out in a linear fashion.
However, if you would prefer something that looks more like most calculators, then you'll need GridBagLayout
...
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Application {
public static void main(String[] args) {
new Application();
}
public Application() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new GridBagLayout());
String labels[][] = new String[][]{{"7", "8", "9"}, {"4", "5", "6"}, {"1", "2", "3"}};
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridy = 0;
for (String[] row : labels) {
gbc.gridx = 0;
for (String col : row) {
add(new JButton(col), gbc);
gbc.gridx++;
}
gbc.gridy++;
}
gbc.gridx = 0;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.gridwidth = 3;
add(new JButton("0"), gbc);
}
}
}
Needs drive musts, you need to decide on the need of flexibility over uniformity (in this case). GridBagLayout
is very powerful and flexible, but with it comes complexity.
Note: I could have done the second layout using two panels and two GridLayout
s as well - which is an important concept, you're not stuck to a single layout manager, you can use multiple panels, each using different layout managers and "compound" them together to produce a rich interface