Can I increase panel length every time a container is added? - java

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;
}
}

Related

using a GridBagLayout, JScrollpane doesn't work (or look appropriate) with JList

I'm aware there are several questions with the same title, and I've tried their answers but to no avail.
I'm getting the following result with my code:
It does not scroll as it should, and there's this empty little space to the right.
Here is the main code for the frame, mainpanel, list panel and the buttons panel that are inside the mainpanel.
public Tester2() {
JPanel mainPanel = new JPanel(); /////// MAIN PANEL
mainPanel.setLayout(new BorderLayout());
mainPanel.setPreferredSize(new Dimension(200, 400));
JPanel upperListPnl = new JPanel(); ////// LIST PANEL
upperPnlSetup(upperListPnl);
JPanel lowerBtnsPnl = new JPanel(); ///// BUTTONS PANEL
lowerBtnsPnl.setLayout(new BorderLayout());
JButton testButton = new JButton("Test the list");
testButton.addActionListener(e -> {
exampleModel.addElement("List has been tested");
updateExampleData();
});
lowerBtnsPnl.add(testButton);
mainPanel.add(upperListPnl, BorderLayout.CENTER);
mainPanel.add(lowerBtnsPnl, BorderLayout.SOUTH);
JFrame frame = new JFrame();
frame.add(mainPanel);
frame.setVisible(true);
frame.pack();
frame.setLocationRelativeTo(null);
}
Here is the code for the JList and the JScrollpane (upper panel):
public void upperPnlSetup(JPanel panel) {
panel.setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
exampleList = new JList<>(exampleModel);
JScrollPane jsp = new JScrollPane(exampleList, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
c.fill = GridBagConstraints.BOTH;
c.weighty = 1;
c.weightx = 0.75;
panel.add(exampleList, c);
c.weightx = 0.25;
panel.add(jsp, c);
}
And then the JList and model list as well as the data updating method:
private JList<String> exampleList;
private DefaultListModel<String> exampleModel = new DefaultListModel<>();
public void updateExampleData() {
exampleList.setModel(exampleModel);
}
I tried a FloatLayout, a BorderLayout, and a GridLayout (0,2 and 0,1) all of which didn't work. Finally, I settled for the GridBagLayout since it's seemingly always used for JLists and/or JScrollpanes, and I played with the GridBagConstraints as well as the positioning of the code but seem to always land on the same problem. I've tried giving the scroll pane a preferredSize, didn't do anything.
Okay so, apparently the problem was that I was adding the list to the panel. Adding it to the scrollpane, then adding the scrollpane to the panel was enough, so commenting out the
panel.add(exampleList, c);`
fixed the whole thing.

Setting Size is not overriding on Java

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.

Pack method called from actionPerformed functions only sometimes

Problem
Upon compiling and running my program multiple times, sometimes pack() works and the components of newGamePanel are compressed, and sometimes it doesn't work, and newGamePanel expands to fill the JFrame values set by setSize(). I have been unable to reliably reproduce either result-- it really seems to be random.
Note: As I cut down on the amount of GUI formatting to have a reasonable amount of code to review, the GUI is pretty trash. However, the problem is still easy to identify. When the JPanel that's supposed to be packed is shown by CardLayout, sometimes the JFrame is the "packed" size and sometimes it matches the setSize() values I set in the beginning. Now that I cut the GUI, the newGamePanel components don't move to fill their container, but that's just because I removed all their constraint values.
Suspicions and design
I am calling pack() from class TankEvent, which implements ActionListener. Game is a TankApplication object (TankApplication extends JFrame) passed to TankEvent in the TankEvent constructor, which is called by TankDisplay (TankDisplay extends JPanel).
JFrame instantiates JPanel, passes instance of self.
JPanel instantiates ActionListener, passes instance of self.
ActionListener modifies JFrame using pack().
The following is the code executed when a button is pressed.
CardLayout layOut = (CardLayout)(display.getLayout()); //display is an object of TankDisplay
layOut.show(display, "newGamePanel");
game.pack(); //game is an object of TankApplication
game.setResizable(false);
break;
I wonder if the issue is in my design. I'm making a huge assumption that pack() repaints the JFrame (are JFrames even repainted? Perhaps revalidates/updates?). But as long as I reset the size of JFrame when I'm done, I'm not sure why it would be an issue..
(Side question, I'm not sure why I need to cast display.getLayout() as a CardLayout. This is the suggested implementation from docs.oracle, but why does getLayout() return a LayoutManager and not the actual LayoutManager...?)
Shortened Relevant Code
Tank Display
package Tanks;
import javax.swing.*;
import java.awt.*;
import java.awt.image.*;
import java.io.*;
import java.net.URL;
import javax.imageio.*;
public class TankDisplay extends JPanel{
JCheckBox unlimitedAmmoCB, unlimitedTimeCB;
JTextField playerOneTF, playerTwoTF;
JPanel menuPanel, newGamePanel;
public TankDisplay(TankApplication g){
TankEvent listener = new TankEvent(this, g); //passing an instance of self and previously received instance of TankApplication to TankEvent
setLayout(new CardLayout()); //Hihghest level of GUI after JFrame. CardLayout for overall display JPanel, need for switching functionality in TankEvent
menuPanel = new JPanel(new GridBagLayout()); //Second highest level of GUI. Will eventually display a picture instead of a black JPanel. Has button "New Game" and "Load Game"
JPanel mainMenuImageP = new JPanel();
GridBagConstraints conMainMenuImageP = new GridBagConstraints();
mainMenuImageP.setBackground(Color.BLACK);
conMainMenuImageP.fill = GridBagConstraints.BOTH;
conMainMenuImageP.gridy = 0;
conMainMenuImageP.gridx = 0;
menuPanel.add(mainMenuImageP, conMainMenuImageP); //adding menuPanel components
JButton newGameB = new JButton("New Game");
GridBagConstraints conNewGameB = new GridBagConstraints();
conNewGameB.fill = GridBagConstraints.NONE;
conNewGameB.gridy = 1;
conNewGameB.gridx = 0;
menuPanel.add(newGameB, conNewGameB); //adding menuPanel components
JButton loadGameB = new JButton("Load Game");
GridBagConstraints conLoadGameB = new GridBagConstraints();
conLoadGameB.fill = GridBagConstraints.NONE;
conLoadGameB.gridy = 1;
conLoadGameB.gridx = 1;
menuPanel.add(loadGameB, conLoadGameB); //adding menuPanel components
//action listners for mainPenu panel components
newGameB.addActionListener(listener);
add(menuPanel, "menuPanel"); //menuPanel is added to higher display JPanel
newGamePanel = new JPanel(new GridBagLayout()); //creating second higher level container. To achieve certain functionality,
//this panel contains four other panels, that each contain their own
JPanel playerOneSetUp = new JPanel(new GridBagLayout()); //components. newGamePanel uses GridBagLayout, and so do the panels
GridBagConstraints conPlayerOneSetUp = new GridBagConstraints();//that it's managing. GridBayLayout managaing GridBagLayout
conPlayerOneSetUp.fill = GridBagConstraints.BOTH;
conPlayerOneSetUp.gridy = 0;
conPlayerOneSetUp.gridx = 0;
JLabel playerOneL = new JLabel("Player One Name");
GridBagConstraints conPlayerOneL = new GridBagConstraints();
conPlayerOneL.fill = GridBagConstraints.HORIZONTAL;
conPlayerOneL.gridy = 0;
conPlayerOneL.gridx = 0;
playerOneSetUp.add(playerOneL, conPlayerOneL);
playerOneTF = new JTextField();
GridBagConstraints conPlayerOneTF = new GridBagConstraints();
conPlayerOneTF.fill = GridBagConstraints.HORIZONTAL;
conPlayerOneTF.gridy = 1;
conPlayerOneTF.gridx = 0;
playerOneSetUp.add(playerOneTF, conPlayerOneTF);
JButton playerOneJColorChooser = new JButton("Player One Color");
GridBagConstraints conPlayerOneJColorChooser = new GridBagConstraints();
conPlayerOneJColorChooser.fill = GridBagConstraints.HORIZONTAL;
conPlayerOneJColorChooser.gridy = 2;
conPlayerOneJColorChooser.gridx = 0;
playerOneSetUp.add(playerOneJColorChooser, conPlayerOneJColorChooser);
newGamePanel.add(playerOneSetUp, conPlayerOneSetUp); //adding newGamePanel components
JPanel playerTwoSetUp = new JPanel(new GridBagLayout());
GridBagConstraints conPlayerTwoSetUp = new GridBagConstraints();
conPlayerTwoSetUp.fill = GridBagConstraints.BOTH;
conPlayerTwoSetUp.gridy = 1;
conPlayerTwoSetUp.gridx = 0;
JLabel playerTwoL = new JLabel("Player Two Name");
GridBagConstraints conPlayerTwoL = new GridBagConstraints();
conPlayerTwoL.fill = GridBagConstraints.HORIZONTAL;
conPlayerTwoL.gridy = 0;
conPlayerTwoL.gridx = 0;
playerTwoSetUp.add(playerTwoL, conPlayerTwoL);
playerTwoTF = new JTextField();
GridBagConstraints conPlayerTwoTF = new GridBagConstraints();
conPlayerTwoTF.fill = GridBagConstraints.HORIZONTAL;
conPlayerTwoTF.gridy = 1;
conPlayerTwoTF.gridx = 0;
playerTwoSetUp.add(playerTwoTF, conPlayerTwoTF);
JButton playerTwoJColorChooser = new JButton("Player Two Color");
GridBagConstraints conPlayerTwoJColorChooser = new GridBagConstraints();
conPlayerTwoJColorChooser.fill = GridBagConstraints.HORIZONTAL;
conPlayerTwoJColorChooser.gridy = 2;
conPlayerTwoJColorChooser.gridx = 0;
playerTwoSetUp.add(playerTwoJColorChooser, conPlayerTwoJColorChooser);
newGamePanel.add(playerTwoSetUp, conPlayerTwoSetUp); //adding newGamePanel components
JPanel options = new JPanel(new GridBagLayout());
GridBagConstraints conOptions = new GridBagConstraints();
conOptions.fill = GridBagConstraints.BOTH;
conOptions.gridy = 0;
conOptions.gridx = 1;
JLabel optionsL = new JLabel("Game Options");
GridBagConstraints conOptionsL = new GridBagConstraints();
conOptionsL.fill = GridBagConstraints.HORIZONTAL;
conOptionsL.gridy = 0;
conOptionsL.gridx = 0;
options.add(optionsL, conOptionsL);
unlimitedAmmoCB = new JCheckBox("Unlimited Ammunition");
GridBagConstraints conUnlimitedAmmoCB = new GridBagConstraints();
conUnlimitedAmmoCB.fill = GridBagConstraints.HORIZONTAL;
conUnlimitedAmmoCB.gridy = 1;
conUnlimitedAmmoCB.gridx = 0;
options.add(unlimitedAmmoCB, conUnlimitedAmmoCB);
unlimitedTimeCB = new JCheckBox("Unlimited Time");
GridBagConstraints conUnlimitedTimeCB = new GridBagConstraints();
conUnlimitedTimeCB.fill = GridBagConstraints.HORIZONTAL;
conUnlimitedTimeCB.gridy = 2;
conUnlimitedTimeCB.gridx = 0;
options.add(unlimitedTimeCB, conUnlimitedTimeCB);
newGamePanel.add(options, conOptions); //adding newGamePanel components
JButton startGameB = new JButton("START");
GridBagConstraints conStartGameB = new GridBagConstraints();
conStartGameB.fill = GridBagConstraints.BOTH;
conStartGameB.gridy = 1;
conStartGameB.gridx = 1;
newGamePanel.add(startGameB, conStartGameB); //adding newGamePanel components
add(newGamePanel, "newGamePanel"); //newGamePanel is added to higher level display JPanel
}
}
Tank Application
package Tanks;
import javax.swing.*;
import java.awt.*;
public class TankApplication extends JFrame{
public static void main (String args[]){
TankApplication GUI = new TankApplication();
}
public TankApplication(){
super("Tanks");
add(new TankDisplay(this));
setSize(800, 600);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
}
}
Tank Event
package Tanks;
import java.awt.*;
import java.awt.event.*;
import javax.swing.JColorChooser;
public class TankEvent implements ActionListener{
TankApplication game;
TankDisplay display;
public TankEvent(TankDisplay d, TankApplication g){ //I found this was necesarry because I didn't want to call the constructors of panels
display = d; //and frames. I'm not sure why that caused errors, but it does. And when I tried to
game = g; //create overloaded constructors for TankApplication and TankDisplay, their references
} //didn't have the information I needed. This is likely because I kept most of the components
//as local variables in the constructors, instead of creating variables in their respective classes, and using
public void actionPerformed(ActionEvent e){ //the constructors to modify them
CardLayout layOut = (CardLayout)(display.getLayout()); //<---Why do I need to do this?
switch(e.getActionCommand()){
case "New Game":
layOut.show(display, "newGamePanel");
game.pack(); //<<<---Root problem. Sometimes newGamePanel is packed, the JFrame is smaller, sometimes newGameaPanel is not packed. Seems random
game.setResizable(false); //for this JPanel only, I don't want to be able to resize the window. I will change this when the user flips
break; //to another JPanel
}
}
}
Robert seems to have asked a similar question, but didn't seem to get a satisfactory answer. Why do threads have anything to do with this?
You are not using CardLayout correctly.
When you use a CardLayout on a panel the preferred size of the panel is the size of the largest child panel added to the CardLayout.
Swapping from one panel to another will not alter the preferred size of panel and therefore the frame. So the pack() method will have no effect.
I suggest you don't worry about packing the frame. Just create the "menu panel" so that its components are centered. Then when you start the game all that changes is that you display the "game panel".

GUI, arranging buttons inside a panel

How to i display the buttons right?
heres my code:
import javax.swing.*;
import java.awt.*;
public class cal extends JFrame
{
private JLabel monthnym, monnym,tuesnym,wednym,thunym,frinym,satnym,sunnym;
private JButton b1,b2,b3,b4,b5,b6,b7,b8,b9,b10,b11,b12,b13,b14,b15,b16,b17,b18,
b19,b20,b21,b22,b23,b24,b25,b26,b27,b28,b29,b30;
private JPanel panel1, panel2, panel3,panel4;
public cal()
{
super("November");
Container c = getContentPane();
c.setLayout(new GridLayout(7,5));
panel1=new JPanel(new GridLayout(1,0));
monthnym=new JLabel("November 2013");
panel1.add(monthnym);
panel2=new JPanel(new GridLayout(1,7,2,2));
sunnym=new JLabel("SUN");
monnym=new JLabel("MON");
tuesnym=new JLabel("TUE");
wednym=new JLabel("WED");
thunym=new JLabel("THU");
frinym=new JLabel("FRI");
satnym=new JLabel("SAT");
panel2.add(sunnym);
panel2.add(monnym);
panel2.add(tuesnym);
panel2.add(wednym);
panel2.add(thunym);
panel2.add(frinym);
panel2.add(satnym);
panel3=new JPanel(new GridLayout(5,7,3,3));
b1=new JButton("1");
b2=new JButton("2");
b3=new JButton("3");
b4=new JButton("4");
b5=new JButton("5");
panel3.add(b1);
panel3.add(b2);
panel3.add(b3);
panel3.add(b4);
panel3.add(b5);
//panel4=new JPanel(new GridLayout(4,7,5,5));
c.add(panel1);
c.add(panel2);
c.add(panel3);
//c.add(panel4);
setSize(500,500);
show();
}
public static void main(String[] args) {
cal app = new cal();
}
}
i edit my code severwal times, but no luck.
i think theres something in the (x,y) but i nothing change.
and those buttons are 30, i redused it to 5 cause i get error posting this question
Essentially, GridLayout is reserving space for what it thinks it needs, but because the area it wants is larger then the area you've provided, it's squeezed every thing.
If I change the layout manager for the content pane from c.setLayout(new GridLayout(7, 5)); to c.setLayout(new BorderLayout()); I get...
My first recommendation is to use better layouts. You've already broken the code down into separate components, which is a good start, you can use different layout managers for each of these sections to generate a better layout.
You may need to consider placing you UI into a JScrollPane if it simply won't fit into a (reasonable) screen...
You should also use JFrame#pack to size the main frame instead of setSize where possible.
Take a look at A Visual Guide to Layout Managers for some ideas.
Next, I would suggest that you generate a custom component which maintains the basic content, so you can re-use.
I would also encourage you to take a look at Initial Threads and ensure that your UI is constructed within the context of the Event Dispatching Thread to prevent possible issues.
I would also encourage you to place your buttons into an array or List of some kind, instead of creating 30 named variables...IMHO
Try this :
c.setLayout(new GridLayout(3,5));
and
panel3=new JPanel(new GridLayout(1,7,1,1));
As recommended by #MadProgrammer try to use different LayoutManagers for panels. I change your code a little. I set GridBagLayout for your container, now it looks better.
public class Form extends JFrame {
private JLabel monthnym, monnym, tuesnym, wednym, thunym, frinym, satnym,
sunnym;
private JPanel panel1, panel2, panel3;
public Form() {
super("November");
Container c = getContentPane();
c.setLayout(new GridBagLayout());
panel1 = new JPanel(new GridLayout(1, 0));
monthnym = new JLabel("November 2013");
panel1.add(monthnym);
panel2 = new JPanel(new GridLayout(1, 0));
sunnym = new JLabel("SUN");
monnym = new JLabel("MON");
tuesnym = new JLabel("TUE");
wednym = new JLabel("WED");
thunym = new JLabel("THU");
frinym = new JLabel("FRI");
satnym = new JLabel("SAT");
panel2.add(sunnym);
panel2.add(monnym);
panel2.add(tuesnym);
panel2.add(wednym);
panel2.add(thunym);
panel2.add(frinym);
panel2.add(satnym);
panel3 = new JPanel(new GridLayout(5, 7));
for(int i =0;i<30;i++){
JButton b = new JButton(""+i);
panel3.add(b);
}
GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(5, 5, 5, 5);
gbc.fill = GridBagConstraints.BOTH;
gbc.gridy =0;
c.add(panel1,gbc);
gbc.gridy++;
c.add(panel2,gbc);
gbc.gridy++;
c.add(panel3,gbc);
pack();
setVisible(true);
}
public static void main(String[] args) {
Form app = new Form();
}
}
Also use pack() instead of setSize(), and setVisible(true) instead of deprecated show()

GridBagLayout within JScrollPane not resizing properly

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);
}
}

Categories

Resources