What settings should I use to resolve this GridBagLayout resizing issue? - java

I have been searching and trying ways to resolve the problems I encountered with GridBagLayout resizing but to no avail. The problems are:
I drag the bottom of the JDialog window down to make it taller; the search panel (above panel in the below screenshot) kept getting taller, just adding white space that it didn't need for its contents (I don't want this wasted space which takes height away from the scrolling table below it).
If I move the right side of the window to make it a bit narrower, the scroll panel becomes too short even though my screen and the window could have displayed its full height; a vertical scroll bar appears (I don't like the panels to scroll vertically, just horizontally.)
My JDialog that holds below components in the upper right portion uses below layout manager and constraints:
JPanel level 1 uses GridBagLayout Setting 1 (see below)
JScrollPane level 2 uses GridBagLayout Setting 1
JPanel level 3 uses GridBagLayout Setting 2
JPanel level 4 uses GridBagLayout Setting 2
JPanel level 5 uses GridBagLayout Setting 2
JPanel level 5 uses GridBagLayout Setting 2
GridBagLayout.GridBagConstraints (c)
Setting 1:
c.fill = GridBagConstraints.BOTH;
c.weightx = 99.0;
c.weighty = 99.0;
Setting 2:
c.fill = GridBagConstraints.NONE;
c.weightx = 1.0;
c.weighty = 1.0;
Originally, this is my JDialog if I don't use JScrollPane:
If I drag the window to make it bigger, the size of the JPanel (which was what I use before I used JScrollPane to make it scrollable horizontally) remains as it is. I want to achieve the same behavior, only that I want to make it horizontally scrollable.
What layout manager should I use to resolve this resizing problem? If I have to really use GridBagLayout, what constraints/settings should I use? I would highly appreciate any suggestion. Thank you!
UPDATE 1 ------------------------------------------------------
Kindly check sample code scenario below. Both scrollable panels (RED and BLUE) use GridBagConstraints.BOTH, weightx and weighty equal to 99.0. I want the red panel to have a height that is enough to contain the text field. I also want that when the dialog is dragged down to make the window bigger, the red panel's height remains the same. Please note that in the actual screen, both panels' number of contents may change (add/minus buttons exist), hence, setting of minimum panel size (for resizing) won't help. Kindly advise how I should go about this case. Thanks!
package cfr.view.search;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JDialog;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.border.EmptyBorder;
public class GBLSample extends JDialog {
private JPanel contentPane;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
GBLSample frame = new GBLSample();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public GBLSample() {
setBounds(100, 100, 350, 400);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
GridBagLayout gbl_contentPane = new GridBagLayout();
contentPane.setLayout(gbl_contentPane);
// RED PANEL ------------------------------------------------
JScrollPane sp1 = new JScrollPane();
GridBagConstraints gbc1 = new GridBagConstraints();
gbc1.fill = GridBagConstraints.BOTH;
gbc1.weightx = 99.0;
gbc1.weighty = 99.0;
contentPane.add(sp1, gbc1);
JPanel redPanel = new JPanel();
redPanel.setBackground(Color.RED);
JTextField field = new JTextField(20);
GridBagConstraints gbc2 = new GridBagConstraints();
gbc2.anchor = GridBagConstraints.PAGE_START;
gbc2.fill = GridBagConstraints.NONE;
contentPane.add(field, gbc2);
redPanel.add(field);
sp1.setViewportView(redPanel);
// BLUE PANEL ------------------------------------------------
JScrollPane sp2 = new JScrollPane();
GridBagConstraints gbc3 = new GridBagConstraints();
gbc3.fill = GridBagConstraints.BOTH;
gbc3.gridx = 0;
gbc3.gridy = 1;
gbc3.weightx = 99.0;
gbc3.weighty = 99.0;
contentPane.add(sp2, gbc3);
JPanel bluePanel = new JPanel();
bluePanel.setBackground(Color.BLUE);
sp2.setViewportView(bluePanel);
}
}
UPDATE 2 ------------------------------------------------------
Still have the same problem with the JPanel's sizing as #1 above.
Problem 1

try this code:
package test;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.border.EmptyBorder;
public class GridBagLayoutSample extends JFrame {
private JPanel contentPane;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
GridBagLayoutSample frame = new GridBagLayoutSample();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public GridBagLayoutSample() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 450, 300);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
GridBagLayout gbl_contentPane = new GridBagLayout();
gbl_contentPane.columnWidths = new int[]{0, 0};
gbl_contentPane.rowHeights = new int[]{50, 0, 0};
//the 1.0 value in columnWeights let redPanel and scrollPane (that contain bleuPanel) grow horizontally
//the 1.0 value is in the first index so it affect the first column
//you still need to use a valid value for gbc_redPanel.fill and gbc_scrollPane.fill;
gbl_contentPane.columnWeights = new double[]{1.0, Double.MIN_VALUE};
//the 0.0 value of rowWeights => components in first row will not grow
//the 0.0 value of rowWeights => components in second row will grow
gbl_contentPane.rowWeights = new double[]{0.0, 1.0, Double.MIN_VALUE};
contentPane.setLayout(gbl_contentPane);
JPanel redPanel = new JPanel();
redPanel.setBackground(Color.RED);
GridBagConstraints gbc_redPanel = new GridBagConstraints();
gbc_redPanel.insets = new Insets(0, 0, 5, 0);
gbc_redPanel.fill = GridBagConstraints.BOTH;
gbc_redPanel.gridx = 0;
gbc_redPanel.gridy = 0;
contentPane.add(redPanel, gbc_redPanel);
JScrollPane scrollPane = new JScrollPane();
GridBagConstraints gbc_scrollPane = new GridBagConstraints();
gbc_scrollPane.fill = GridBagConstraints.BOTH;
gbc_scrollPane.gridx = 0;
gbc_scrollPane.gridy = 1;
contentPane.add(scrollPane, gbc_scrollPane);
JPanel bleuPanel = new JPanel();
bleuPanel.setBackground(Color.BLUE);
//scrollpane work with the preferred size of the component in the viewportView
//try to change this values
bleuPanel.setPreferredSize(new Dimension(400, 400));
scrollPane.setViewportView(bleuPanel);
}
}
add this to your code
gbl_contentPane.rowHeights = new int[]{40, 0, 0};
gbl_contentPane.rowWeights = new double[]{0.0,0.0, 1.0, Double.MIN_VALUE};
gbc1.gridx = 0;
gbc1.gridy = 0;
and remove this
gbc1.weightx = 99.0;
gbc1.weighty = 99.0;

Maybe a GridBagLayout might not be suited for your current UI, and a BorderLayout would work better? Put the red panel in BorderLayout.NORTH and put the blue panel in BorderLayout.CENTER. Components in the CENTER region will grow and shrink as you resize your dialog, and your red panel's preferredSize will be respected as you +/- items.

I have been searching and trying ways to resolve the problems I encountered with GridBagLayout resizing but to no avail.
Welcome to GridBagLayout.
First thing to note is that in
JPanel redPanel = new JPanel();
redPanel.setBackground(Color.RED);
JTextField field = new JTextField(20);
// GridBagConstraints gbc2 = new GridBagConstraints();
// gbc2.anchor = GridBagConstraints.PAGE_START;
// gbc2.fill = GridBagConstraints.NONE;
// contentPane.add(field, gbc2);
redPanel.add(field);
sp1.setViewportView(redPanel);
You are adding the text field to the content pane and then adding it again to the panel, which overrides your previous assignment (a component can only belong to one container). I commented out the lines which do nothing. The choice for how to lay out the text field in the red panel is completely different than the choice of how to lay out the red panel in the content pane.
I want the red panel to have a height that is enough to contain the text field.
That is taken care of by the layout manager. However, if you resize the window manually so that the panel will not have enough space, then scrollbars will appear provided that the panel is in a JScrollPane. You can try to #Override the getMinimumSize of the panel to its getPreferredSize, but not all layout managers respect it, I believe.
Regardless, I don't see why you need the scroll pane for the red panel at all.
I also want that when the dialog is dragged down to make the window bigger, the red panel's height remains the same.
Then you should set its weighty to 0.
Note: don't use underscores (_) in non-final variable names in accordance with the Java naming conventions (gbl_contentPane should be gblContentPane).
Edit
Here is an example of of dynamically changing the allocated size for the redPanel. I use BorderLayout for the content pane (also suggested by Dan O) for simplicity.
public class GBLSample extends JDialog {
private JPanel contentPane;
private JScrollPane redSP = new JScrollPane(new RedPanel());
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
GBLSample frame = new GBLSample();
frame.setVisible(true);
});
}
private class RedPanel extends JPanel {
RedPanel() {
setLayout(new GridBagLayout());
setBackground(Color.RED);
GridBagConstraints c = new GridBagConstraints();
c.anchor = GridBagConstraints.FIRST_LINE_START;
add(new JTextField(10), c);
c.weightx = 1;
c.gridx = 1;
add(new JComboBox<>(), c);
c.weightx = 0;
c.gridx = 0;
add(new JComboBox<>(), c);
c.gridx = 1;
add(new JComboBox<>(), c);
c.weighty = 1;
c.gridx = 0;
c.gridy = 2;
add(new JButton("SSSS"), c);
}
#Override
public Dimension getPreferredSize() {
Dimension dim = super.getPreferredSize();
JScrollBar sb = redSP.getHorizontalScrollBar();
if (!sb.isShowing())
return dim;
return new Dimension(dim.width, dim.height + sb.getHeight());
}
}
public GBLSample() {
setBounds(100, 100, 350, 400);
contentPane = new JPanel(new BorderLayout());
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
// RED PANEL ------------------------------------------------
redSP.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER);
contentPane.add(redSP, BorderLayout.PAGE_START);
// BLUE PANEL ------------------------------------------------
JPanel bluePanel = new JPanel();
bluePanel.setBackground(Color.BLUE);
contentPane.add(new JScrollPane(bluePanel));
}
}
The idea is to add all extra space at the bottom of the panel by giving all the weight to a component on the bottom (and similarly can be done for the x axis with a right-most component). When the scrollbar is shown, the panel recalculates its height and adds the scrollbar's height to to itself (to the bottom most component), then the scrollbar does not hide anything.

Unfortunately, there was a bug in the system's overridden JPanel.getMinimumSize() that was causing my search panel to get squished out of existence. I was able to find a fix for it already without changing any setting with the system's customized layout manager. Still, thanks a lot for all your answers and help.

Related

GridBagLayout - Trouble placing components without anchor

I'm making an assignment planner program. For the containers (the assignments), I want to place certain components into certain places. However. I can only seem to move components around by using anchor. It seems as if my gridx and gridy do nothing. Could anyone point out my problem and possibly offer some suggestions. My code and a picture of the intended final result are provided below.
Code:
import javax.swing.*;
import java.awt.*;
import static java.awt.GridBagConstraints.*;
//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;
private int scrollPaneValue = 110;
//ArrayList<JFrame> frame = new ArrayList<>();
public MyWindow()
{
frame.setTitle("Assignment Planner");
this.contents();
}
private void contents()//make a border above each panel stating "TO-DO" or "COMPLETED"
{//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, 110));
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(Box.createRigidArea(new Dimension(0,1)));
toDoList.add(assignment());
scrollPaneValue += 110; //add these 2 lines of code, beginning after the first two containers to increase jscrollpane
toDoList.setPreferredSize(new Dimension(250, scrollPaneValue));
//toDoList.revalidate(); may not even need
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 cDefault = new GridBagConstraints();
cDefault.weightx = 0.5;
cDefault.insets = new Insets(5,5,5,5);
JCheckBox cb;
JLabel dueDate, description;
JButton edit;
cb = new JCheckBox();
GridBagConstraints cCb = new GridBagConstraints();
cCb.weightx = 0.5;
cCb.weighty = 1;
cCb.fill = GridBagConstraints.NONE;//originally none
cCb.gridx = 0;
cCb.gridy = 0;
//cCb.gridwidth = 1;
//cCb.gridheight = 1;
cCb.anchor = FIRST_LINE_START;//may not need, plus needs static import
cCb.insets = cDefault.insets;
cb.setBackground(Color.RED);
container.add(cb, cCb);
dueDate = new JLabel("Due Date");
GridBagConstraints cDueDate = new GridBagConstraints();
cDueDate.gridx = 1;
cDueDate.gridy = 0;
cDueDate.gridwidth = 2;
//cDueDate.fill = GridBagConstraints.HORIZONTAL;
cDueDate.anchor = PAGE_START;
dueDate.setBackground(Color.BLUE);
//cDueDate.anchor = FIRST_LINE_START;
container.add(dueDate, cDueDate);
edit = new JButton("Edit");
GridBagConstraints e = new GridBagConstraints();
e.gridx = 4;
e.gridy = 0;
e.anchor = GridBagConstraints.FIRST_LINE_END;
e.insets = cDefault.insets;
edit.setBackground(Color.GREEN);
container.add(edit, e);
description = new JLabel("Description...");
GridBagConstraints d = new GridBagConstraints();
d.gridx = 1;
d.gridy = 3;
d.gridwidth = 3;
d.fill = GridBagConstraints.HORIZONTAL;
description.setBackground(Color.YELLOW);
container.add(description, d);
container.setBackground(Color.LIGHT_GRAY);//does no fill area behind checkbox
return container;
}
}
What I want the container to look like:
This just concerns my lack of knowledge with GridBagLayout.
Start with the section from the Swing tutorial on How to Use GridBagLayout for working examples and an explanation of all the constraints.
A few things about the code:
//container.setMaximumSize(new Dimension(500,100));
Don't set a maximum size. The layout manager will determine the size of the panel.
//cCb.weightx = 0.5;
//cCb.weighty = 1;
The above code assigns all the extra space of the panel to the check box, since it is the only component with a weightx/y constraint. I doubt you want that. Try commenting out those statements to see what happens.
dueDate.setOpaque(true);
dueDate.setBackground(Color.BLUE);
Yes, that is a good idea to set a background to see the actual size of the component. Problem is a JLabel is transparent by default so the background is never painted. You need need to make your labels opaque if you want to see the background. Another approach to help with debugging is to add LineBorder to the label, then you don't need to worry about transparency.
//e.gridx = 4;
e.gridx = 3;
Be careful with the grid value. You can't just use an value. The first component has a width of 1 and the second a width of 2, so the this component should start at 3.
I can only seem to move components around by using anchor
Actually, I don't this the anchor is doing anything. As I understand it, the anchor only has meaning when the component size is smaller than the grid size. In your original code, only the check box used weightx/y values, so that is the only component where this is true.
The GridBagLayout is one of the most complicated (and flexible) layout manager to use, so yes it takes practice to learn how to use it. Reread the tutorial and play with the constraints.

JInternal Frame Over JPanel

I need some help in JInternalFrame within JPanel's Area.I have a JFrame which contains
JPanel added to its ContentPane.JFrame Contains Menu when i click one of its Menu item i
need JInternal Frame to be added on top of the contentpane.The Code i have given so far,
JDesktopPane desktop = new JDesktopPane();
desktop.setLayout(new BorderLayout());
JPanel topPanel = new JPanel();
GridBagLayout gbl_contentPane = new GridBagLayout();
gbl_contentPane.columnWidths = new int[] { 0, 0, 0, 0 };
gbl_contentPane.rowHeights = new int[] { 0, 0, 0, 0 };
gbl_contentPane.columnWeights = new double[] { 1.0, 6.0, 1.0,
Double.MIN_VALUE };
gbl_contentPane.rowWeights = new double[] { 0.0, 8.0, 0.0,
Double.MIN_VALUE };
topPanel.setLayout(gbl_contentPane);
JPanel left = new JPanel();
GridBagConstraints gbc_left = new GridBagConstraints();
gbc_left.insets = new Insets(0, 0, 5, 5);
gbc_left.fill = GridBagConstraints.BOTH;
gbc_left.gridx = 0;
gbc_left.gridy = 1;
topPanel.add(left, gbc_left);
JPanel middle = new JPanel();
GridBagLayout gbl_middle = new GridBagLayout();
gbl_middle.columnWeights = new double[] { 1.0 };
middle.setLayout(gbl_middle);
GridBagConstraints gbc_middle = new GridBagConstraints();
gbc_middle.insets = new Insets(0, 0, 5, 5);
gbc_middle.fill = GridBagConstraints.BOTH;
gbc_middle.gridx = 1;
gbc_middle.gridy = 1;
topPanel.add(middle, gbc_middle);
GridBagConstraints gbc = new GridBagConstraints();
JPanel panel1 = new JPanel();
Border eBorder = BorderFactory.createEtchedBorder();
panel1.setBorder(BorderFactory.createTitledBorder(eBorder, "70pct"));
gbc.gridx = 0;
gbc.gridy = 0;
gbc.fill = GridBagConstraints.BOTH;
gbc.weightx = gbc.weighty = 30;
middle.add(panel1, gbc);
panel1.setLayout(new MigLayout("", "[944.00,grow][353.00]",
"[6.00][128.00,grow][]"));
/*lblHeader = new JLabel(
"<html>Indira Institute of Technology<br>Tatabad<br>Karpagam Complex Stop<br>Coimbatre</html>");
lblHeader.setIcon(new ImageIcon(
"C:\\Users\\Prakash\\Desktop\\images.jpg"));
panel1.add(lblHeader, "cell 0 1 2 1,alignx center,aligny center");*/
JPanel panel2 = new JPanel();
gbc = new GridBagConstraints();
panel2.setBorder(BorderFactory.createTitledBorder(eBorder, "30pct"));
gbc.gridy = 1;
gbc.gridwidth = gbc.gridheight = 1;
gbc.fill = GridBagConstraints.BOTH;
gbc.anchor = GridBagConstraints.NORTHWEST;
gbc.weightx = gbc.weighty = 70;
gbc.insets = new Insets(2, 2, 2, 2);
middle.add(panel2, gbc);
panel2.setLayout(new MigLayout(
"",
"[30px][69.00px][144.00][68.00][][159.00px][59.00px][65px][28.00][]",
"[20px:n,grow 50,shrink 50][20px:n,grow 50,shrink 50][20px:n,grow 50,shrink 50][20px:n,grow 50,shrink 50][30.00][48.00:n,grow 50,shrink 50]"));
getContentPane.add(topPanel);
I have never used the DesktopPane in this(I don't know how to make use of this in this situation) And The Screen So far is as follows,
Now I need the JInternalFrame to be added for the Previous Screen as Follows,
I am aware that i can only be able to add a JInternalFrame to the DesktopPane.But i
Already Filled my ContentPane with JPanel to show its content.How can i achieve Jinternal
Frame to be added in this JFrame.Kindly give your valuable suggestions.
Not really the right direction. You original panel is under the control of layout manager, this means that when you add the JInternalFrame to it, the layout manager wants to try and layout it out.
Generally speaking, a JInternalFrame wants to reside in a container which is unmanaged, allowing it to be positioned and sized independently of the content.
A possible solution might be to take advantage of the glass pane for the JInternalFrame instead, for more details see How to Use Root Panes
Another solution might be to use a JLayeredPane. Basically, you would start by setting the layout manager of the JLayeredPane to something link BorderLayout add the first panel to it and then add a second, transparent pane, with no layout, above it. You would add the JInternalFrames to this second panel.
See How to Use Layered Panes for more details
The question that jumps out at me though is...why? Why wouldn't you just use some kind of dialog instead? See How to Make Dialogs for more details
What is it what you really want?
You wrote you already have your content pane added to your frame. JDesktopPane has to have its own space reserved. If you don't have or you don't want to reserve space for the internal frames in your main frame, then maybe you don't even want it to be part of the main frame. In this case you might want to use child JDialogs instead of JInternalFrames.
So either add your JDesktopPane to your main frame (having its space reserved) or use child JDialogs which can be modal or not and can overlap any part of the main frame. JInternalFrames are only visible in the area of the JDesktopPane while child JDialogs can "float" over your main frame.
Check out this Oracle documentation: How to Use Internal Frames
And How to Make Dialogs.

How to make a JPanel use the scrollbars to fit in large J components?

I have this problem where the JPanel (contentPane) re-sizes (testLabel) GUI components to be really small whenever they are too big to fit in the panel. I have added scrollbars to the JPanel but the components still re-size instead of using the scrollbars. Here is my class where I use the JPanel with scrollbars.
package marsPackage;
import java.awt.*;
import javax.swing.*;
public class DashTab{
private JLabel testLabel; //test label
private JLabel testLabel2;
private JLabel testLabel3;
private JLabel testLabel4;
private JPanel dashPanel; //Panel that holds the JTabbedPane tab
private JPanel contentPane; // Panel that holds all GUI components
private JScrollPane scrollPane; // Scrollpane used on contentPane
/*
* Constructor
* All of your GUI components should be added to
* contentPane using the gridBagLayout.
*/
public DashTab(){
//Creating the dashpanel that holds everything
dashPanel = new JPanel();
dashPanel.setBackground(Color.WHITE);
//Creating the contentPane that holds all GUI components and
//uses vertical/horizontal sidebards as needed
contentPane = new JPanel();
contentPane.setBackground(Color.WHITE);
//Giving the contentPane the GridBagLayout
contentPane.setLayout(new GridBagLayout());
GridBagConstraints g = new GridBagConstraints();
contentPane.setPreferredSize(new Dimension(857, 725));
//Adding scrollPane to Content Pane and adding those two to dashPanel
scrollPane = new JScrollPane(contentPane);
scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
scrollPane.setBackground(Color.WHITE);
dashPanel.add(scrollPane);
/*
* You may begin adding your GUI components from this point forward.
* Remember to only use GridBagLayout with GridBagConstraints using the
* g variable.
*/
testLabel = new JLabel("Testing Here 1");
testLabel.setPreferredSize(new Dimension(500, 500));
testLabel.setBorder(BorderFactory.createMatteBorder(2, 2, 2, 2, Color.gray));
g.gridx = 0;
g.gridy = 0;
contentPane.add(testLabel, g);
testLabel2 = new JLabel("Testing Here 2");
testLabel2.setPreferredSize(new Dimension(250, 200));
testLabel2.setBorder(BorderFactory.createMatteBorder(2, 2, 2, 2, Color.gray));
g.gridx = 1;
g.gridy = 0;
contentPane.add(testLabel2, g);
testLabel3 = new JLabel("Testing Here 3");
testLabel3.setPreferredSize(new Dimension(200, 200));
testLabel3.setBorder(BorderFactory.createMatteBorder(2, 2, 2, 2, Color.gray));
g.gridx = 1;
g.gridy = 1;
contentPane.add(testLabel3, g);
testLabel4 = new JLabel("Testing Here 4");
testLabel4.setPreferredSize(new Dimension(200, 200));
testLabel4.setBorder(BorderFactory.createMatteBorder(2, 2, 2, 2, Color.gray));
g.gridx = 2;
g.gridy = 2;
contentPane.add(testLabel4, g);
}
/**
* The getDashTab method returns a DashTab object.
* #return a DashTab panel object.
*/
public JPanel getDashTab(){
return dashPanel;
}
}
This is how the above code looks like:
Whenever I remove contentPane.setPreferredSize(new Dimension(857, 725)); the panel just stretches out and complete ignores the scrollbars making it look like:
contentPane.setPreferredSize(new Dimension(857, 725));
Don't use the setPreferredSize() method to set the size. That is the job of the layout manager, in this case, the GridBagLayout to determine the size of the panel.
Scrollbars will appear automatically when the preferred size of the panel is greater than the size of the scrollpane.
GUI components to be really small whenever they are too big to fit in the panel.
The GridBagLayout will try to respect the preferred size of the component. If the preferred size is greater than the size of the panel, then the components "minimum size" will be used. In the case of a JLabel, the minimum size is the space needed to entirely display the text.
Once again, don't try to use the setPreferedSize() method.

JScrollPane can resize smaller, but JTextArea does not

I have a window containing a JScrollArea, which contains a JPanel which contains a JTextArea. When I resize the window to make it larger, the layout updates perfectly, but if I make the window smaller, the JPanel does not shrink its contents. I attempted to add a ComponentListener on the JScrollArea to resize the JPanel based on the new size of the viewport, but this seems to defeat the purpose of the vertical scroll bar.
UPDATE: The idea here is that the JScrollArea will contain a JPanel (since it can only contain one component for its viewport), and within that JPanel I will be adding multiple JPanels containing components that describe processes that are running to the user. Since there could be any number of these processes running, I need to have some kind of scroll bar functionality available. Hence the component hierarchy I'm using below.
The desired behavior here is that the window can be resized larger or smaller and the text area will wrap its contents accordingly, and a vertical scroll bar will appear if the contents of the JPanel are larger vertically than the window. Any suggestions?
public class TestWindow extends JFrame {
JPanel scrollContentPanel;
JScrollPane scrollPane;
public TestWindow() {
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
JPanel mainPanel = new JPanel();
this.setContentPane(mainPanel);
GridBagLayout mainPanelLayout = new GridBagLayout();
mainPanel.setLayout(mainPanelLayout);
scrollContentPanel = new JPanel();
scrollPane = new JScrollPane();
scrollPane.setViewportView(scrollContentPanel);
scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
GridBagLayout scrollContentLayout = new GridBagLayout();
scrollContentPanel.setLayout(scrollContentLayout);
JPanel contentEntry = new JPanel();
GridBagConstraints contentEntryConstraints = new GridBagConstraints();
contentEntryConstraints.weightx = 1.0;
contentEntryConstraints.insets = new Insets(3, 3, 5, 3);
contentEntryConstraints.fill = GridBagConstraints.BOTH;
contentEntryConstraints.gridx = 0;
contentEntryConstraints.gridy = 1;
scrollContentPanel.add(contentEntry, contentEntryConstraints);
GridBagLayout contentEntryLayout = new GridBagLayout();
contentEntry.setLayout(contentEntryLayout);
JTextArea descTextArea = new JTextArea();
descTextArea.setEditable(false);
descTextArea.setFont(new Font("Dialog", Font.PLAIN, 11));
descTextArea.setText("This is a description of an arbitrary unspecified length that may easily span multiple lines without any breaks in-between. Therefore it is necessary that the description automatically wrap as appropriate.");
descTextArea.setLineWrap(true);
descTextArea.setWrapStyleWord(true);
GridBagConstraints descTextAreaConstraints = new GridBagConstraints();
descTextAreaConstraints.weightx = 1.0;
descTextAreaConstraints.weighty = 1.0;
descTextAreaConstraints.insets = new Insets(0, 0, 3, 0);
descTextAreaConstraints.fill = GridBagConstraints.BOTH;
descTextAreaConstraints.gridx = 0;
descTextAreaConstraints.gridy = 1;
descTextAreaConstraints.gridwidth = 2;
contentEntry.add(descTextArea, descTextAreaConstraints);
GridBagConstraints scrollPaneConstraints = new GridBagConstraints();
scrollPaneConstraints.insets = new Insets(0, 0, 5, 0);
scrollPaneConstraints.weightx = 1.0;
scrollPaneConstraints.weighty = 1.0;
scrollPaneConstraints.fill = GridBagConstraints.BOTH;
scrollPaneConstraints.gridx = 0;
scrollPaneConstraints.gridy = 0;
mainPanel.add(scrollPane, scrollPaneConstraints);
scrollPane.addComponentListener(new ComponentAdapter() {
#Override
public void componentResized(ComponentEvent evt) {
super.componentResized(evt);
scrollContentPanel.setPreferredSize(scrollPane.getViewportBorderBounds().getSize());
scrollContentPanel.validate();
}
});
pack();
}
public static void main(String[] args) {
TestWindow wnd = new TestWindow();
wnd.setVisible(true);
}
}
JTextArea should be placed directly into the JScrollPane, as long as that is the component your are trying to scroll. If there are other items you want to scroll with it (and hence the intermediate JPanel), then you might want to consider making that JPanel implement Scrollable so that the JScrollPane knows what to do with it. JTextArea implements Scrollable, which is why it works with JScrollPane out of the box.
no idea about your goal without detailed description, explanation
JTextArea should be placed in JScrollPane
set intial setPreferredSize for JTextArea, e.g. JTextArea(5, 10)
you are put three JPanels (is there reason ??? for this components hierarchy) one to JScrollPane, JTextArea is placed directly into JPanel instead of to the JScrollPane
then usage of ComponentListener is useless and contraproductive

How does GridBagLayout determine size of container

I am using a JDialog with GridBagLayout. Since this layout determines the container and component size automatically, I have not used setSize on anything. However, when the GUI is drawn, it seems to be stretching the container unnecessarily.
Why does GridBagLayout not size the container to "just as much as needed"? Basically I want the dialog size to be just as big as the table inside. Here is the code snippet:
public class GridBagLayoutTester
{
public static void main(String[] args)
{
JDialog mDialog = new JDialog();
JPanel panel1 = new JPanel();
panel1.setLayout(new GridBagLayout());
// Create a table to be added to the panel
JTable table = new JTable(4,4);
JScrollPane scrollpane = new JScrollPane(table);
scrollpane.setBorder(BorderFactory.createLineBorder(Color.ORANGE, 5));
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = gbc.gridy = 0;
gbc.fill = GridBagConstraints.NONE;
gbc.anchor = GridBagConstraints.FIRST_LINE_START;
// Add table to the panel
panel1.add(scrollpane, gbc);
mDialog.add(panel1, BorderLayout.CENTER);
// Display the window.
mDialog.pack();
mDialog.setVisible(true);
}
}
You have to set the preferred size of components when the default sizing isn't what you want.
Change your program to add these lines:
// Display the window.
mDialog.pack();
Dimension d = table.getPreferredSize();
d.width += 16;
d.height += 10;
scrollpane.setPreferredSize(d);
mDialog.pack();
mDialog.setVisible(true);
The additional width of 16 accommodates the border and vertical scroll bar.
The additional height of 10 accommodates the border.

Categories

Resources