How to get a GridBagLayout to arrange column widths? - java

Here is a pretty simple layout (code included) where non-uniform column sizes could improve packing.
Is there a way, using a single GridBagLayout, to get the components to fit together nicely?
I thought that using a width of 3 for the top two components, then a width of 5 & 1 for the next two rows would influence the alignment, but I cannot get it to stay flush. My current solution (not included) is to create a sub panel with the red and green panels.
import javax.swing.*;
import java.awt.*;
public class GridBagWrong{
public static void main(String[] args){
JPanel content = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
//create five panels to layout.
JPanel a = new JPanel();
a.setPreferredSize( new Dimension(300, 30) );
a.setBorder( BorderFactory.createLineBorder(Color.BLUE) );
JPanel b = new JPanel();
b.setPreferredSize( new Dimension(300, 30) );
b.setBorder( BorderFactory.createLineBorder(Color.BLUE) );
JPanel c = new JPanel();
c.setPreferredSize( new Dimension(500, 30) );
c.setBorder( BorderFactory.createLineBorder(Color.GREEN) );
JPanel d = new JPanel();
d.setPreferredSize( new Dimension(500, 30) );
d.setBorder( BorderFactory.createLineBorder(Color.GREEN) );
JPanel e = new JPanel();
e.setPreferredSize( new Dimension(100, 60) );
e.setBorder( BorderFactory.createLineBorder(Color.RED) );
//place them in a gridbaglayout.
gbc.gridwidth = 3;
content.add(a, gbc);
gbc.gridx = 3;
content.add(b, gbc);
gbc.gridx = 0;
gbc.gridy = 1;
gbc.gridwidth = 5;
content.add(c, gbc);
gbc.gridy = 2;
content.add(d, gbc);
gbc.gridy = 1;
gbc.gridx = 5;
gbc.gridheight = 2;
gbc.gridwidth = 1;
content.add(e, gbc);
JFrame frame = new JFrame("test");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setContentPane( content );
frame.pack();
frame.setVisible(true);
}
}

Following up on my comment from above you can use:
//JPanel content = new JPanel(new GridBagLayout());
GridBagLayout gbl = new GridBagLayout();
int[] columns = new int[6];
Arrays.fill(columns, 100);
gbl.columnWidths = columns;
JPanel content = new JPanel(gbl);
The above code states each of the 6 columns will have a minimum width of 100.
If a component is added to a column with gridwidth = 1, then the preferred size of that component will be used as the width of the column.
So now when you specify gridwidth = 3 it has a meaning because the layout can use either the width of a component added to the columnn or the minimum width to determine the actual size of the component.

For some reason GridBagLayout is adding addition space to it's calculations, but I'm not sure why. At first I thought it was the LineBorder, but when I modified your code to remove the border, it still didn't work...
I don't know where the extra spacing on the right is coming from (it's probably really obvious, but I can't see it)
Sooo, this is one of those moments where I "flip the table" and "rage quite" and instead, "hack it"
Since there seems to be a disconnect between the first and second row, for some reason, I combined the two panels from the first row into a single panel and got rid of all the gridwidths (more or less)
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
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());
GridBagConstraints gbc = new GridBagConstraints();
//create five panels to layout.
JPanel a = new LayoutPane();
a.setForeground(Color.BLUE);
a.setPreferredSize(new Dimension(300, 30));
JPanel b = new LayoutPane();
b.setPreferredSize(new Dimension(300, 30));
b.setForeground(Color.BLUE);
JPanel c = new LayoutPane();
c.setPreferredSize(new Dimension(500, 30));
c.setForeground(Color.GREEN);
JPanel d = new LayoutPane();
d.setPreferredSize(new Dimension(500, 30));
d.setForeground(Color.GREEN);
JPanel e = new LayoutPane();
e.setPreferredSize(new Dimension(100, 60));
e.setForeground(Color.RED);
JPanel topPane = new JPanel(new GridBagLayout());
//place them in a gridbaglayout.
gbc.gridx = 0;
gbc.gridy = 0;
gbc.fill = GridBagConstraints.HORIZONTAL;
topPane.add(a, gbc);
gbc.gridx++;
topPane.add(b, gbc);
gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.gridx = 0;
gbc.gridy = 0;
gbc.fill = GridBagConstraints.HORIZONTAL;
add(topPane, gbc);
gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 1;
gbc.anchor = GridBagConstraints.WEST;
add(c, gbc);
gbc.gridy = 2;
add(d, gbc);
gbc = new GridBagConstraints();
gbc.gridy = 1;
gbc.gridx++;
gbc.gridheight = 2;
gbc.anchor = GridBagConstraints.EAST;
add(e, gbc);
}
}
public class LayoutPane extends JPanel {
public LayoutPane() {
setOpaque(false);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(getForeground());
g2d.drawRect(0, 0, getWidth() - 1, getHeight() - 1);
String text = getWidth() + "x" + getHeight();
FontMetrics fm = g2d.getFontMetrics();
int x = (getWidth() - fm.stringWidth(text)) / 2;
int y = ((getHeight() - fm.getHeight()) / 2) + fm.getAscent();
g2d.drawString(text, x, y);
g2d.dispose();
}
}
}

Related

JPanels in GridLayout in JavaSwing

everyone. I would like to have custom JPanels ( I prefer absolute position layout for my use) in GridLayout. GridLayout is in ScrollPane.
public class App extends JFrame {
public App() {
super("bamlOperator");
JPanel panel = new JPanel(new GridLayout(0, 1));
JScrollPane scrollPane = new JScrollPane(panel, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
getContentPane().add(scrollPane, BorderLayout.CENTER);
setExtendedState(JFrame.MAXIMIZED_BOTH);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
panel.add(new MyCustomPanel());
panel.add(new MyCustomPanel());
panel.add(new MyCustomPanel());
panel.add(new MyCustomPanel());
panel.add(new MyCustomPanel());
panel.add(new MyCustomPanel());
pack();
setVisible(true);
}
public static void main(String[] args) {
new App();
}
}
And MyPanel :
public class MyCustomPanel extends JPanel {
private JLabel aaa = new JLabel("aaa:");
private JLabel bbb = new JLabel("bbb");
private JLabel ccc = new JLabel("ccc:");
public MyCustomPanel() {
setPreferredSize(new Dimension(100,100));
JPanel amlPanel = new JPanel();
amlPanel.setLayout(null);
amlPanel.setBounds(0,0,100,100);
aaa.setBounds(10,20,30,40);
amlPanel.add(aaa);
bbb.setBounds(20,30,40,50);
amlPanel.add(bbb);
ccc.setBounds(30,40,50,60);
amlPanel.add(ccc);
add(amlPanel);
}
}
But it doesnt work.
I said, I prefer absolute position layout but I know It is bad practice. I can use another but I need JPanel something like this :
Project of JPanel
So, your fundamental problem is you're mixing absolute layouts with layout managers - the problem is MyCustomPanel isn't providing any sizing hints which the layout manager can use to make better decisions about how best to layout your component. So, if you really want to use absolute layouts, you're going to have to do ALL the work that the layout management API would have done for you
Can you tell me which layout manager will be the best for my use?
All of them. Don't get fixated on a single layout manager achieving everything your want, instead, combine them together to produce the results you're after.
I don't have your "exact" requirements, but I was able to achieve this by using BorderLayout and GridBagLayout
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.image.BufferedImage;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;
public class Test extends JFrame {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new MainPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class MainPane extends JPanel {
public MainPane() {
// You could use a GridLayout, but GridBagLayout will
// honour the preferred sizs of each component
setLayout(new GridBagLayout());
setBorder(new EmptyBorder(10, 10, 10, 10));
GridBagConstraints gbc = new GridBagConstraints();
add(new LeftPane(), gbc);
add(new MiddleLeftPane(), gbc);
add(new MiddlePane(), gbc);
add(new RightPane(), gbc);
}
}
public class LeftPane extends JPanel {
public LeftPane() {
setLayout(new GridBagLayout());
JPanel main = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(4, 4, 4, 4);
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.weightx = 1;
for (int index = 0; index < 6; index++) {
if (index % 2 == 0) {
gbc.anchor = GridBagConstraints.LINE_START;
} else {
gbc.anchor = GridBagConstraints.LINE_END;
}
main.add(new JLabel("Label"), gbc);
}
gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.weightx = 1;
gbc.weighty = 1;
gbc.fill = GridBagConstraints.BOTH;
add(main, gbc);
gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.weightx = 1;
add(new JButton("Button"));
}
}
public class MiddleLeftPane extends JPanel {
public MiddleLeftPane() {
setLayout(new BorderLayout());
BufferedImage img = new BufferedImage(200, 200, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = img.createGraphics();
g2d.setColor(Color.RED);
g2d.drawLine(0, 0, 200, 200);
g2d.drawLine(200, 0, 0, 200);
g2d.dispose();
JLabel label = new JLabel(new ImageIcon(img));
label.setBorder(new LineBorder(Color.GRAY));
add(label);
}
}
public class RightPane extends JPanel {
public RightPane() {
setLayout(new BorderLayout());
BufferedImage img = new BufferedImage(200, 200, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = img.createGraphics();
g2d.setColor(Color.RED);
g2d.drawLine(0, 0, 200, 200);
g2d.drawLine(200, 0, 0, 200);
g2d.dispose();
JLabel label = new JLabel(new ImageIcon(img));
label.setBorder(new LineBorder(Color.GRAY));
add(label);
}
}
public class MiddlePane extends JPanel {
public MiddlePane() {
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.insets = new Insets(4, 4, 4, 4);
add(new JButton("Button"), gbc);
gbc.gridx++;
add(new JButton("Button"), gbc);
gbc.gridwidth = 2;
gbc.gridx = 0;
gbc.gridy = 2;
add(new JButton("Button"), gbc);
gbc.gridy = 1;
gbc.weightx = 1;
gbc.weighty = 1;
gbc.fill = GridBagConstraints.BOTH;
add(new JScrollPane(new JTextArea("Text Area", 5, 10)), gbc);
}
}
}
You are using a null layout for layout of your custom panel. When you add this inside another panel of grid layout, since the sizes are not set, it would not be painted. Try using a proper layout for your custom panel as well.
And, see the answer for Using a JPanel with a null layout .

Fix the size of a JScrollPane of JPanels in a JFrame

I am a beginner in Java Swing and I am trying to put a multiple JPanels in a JScrollPanel. The matter is, the JSCrollPannel (named jp in the code) should not fill all the JFrame but it does even if I fix a size with setSize() and a maximal size with setMaximalSize(). What is the trouble? How can I make the JSCrollPane smaller than the JFrame?
package GUI;
import java.awt.*;
import javax.swing.*;
public class MultiPanels {
private JScrollPane getContent() {
Dimension d = new Dimension(300,200);
JPanel panel = new JPanel(new GridBagLayout());
GridBagConstraints gbc= new GridBagConstraints();
gbc.weightx = 1.0;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.gridwidth = GridBagConstraints.REMAINDER;
panel.add(getPanel(d, 6, Color.red), gbc);
panel.add(getPanel(d, 4, Color.green.darker()), gbc);
panel.add(getPanel(d, 4, Color.orange), gbc);
panel.add(getPanel(d, 12, Color.blue), gbc);
panel.add(getEmptyPanel(d), gbc);
return new JScrollPane(panel);
}
private JScrollPane getPanel(Dimension d, int rows, Color color) {
JPanel panel = new JPanel(new GridBagLayout());
panel.setBackground(color);
GridBagConstraints gbc= new GridBagConstraints();
gbc.insets = new Insets(10,5,10,5);
gbc.weightx = 1.0;
for(int i = 0, j = 1; i < rows; i++) {
gbc.gridwidth = GridBagConstraints.RELATIVE;
panel.add(new JButton(String.valueOf(j++)), gbc);
gbc.gridwidth = GridBagConstraints.REMAINDER;
panel.add(new JButton(String.valueOf(j++)), gbc);
}
JScrollPane scrollPane = new JScrollPane(panel);
scrollPane.setPreferredSize(d);
return scrollPane;
}
private JScrollPane getEmptyPanel(Dimension d) {
JPanel panel = new JPanel() {
protected void paintComponent(Graphics g) {
int w = getWidth();
int h = getHeight();
GradientPaint gp = new GradientPaint(0,0,Color.red,
0,h,Color.cyan);
((Graphics2D)g).setPaint(gp);
g.fillRect(0,0,w,h);
}
};
panel.setPreferredSize(new Dimension(300,400));
JScrollPane scrollPane = new JScrollPane(panel);
scrollPane.setPreferredSize(d);
return scrollPane;
}
public static void main(String[] args) {
JFrame f = new JFrame();
JScrollPane jp = new MultiPanels().getContent();
jp.setSize(new Dimension(200, 200));
jp.setMaximumSize(new Dimension(200,200));
jp.setPreferredSize(new Dimension(200,200));
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(jp);
f.setSize(400,400);
f.setLocation(200,200);
f.setResizable(false);
f.setVisible(true);
}
}
Any time things don't size or arrange correctly, you have to look into Layouts.
Generally, spend more time on:
http://docs.oracle.com/javase/tutorial/uiswing/layout/visual.html
To be specific, the default layout of a JPanel and JFrame is BorderLayout which is a very simple layout manager indeed. When you add to a component managed by BorderLayout without saying where, it is automatically added to the center and fills to use all available space:
http://docs.oracle.com/javase/tutorial/uiswing/layout/visual.html#border
It is possible to use "none" (Absolute Positioning) as the layout, but this is almost always a bad idea and you want to think about what you really want to do with the rest of the space in the JFrame: perhaps by letting new child components, with their own size demands, take up some of the space that the main panel is now swallowing up.

how to maintain dimension size of jpanel with GridBagLayout?

Here is my code. When I resize the program the other layouts, it works fine except for the CheckPanel (with GridBagLayout); somehow it became bigger. How can I handle this?
Advance Thanks.
JPanel CheckPanel = new JPanel();
CheckPanel.setBackground(Color.WHITE);
GridBagConstraints gbc_CheckPanel = new GridBagConstraints();
gbc_CheckPanel.gridwidth = 2;
gbc_CheckPanel.fill = GridBagConstraints.BOTH;
gbc_CheckPanel.gridx = 0;
gbc_CheckPanel.gridy = 1;
CenterPanel.add(CheckPanel, gbc_CheckPanel);
CheckPanel.setLayout(new GridLayout(0, 6, 0, 0));
The constraint
gbc_CheckPanel.fill = GridBagConstraints.BOTH;
tells the GridBagLayout to let this component use any available extra space (also depending on its preferred- and maximum size). Using GridBagConstraints.NONE or GridBagConstraints.VERTICAL could solve this, but you still have to decide which component will receive the extra space.
EDIT: Based on the comments, it is still not clear how the other components are inserted, and how the distribution of extra space is specified. In this example, the weighty fields are used to say that the table should receive all extra space. Maybe it helps to identify differences to the original program:
import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class CheckboxConstraints
{
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
createAndShowGUI();
}
});
}
private static void createAndShowGUI()
{
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel centerPanel = new JPanel(new GridBagLayout());
centerPanel.setBackground(Color.RED);
fill(centerPanel);
f.getContentPane().setLayout(new GridLayout(1,1));
f.getContentPane().add(centerPanel);
f.setSize(500, 300);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
private static void fill(JPanel centerPanel)
{
addSearchBar(centerPanel);
addCheckBoxPanel(centerPanel);
addTable(centerPanel);
}
private static void addSearchBar(JPanel centerPanel)
{
GridBagConstraints gbc = null;
gbc = new GridBagConstraints();
gbc.gridwidth = 1;
gbc.fill = GridBagConstraints.BOTH;
gbc.gridx = 0;
gbc.gridy = 0;
gbc.weightx = 0;
gbc.weighty = 0;
centerPanel.add(new JButton("Search"), gbc);
gbc = new GridBagConstraints();
gbc.gridwidth = 1;
gbc.fill = GridBagConstraints.BOTH;
gbc.gridx = 1;
gbc.gridy = 0;
gbc.weightx = 1;
gbc.weighty = 0;
centerPanel.add(new JTextField(), gbc);
}
private static void addCheckBoxPanel(JPanel centerPanel)
{
JPanel checkPanel = new JPanel();
checkPanel.setBackground(Color.WHITE);
GridBagConstraints gbc_CheckPanel = new GridBagConstraints();
gbc_CheckPanel.gridwidth = 2;
gbc_CheckPanel.fill = GridBagConstraints.BOTH;
gbc_CheckPanel.gridx = 0;
gbc_CheckPanel.gridy = 1;
gbc_CheckPanel.weighty = 0;
centerPanel.add(checkPanel, gbc_CheckPanel);
checkPanel.setLayout(new GridLayout(0, 6, 0, 0));
checkPanel.add(new JCheckBox("C0"));
checkPanel.add(new JCheckBox("C1"));
checkPanel.add(new JCheckBox("C2"));
checkPanel.add(new JCheckBox("C3"));
checkPanel.add(new JCheckBox("C4"));
checkPanel.add(new JCheckBox("C5"));
}
private static void addTable(JPanel centerPanel)
{
JTable table = new JTable(new Object[][] {
{"C00", "C01" },
{"C00", "C01" },
}, new Object[]{ "H0", "H1" });
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = 2;
gbc.fill = GridBagConstraints.BOTH;
gbc.gridx = 0;
gbc.gridy = 2;
gbc.weighty = 1.0;
JScrollPane scrollPane = new JScrollPane(table);
centerPanel.add(scrollPane, gbc);
}
}
Please try:
gbc_CheckPanel.fill =GridBagConstraints.HORIZONTAL
and to adjust the space vertically
gbc_CheckPanel.ipady = 20; //Not sure this works in your case but this should fix the resizing issue
Another solution is to add a new JPanel with BorderLayout and insert the panel with JCheckBoxes using the constraint BorderLayout.NORTH and the table with constraint BorderLayout.CENTRE

Sizing issue with scrollable JTextField

I have a form with lots of text fields and some of those text fields may contain very long strings. To make it work I made those text fields scrollable using this code:
JScrollPane scroll = new JScrollPane(textField);
scroll.setPreferredSize(new Dimension((int)textField.getPreferredSize().getWidth(), (int)textField.getPreferredSize().getHeight() * 2));
Then I put scroll into my form using GridBagLayout.
Second line in my example is required for scroller to show up. But it has downside. When I resize window to fit whole text in text field, then scroll disapears leaving me with just two times higher then others text field, which looks ridiculous.
How can I make this all work and show me normal size of text field after scroller is hidden?
EDIT:
You may use following as a demo code to reproduce the issue:
import javax.swing.*;
import java.awt.*;
public class ScrollTextDemo extends JFrame{
public ScrollTextDemo(){
super();
this.setPreferredSize(new Dimension(500, 300));
JPanel panel = new JPanel();
panel.setLayout(new GridBagLayout());
JTextField textField = new JTextField("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
textField.setCursor(new Cursor(0));
textField.setEditable(false);
JScrollPane scroll = new JScrollPane(textField);
scroll.setPreferredSize(new Dimension(70, 40) );
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 1;
gbc.gridy = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 0.5;
gbc.insets = new Insets(5, 5, 0, 5);
panel.add(scroll,gbc);
//let's add one more text field without scroll bar to compare
JTextField textField2 = new JTextField("abc");
gbc = new GridBagConstraints();
gbc.gridx = 1;
gbc.gridy = 2;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 0.5;
gbc.insets = new Insets(5, 5, 0, 5);
panel.add(textField2,gbc);
this.add(panel);
}
public static void main(String args[]){
ScrollTextDemo demo = new ScrollTextDemo();
demo.pack();
demo.setVisible(true);
}
}
For this , in the absence of a good SSCCE, I think you hadn't provided any constraint that goes for fill, which is used for
Used when the component's display area is larger than the component's requested size to determine whether and how to resize the component. Valid values (defined as GridBagConstraints constants) include NONE (the default), HORIZONTAL (make the component wide enough to fill its display area horizontally, but do not change its height), VERTICAL (make the component tall enough to fill its display area vertically, but do not change its width), and BOTH (make the component fill its display area entirely).
So you must add something like this to your GridBagConstraints
constraintsGridBag.fill = GridBagConstraints.HORIZONTAL;
This will only allow it to expand HORIZONTALLY not both ways.
** EDIT : As for the added code **
Never specify setPreferredSize(...) for any component in Swing. Let the Layout Manager you are using, take care for that. Remove all setPreferredSize(...) thingies, will let it remain in normal size upon resizing.
*EDIT 2 : *
Code to tell you what I am saying :
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.*;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
public class GridBagTest extends JFrame
{
private JPanel topPanel;
private JPanel bottomPanel;
public GridBagTest()
{
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
//gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.fill = GridBagConstraints.BOTH;
gbc.weightx = 1.0;
gbc.weighty = 0.8;
// Setting TOP PANEL.
topPanel = new JPanel();
topPanel.setLayout(new GridBagLayout());
GridBagConstraints constraintsTopPanel = new GridBagConstraints();
constraintsTopPanel.gridwidth = 2; // Specifies that this component will take two columns.
constraintsTopPanel.gridheight = 1; // specifies that the component will take one row.
/*
* fill with HORIZONTAL, means the component upon resize, will
* only expand along the X-Axis.
*/
constraintsTopPanel.fill = GridBagConstraints.NONE;
constraintsTopPanel.insets = new Insets(5, 5, 5, 5);
constraintsTopPanel.ipadx = 2;
constraintsTopPanel.ipady = 2;
constraintsTopPanel.weightx = 0.3;
constraintsTopPanel.weighty = 0.2;
constraintsTopPanel.gridx = 0;
constraintsTopPanel.gridy = 0;
JTextField tfield1 = new JTextField("kajslkajfkl dsjlafj lksdj akljsd lfkajflkdj lkaj flkdjalk jflkaj lkfdsj salkj flkaj flkja dslkfjal ksjdflka jlfjd aflsdj", 10);
topPanel.add(tfield1, constraintsTopPanel);
constraintsTopPanel.gridx = 2;
constraintsTopPanel.gridy = 0;
final JTextField tfield2 = new JTextField("kajslkajfkl dsjlafj lksdj akljsd lfkajflkdj lkaj flkdjalk jflkaj lkfdsj salkj flkaj flkja dslkfjal ksjdflka jlfjd aflsdj", 10);
topPanel.add(tfield2, constraintsTopPanel);
constraintsTopPanel.gridx = 4;
constraintsTopPanel.gridy = 0;
JTextField tfield3 = new JTextField("kajslkajfkl dsjlafj lksdj akljsd lfkajflkdj lkaj flkdjalk jflkaj lkfdsj salkj flkaj flkja dslkfjal ksjdflka jlfjd aflsdj", 10);
topPanel.add(tfield3, constraintsTopPanel);
topPanel.setBackground(Color.WHITE);
add(topPanel, gbc);
constraintsTopPanel.gridx = 0;
constraintsTopPanel.gridy = 2;
constraintsTopPanel.gridwidth = 6; // Specifies that this component will take two columns.
constraintsTopPanel.gridheight = 1; // specifies that the component will take one row.
JButton button = new JButton("REMOVE");
button.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
topPanel.remove(tfield2);
topPanel.revalidate();
topPanel.repaint();
}
});
topPanel.add(button, constraintsTopPanel);
//Setting BOTTOM PANEL.
bottomPanel = new JPanel();
bottomPanel.setLayout(new BorderLayout());
bottomPanel.setBackground(Color.DARK_GRAY);
JLabel label3 = new JLabel("I am a new JLABEL for the bottom JPanel", JLabel.CENTER);
label3.setForeground(Color.WHITE);
bottomPanel.add(label3, BorderLayout.CENTER);
gbc.weighty = 0.2;
add(bottomPanel, gbc);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
pack();
setVisible(true);
}
public static void main(String... args)
{
javax.swing.SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
new GridBagTest();
}
});
}
}
Well the best I've got is looking ugly in code, but does exactly what I need to the textField. Below is changed sample code from initial question. I'd be thankfull for any ideas how to make it better:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
public class ScrollTextDemo extends JFrame{
public ScrollTextDemo(){
super();
this.setPreferredSize(new Dimension(500, 300));
JPanel panel = new JPanel();
panel.setLayout(new GridBagLayout());
JTextField textField = new JTextField("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
textField.setCursor(new Cursor(0));
textField.setEditable(false);
JScrollPane scroll = new JScrollPane(textField, JScrollPane.VERTICAL_SCROLLBAR_NEVER,JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 1;
gbc.gridy = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 0.5;
//gbc.ipady = 20;//gives some room for scroll to appear and don't hide text area under the scroll.
gbc.insets = new Insets(5, 5, 0, 5);
panel.add(scroll,gbc);
//let's add one more text field without scroll bar to compare
JTextField textField2 = new JTextField("bbbbbbbb");
gbc = new GridBagConstraints();
gbc.gridx = 1;
gbc.gridy = 2;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 0.5;
gbc.insets = new Insets(5, 5, 0, 5);
panel.add(textField2,gbc);
scroll.addComponentListener( new ScrollTextComponentListener(scroll, textField2));
this.add(panel);
}
public static void main(String args[]){
ScrollTextDemo demo = new ScrollTextDemo();
demo.pack();
demo.setVisible(true);
}
}
class ScrollTextComponentListener implements ComponentListener {
private boolean scrollVisible;
private JScrollPane scroll;
private JComponent compareComponent;
public ScrollTextComponentListener(JScrollPane scroll, JComponent compareComponent) {
this.scroll = scroll;
this.compareComponent = compareComponent;
}
private boolean isScrollVisible() {
return scroll.getHorizontalScrollBar().getModel().getExtent() != scroll.getHorizontalScrollBar().getModel().getMaximum();
}
private void setScrollSize(){
boolean scrollVisible = isScrollVisible();
if (scrollVisible){
scroll.setPreferredSize(new Dimension(compareComponent.getWidth(),compareComponent.getHeight()*2));
//also had to set both min and max sizes, because only preffered size didn't always work
scroll.setMinimumSize(new Dimension(compareComponent.getWidth(),compareComponent.getHeight()*2));
scroll.setMaximumSize(new Dimension(compareComponent.getWidth(),compareComponent.getHeight()*2));
}
else {
scroll.setPreferredSize(new Dimension(compareComponent.getWidth(),compareComponent.getHeight()));
scroll.setMinimumSize(new Dimension(compareComponent.getWidth(),compareComponent.getHeight()));
scroll.setMaximumSize(new Dimension(compareComponent.getWidth(),compareComponent.getHeight()));
}
this.scrollVisible = scrollVisible;
}
#Override
public void componentResized(ComponentEvent e) {
if (isScrollVisible() != scrollVisible) setScrollSize();
}
#Override
public void componentMoved(ComponentEvent e) {
}
#Override
public void componentShown(ComponentEvent e) {
setScrollSize();
}
#Override
public void componentHidden(ComponentEvent e) {
}
}

How to put component in bottom-right corner with GridBagLayout?

I need to display a single component within a JPanel, and I want to keep that component in bottom right corner at all times. I tried to do it with GridBagLayout:
val infoArea = new TextArea {
text = "Hello!"
border = Swing.EmptyBorder(30)
background = Color.RED
editable = false
}
val p = new JPanel
p.setLayout(new GridBagLayout)
val c = new GridBagConstraints
c.gridx = 0
c.gridy = 0
c.anchor = GridBagConstraints.LAST_LINE_END
p.add(infoArea.peer,c)
val f = new JFrame
f.setContentPane(p)
f.setVisible(true)
But the text area is at the center for some reason:
What am I doing wrong here?
For example:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import javax.swing.*;
public class LayoutDemo {
private static void createAndShowGui() {
JLabel label = new JLabel("Hello");
label.setOpaque(true);
label.setBackground(Color.red);
JPanel bottomPanel = new JPanel(new BorderLayout());
bottomPanel.add(label, BorderLayout.LINE_END);
JPanel mainPanel = new JPanel(new BorderLayout());
mainPanel.add(bottomPanel, BorderLayout.PAGE_END);
mainPanel.setPreferredSize(new Dimension(400, 400));
JFrame frame = new JFrame("LayoutDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
final JFrame frame = new JFrame();
frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
frame.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.fill = GridBagConstraints.BOTH;
gbc.weightx = 1.0;
gbc.weighty = 1.0;
frame.add(Box.createGlue(), gbc);
final JTextArea textArea = new JTextArea("SE");
textArea.setPreferredSize(new Dimension(50, 50));
textArea.setOpaque(true);
textArea.setBackground(Color.RED);
gbc = new GridBagConstraints();
gbc.gridx = 1;
gbc.gridy = 1;
gbc.fill = GridBagConstraints.NONE;
gbc.weightx = 0.0;
gbc.weighty = 0.0;
frame.add(textArea, gbc);
frame.setSize(640, 480);
frame.setVisible(true);
...if you realy want to use GridBagLayout
you have to put a dummy (use Box.createGlue() to make a dummy component) component on gridx = 0 and gridy = 0 and the component you want to put at the bottom right at gridx = 1, gridy = 1.like this

Categories

Resources