I am having issue where my JPanel is not setting up the size. I am not sure if is something to do with my JTab or JFrame. I am using GridBagLayout layout management. And for some reason are not able to set the size.
Here is a dummy code, following the same logic to my original source code:
FirstPanel.java
import javax.swing.*;
import java.awt.*;
public class FirstPanel extends JPanel {
private JLabel label1 = new JLabel("Label 1");
private JTextField textField1 = new JTextField();
private GridBagConstraints c = new GridBagConstraints();
public FirstPanel() {
//Size is not overriding
Dimension size = getPreferredSize();
size.width = 100;
setPreferredSize(size);
setBorder(BorderFactory.createTitleBorder("Border Title");
setLayout(new GridBagLayout());
addComponents();
}
private void addComponents() {
c.gridx = 0;
c.gridy = 0;
c.anchor = GridBagConstraints.NORTHWEST;
c.insets = new Insets(5, 0, 0, 0);
add(label1, c);
c.gridx = 1;
add(textField1, c);
c.weightx = 1;
c.weighty = 1;
add(new JLabel(""), c);
}
}
MainPanel.java
import javax.swing.*;
import java.awt.*;
public class MainPanel {
private JFrame frame = new JFrame("App");
private JPanel panel1 = new JPanel(new GridBagLayout());
private GridBagConstraints c = new GridBagConstraints();
private JTabbedPane tabPane = new JTabbedPane();
public MainPanel() {
addComponents();
frame.add(tabPane);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500, 350);
frame.setVisible(true);
frame.setLocationRelativeTo(null);
frame.setResizable(false);
}
private void addComponents() {
tabPane.addTab("Tab 1", new FirstPanel());
}
}
Main.java
public class Main {
public static void main(String[] args) {
new MainPanel();
}
}
Or at least have two JPanels,
Exactly.
Frist you create a main panel using a BorderLayout that you add to the tabbed pane.
Then you have a second panel for your labels and text fields (using whatever layout manager you want). Then you add this panel to the BorderLayout.LINE_START.
Then you add your scrollpane containing the JTable to the BorderLayout.CENTER of the main panel.
Read the tutorial on Layout Manager. Nest panels with different layout managers as required.
want to have JTable taking 50% of the other side.
Picking a random number like 50% is not the way to design a GUI. What happens if the frame is made smaller/larger. What happens to the space? Design the layout with flexibility in mind, just like your browser window is designed. There are always fixed areas where the size is determined by the components added and there is a flexible area that grows/shrinks as desired.
Related
I'm currently designing a GUI assignment planner. I have run across a few issues along the way. For one part of my program I have a panel to hold assignments that still need to be completed. What I would like to create is a panel that will add containers (holding the components to display an assignment) to a panel. However, the only way I can conceive of doing this is by lengthening the panel each time a container is added. Unfortunately, to the best of knowledge, this isn't possible since a panel is given a defined width and depth when it is created. Ideally, if possible, I'd like to increase the panel length every time a container is added. A scrollbar would scroll down the panel.
So is this possible? Am I approaching this the right way? I am very new to GUI so I am open to improvements and suggestions. If anyone would like me to post my code so far, I will. (Beware, it is in very rough shape at the moment)
Attached below is a rough draft of what I am trying to make:
TIA
This is the majority of my code so far. The problem is that once i add a certain amount of containers it starts to make them smaller. I just want to extend it every time a container is added. Most of the comments are for documentation or to remind to do something.
import javax.swing.*;
import java.awt.*;
//import java.util.ArrayList;
public class MyWindow
{
private final JFrame frame = new JFrame();
private final int WINDOW_WIDTH = 500, WINDOW_DEPTH = 500;
private JPanel panel;
private JPanel toDoList, completed;
//ArrayList<JFrame> frame = new ArrayList<>();
public MyWindow()
{
frame.setTitle("Assignment Planner");
this.contents();
}
private void contents()
{//use an arraylist to create containers ArrayList<JPanel> container = new ArrayList<>();
frame.setSize(WINDOW_WIDTH, WINDOW_DEPTH);
panel = new JPanel(new GridLayout(2, 1));
toDoList = new JPanel();
toDoList.setLayout(new /*GridLayout(0,1,5,5)*/BoxLayout(toDoList, BoxLayout.PAGE_AXIS));
toDoList.setPreferredSize(new Dimension(250, 250));
panel.add(toDoList);
completed = new JPanel();
//panelCompleted.setLayout(new GridLayout(0, 1)); //fix like one above
panel.add(completed);
JScrollPane scroll = new JScrollPane(toDoList);
panel.add(scroll); //scroll panes for both panels
JScrollPane scroll2 = new JScrollPane(completed);
panel.add(scroll2);
toDoList.add(assignment());
toDoList.add(Box.createRigidArea(new Dimension(0,1)));
toDoList.add(assignment());
toDoList.add(Box.createRigidArea(new Dimension(0,1)));
toDoList.add(assignment());
toDoList.add(Box.createRigidArea(new Dimension(0,1)));
beginningScrollPaneValue += 110;
toDoList.setPreferredSize(new Dimension(250, beginningScrollPaneValue));
toDoList.revalidate(); //scroll.revalidate();
toDoList.repaint(); //scroll.repaint();
frame.getContentPane().add(panel, BorderLayout.CENTER);//add the panel in the JFrame's content pane in the center
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
JPanel assignment()
{
JPanel container = new JPanel(new GridBagLayout());
container.setMaximumSize(new Dimension(500,100));
GridBagConstraints c = new GridBagConstraints();
c.weightx = 0.5;
JCheckBox cb = new JCheckBox();
c.fill = GridBagConstraints.NONE;
c.gridx = 1;
c.gridy = 0;
container.add(cb, c);
container.setBackground(Color.red);//does no fill area behind checkbox
return container;
}
}
I'm trying to use GridBagLayout but the GridBagConstraints objects doesn't show any effect. I want a button to fill the horizontal space. Any Ideas?
static class Five extends JFrame {
public Five() {
setSize(300, 400);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
c.gridx = 0;
c.gridy = 0;
c.fill = GridBagConstraints.HORIZONTAL;
JButton button = new JButton("Long-Named Button 4");
add(button, c);
setVisible(true);
}
This works, details in comments:
import java.awt.*;
import javax.swing.*;
public class Five extends JFrame {
public Five() {
setSize(300, 400);
setDefaultCloseOperation(EXIT_ON_CLOSE);
// best to do all important stuff in a panel added to the frame
JPanel gui = new JPanel(new GridBagLayout());
setContentPane(gui);
GridBagConstraints c = new GridBagConstraints();
c.gridx = 0;
c.gridy = 0;
c.fill = GridBagConstraints.HORIZONTAL;
c.weightx = 1d; // fixes the problem
JButton button = new JButton("Long-Named Button 4");
add(button, c);
pack(); // should always be done after all components are added
setVisible(true);
}
public static void main(String[] args) {
Runnable r = new Runnable() {
#Override
public void run() {
new Five();
}
};
SwingUtilities.invokeLater(r);
}
}
Further tips:
There is no good case for extending JFrame in this case, just do the relevant additions etc. to an instance of a standard frame.
To make the button larger, set a large icon, large insets, or large font. To make the frame bigger, add an EmptyBorder around the gui panel.
Trying to understand GridBagLayout and to fully work it. I'm trying some examples.
What my aim is to have three buttons directly below one another, and three buttons going across the screen.
Now I can get the first two rows working fine but the third row just goes straight to the middle of the screen.
import javax.swing.*;
import java.awt.*;
class test
{
public static void main (String Args [])
{
//frame and jpanel stuff
JFrame processDetail = new JFrame("Enter information for processes");
JPanel panelDetail = new JPanel(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
//label to add on top centre
JButton label = new JButton("Proccess:");
JButton label2 = new JButton("Arrival Time");
JButton label3 = new JButton("Quanta Time");
JButton label4 = new JButton("woooo");
JButton label5 = new JButton("LdsdaE");
JButton label6 = new JButton("affafa 666");
//set size of frame and operation
processDetail.setSize(500,500);
processDetail.setDefaultCloseOperation(processDetail.EXIT_ON_CLOSE);
//add the label to panel
c.gridx = 0;
c.gridy = 0;
c.weightx = 0.5;
//c.weighty = 0.5;
c.fill = GridBagConstraints.NONE;
c.anchor = GridBagConstraints.PAGE_START;
panelDetail.add(label, c); //row 1 left
c.gridx=1;
panelDetail.add(label2, c); //row 1 middle
c.gridx=2;
panelDetail.add(label3, c); //row 1right
c.weighty=0.1;
c.gridx=0;
c.gridy=1;
panelDetail.add(label4, c); //row 2 left
c.gridx=0;
c.gridy=2;
panelDetail.add(label5, c); //row 3 left
processDetail.add(panelDetail);
processDetail.setVisible(true);
}
}
Edit
The button label 5, should be directly underneath the button label 4:
Like so:
[----LABEL 4 ---]
[----LABEL 5 ---]
at the moment its like:
[----LABEL 4 ---]
(dont want this gap between the two?)
[----LABEL 5 ---]
If you want the buttons all at the top with minimal gap between them, then either consider using a GridLayout and placing your JButtons into the GridLayout using JPanel, and then have your main JPanel use a BorderLayout add the button holding JPanel to your main JPanel BorderLayout.PAGE_START. Or the button holding JPanel could use a GridBagLayout, but I'd still nest it into a main JPanel and again at the BorderLayout.PAGE_START position. For example,
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import javax.swing.*;
public class Test4 extends JPanel {
private static final long serialVersionUID = 1L;
private static final int GAP = 3;
public Test4() {
JPanel buttonHoldingPanel = new JPanel(new GridLayout(3, 3, GAP, GAP));
buttonHoldingPanel.add(new JButton("Process"));
buttonHoldingPanel.add(new JButton("Arrival Time"));
buttonHoldingPanel.add(new JButton("Quanta Time"));
buttonHoldingPanel.add(new JButton("woooo"));
buttonHoldingPanel.add(new JLabel());
buttonHoldingPanel.add(new JLabel());
buttonHoldingPanel.add(new JButton("LdsdaE"));
buttonHoldingPanel.add(new JLabel());
buttonHoldingPanel.add(new JLabel());
setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP));
setLayout(new BorderLayout());
add(buttonHoldingPanel, BorderLayout.PAGE_START);
add(Box.createRigidArea(new Dimension(400, 300)), BorderLayout.CENTER);
}
private static void createAndShowGui() {
Test4 mainPanel = new Test4();
JFrame frame = new JFrame("Test4");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
Which creates this:
And as per my comment, if this image doesn't match the overall structure of the GUI you're trying to create, then please show us an image of just what it is you're trying to achieve.
I have a JPanel with a GridBagLayout inside of a JScrollPane. I also have an 'add' button within the JPanel which, when clicked, will be removed from the JPanel, adds a new instance of a separate component to the JPanel, then adds itself back to the JPanel. This sort of makes a growing list of components, followed by the 'add' button.
Adding new components works fine, the JPanel stretches to accommodate the new components, and the JScrollPane behaves as expected, allowing you to scroll through the entire length of the JPanel.
This is how the add works:
jPanel.remove(addButton);
GridBagConstraints c = new GridBagConstraints();
c.gridx = 0;
c.gridy = GridBagConstraints.RELATIVE;
jPanel.add(new MyComponent(), c);
jPanel.add(addButton, c);
jPanel.validate();
jPanel.repaint();`
Removal works by clicking a button inside the added components themselves. They remove themselves from the JPanel just fine. However, the JPanel keeps it's stretched-out size, re-centering the list of components.
This is how removal works:
Container parent = myComponent.getParent();
parent.remove(myComponent);
parent.validate();
parent.repaint();`
The question is, why does my GridBagLayout JPanel resize when adding components, but not when removing components?
You have to revalidate and repaint the JScrollPane, here is an example:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class SwingTest {
public static void main(String[] args) {
final JPanel panel = new JPanel(new GridBagLayout());
for (int i = 0; i < 25; i++) {
JTextField field = new JTextField("Field " + i, 20);
GridBagConstraints constraints = new GridBagConstraints();
constraints.gridy = i;
panel.add(field, constraints);
}
final JScrollPane scrollPane = new JScrollPane(panel);
JButton removeButton = new JButton("Remove Field");
removeButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (panel.getComponentCount() >= 1) {
panel.remove(panel.getComponentCount() - 1);
scrollPane.revalidate();
scrollPane.repaint();
}
}
});
JFrame frame = new JFrame("Swing Test");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setSize(640, 480);
frame.setLocation(200, 200);
frame.getContentPane().add(scrollPane);
frame.getContentPane().add(removeButton, BorderLayout.SOUTH);
frame.setVisible(true);
}
}
I'm using a JTable and adding it to a panel which uses a gridbaglayout like so:
JTable qdbs = new JTable(rowData, columnNamesVector);
qdbs.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
panel.add(qdbs, c);
I don't want the table to be in a scroll pane, but I do want the table to take up the entire width of the panel. How would I accomplish this?
An SSCCE as requested:
import javax.swing.*;
import java.awt.*;
public class Main{
public static void main(String[] args) {
new TestFrame();
}
public static class TestFrame extends JFrame{
public TestFrame() {
this.setTitle("SSCCE");
JPanel panel = new JPanel();
panel.setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
c.gridx = 0;
c.gridy = 0;
c.insets = new Insets(10,10,10,10);
JTable testTable = new JTable(10,2);
panel.add(testTable, c);
this.add(panel);
this.pack();
this.setVisible(true);
}
}
}
I would like this table to always take up the entire width of the panel (except the insets). Currently the table does not change size when the frame is resized.
You need to add constrains to tell the layout what to do with more space. In your SSCCE add these items:
c.fill = GridBagConstraints.BOTH;
c.weightx = 1;
c.weighty = 0;
import java.awt.*;
import javax.swing.*;
public class Test
{
public static void main(String args[]) throws Exception
{
JPanel panel = new JPanel( new GridBagLayout() );
JTable table = new JTable(5, 5);
GridBagConstraints gbc = new GridBagConstraints();
gbc.weightx = 1.0;
gbc.fill = GridBagConstraints.HORIZONTAL;
panel.add(table, gbc);
JFrame frame = new JFrame();
frame.add(panel, BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
}
}
If you need more help post a SSCCE that demonstrates the problem.
c is a GridBagConstraint or something along those lines, I imagine? The very simplest thing to do would be to set the LayoutManager of the JPanel to a BorderLayout, then just add with the constraint BorderLayout.CENTER .
hmmm
Alex Bliskovsky wrote panel.add(qdbs, c);
that's wrong, not, never do that, you are forgot wrap you JTable to the ScrollPane and then you can play with some of LayoutManagers, for related examples for LayoutManagers check GridBagConstraints for GrigBagLayout
The following frame will correctly resize the table when the frame is resized.
public class Sandbox {
public static void main(String[] args) {
new TestFrame();
}
public static class TestFrame extends JFrame {
public TestFrame() {
this.setTitle("SSCCE");
JPanel panel = new JPanel();
panel.setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
c.gridx = 0;
c.gridy = 0;
c.insets = new Insets(10, 10, 10, 10);
c.fill = GridBagConstraints.BOTH;
c.weightx = 1;
c.weighty = 1;
JTable testTable = new JTable(10, 2);
panel.add(testTable, c);
this.add(panel);
this.pack();
this.setVisible(true);
}
}
}
Perhaps with:
GridBagConstraints.fill = GridBagContraints.BOTH;