JPanel of larger size than the Scrollpane - java

I have implemented a dialog in which I add a number of checkboxes in a JPanel that also has a scroll bar. The number of check boxes isn't fixed for each run of my program but I know it before I create the dialog.
Unfortunately when I have a large number of checkboxes to add the dialog looks like this:
My code is:
JPanel listPanel = new JPanel(new GridLayout(files.size() + 2, 1));
for (int i = 0; i < files.size(); i++) {
listPanel.add(files.get(i));
}
listPanel.setPreferredSize(new Dimension(600, 1400));
JScrollPane sp =
new JScrollPane(listPanel, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
sp.setPreferredSize(new Dimension(300, 200));
mainPanel.add(sp, BorderLayout.CENTER);
mainPanel.add(buttonPane, BorderLayout.EAST);
getContentPane().setLayout(new FlowLayout());
getContentPane().add(mainPanel);
pack();
setResizable(false);
How can I just set the size of the Panel inside the Scrollpane to a larger size without affecting the frame?

Avoid using setPreferredSize, let the layout managers decide the sizes they actually need...
Updated with example
The JViewport of the scroll pane is using the preferred size of the listPane to determine how much viewable space it needs, which is a lot...
In order to overcome this, you need to provide a better hint to the view port as to the viewable size your component would actually like to be. The preferredSize of the component isn't going to work here, you need to supply preferredScrollableViewportSize from the Scrollable interface
public class BadList {
public static void main(String[] args) {
new BadList();
}
public BadList() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
List<String> files = new ArrayList<>(2000);
for (int index = 0; index < 2000; index++) {
files.add(Integer.toString(index));
}
ListPane listPanel = new ListPane();
listPanel.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.weightx = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.gridwidth = GridBagConstraints.REMAINDER;
for (String file : files) {
listPanel.add(new JCheckBox(file), gbc);
}
JScrollPane sp = new JScrollPane(listPanel);
JPanel mainPanel = new JPanel(new BorderLayout());
JPanel buttonPane = new JPanel(new GridBagLayout());
buttonPane.add(new JButton("Select All"), gbc);
buttonPane.add(new JButton("Deselect All"), gbc);
gbc.weighty = 1;
buttonPane.add(new JPanel(), gbc);
mainPanel.add(sp, BorderLayout.CENTER);
mainPanel.add(buttonPane, BorderLayout.EAST);
setLayout(new BorderLayout());
add(mainPanel);
}
}
public class ListPane extends JPanel implements Scrollable {
#Override
public Dimension getPreferredScrollableViewportSize() {
return new Dimension(200, 200);
}
#Override
public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) {
return 128;
}
#Override
public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) {
return 128;
}
#Override
public boolean getScrollableTracksViewportWidth() {
return false;
}
#Override
public boolean getScrollableTracksViewportHeight() {
return false;
}
}
}
nb- I've used some arbitrary magic numbers in this example, you're going to what to provide more realistic values for your need

JPanel has implemented FlowLayout,
FlowLayout accepting only PreferredSize, then your JScrollPane is correctly layed
use JTable (put there Boolean value, representing JCheckBox) instead of add childs to the JPanel (non_natural scrolling, have to change scroll increment)
listPanel.setPreferredSize(new Dimension(600, 1400)); isn't nice Dimmension, comment this code line, lets that for pack()
for this job (code posted here) I'd be put JScrollPane and buttonPane to the JFrame directly, instead of usage mainPanel(), otherwise post an SSCCE

Related

GridBagLayout in JPanel, components don't change x || y positions

I'm attempting to create my own GUI, trying to move the playerWins JLabel over to the far right. I've tried changing both x and y coordinates but the JLabel stays where it is. I'm wondering if it has to do with the JPanel being set as CENTRE.
import javax.swing.*;
import java.awt.*;
public class DieIntGUI extends JFrame {
public DieIntGUI(String title) {
super(title);
setSize(700, 700);
getContentPane().setBackground(Color.white);
setLayout(new BorderLayout());
initComponents();
add(panel);
add(errorMessages, BorderLayout.SOUTH);
setLocationRelativeTo(null);
}
public static void main(String[] args) {
DieIntGUI frame = new DieIntGUI("Dice Game");
frame.setVisible(true);
}
private void initComponents() {
panel = new JPanel();
errorMessages = new JLabel("T");
playerWins = new JLabel("F");
computerWins = new JLabel("S");
drawComponents();
}
private void drawComponents() {
GridBagConstraints gbc = new GridBagConstraints();
panel.setLayout(new GridBagLayout());
panel.setSize(700, 700);
panel.setBackground(Color.white);
gbc.gridx = 2;
gbc.gridy = 17;
panel.add(playerWins, gbc);
}
private JPanel panel;
private JLabel errorMessages;
public JLabel playerWins, computerWins;
}
The solution using GridBagLayout would be.
gbc.gridx = 1;
gbc.gridy = 1;
gbc.weightx=1; //Fill all space
gbc.anchor=GridBagConstraints.EAST; //align component to the EAST
I have set x, y to 1. What's important to understand is that these are index's relative to other object that you add. (Has no sense if only 1 component, there are no invisible grid locations.)
This will move the label to far right.
public DieIntGUI(String title) {
super(title);
setSize(700, 700);
getContentPane().setBackground(Color.white);
setLayout(new BorderLayout());
initComponents();
add(panel, BorderLayout.EAST); // Move to right
add(errorMessages, BorderLayout.SOUTH);
setLocationRelativeTo(null);
}
Output:
And yes, the panel was set to CENTER because in BorderLayout, if you do not specify a position, its set to BorderLayout.CENTER by default.

Set size of container that contains a JScrollPane with so that the scrollbar is not visible

How do you set the size of a container which contains a JScrollPane so that the scrollbar does not appear?
Consider this SSCCE (using MigLayout):
public static void main(String[] args) {
JPanel panel = new JPanel(new MigLayout());
for(int i = 0; i < 15; i++) {
JTextArea textArea = new JTextArea();
textArea.setColumns(20);
textArea.setRows(5);
textArea.setWrapStyleWord(true);
textArea.setLineWrap(true);
JScrollPane jsp = new JScrollPane(textArea);
panel.add(new JLabel("Notes" + i));
panel.add(jsp, "span, grow");
}
JScrollPane jsp = new JScrollPane(panel);
JFrame frame = new JFrame();
frame.add(jsp);
frame.pack();
frame.setSize(jsp.getViewport().getViewSize().width, 500);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
As you can see, I'm trying to figure out what to put on this line:
frame.setSize(jsp.getViewport().getViewSize().width, 500);
The goal is to set the width with respect to the contents of the viewport so that the horizontal scroll bar is not needed.
should be:
EDIT: Following camikr's advice, this is the result:
public static final int pref_height = 500;
public static void main(String[] args) {
JPanel panel = new JPanel(new MigLayout());
for(int i = 0; i < 15; i++) {
JTextArea textArea = new JTextArea();
textArea.setColumns(20);
textArea.setRows(5);
textArea.setWrapStyleWord(true);
textArea.setLineWrap(true);
JScrollPane jsp = new JScrollPane(textArea);
panel.add(new JLabel("Notes" + i));
panel.add(jsp, "span, grow");
}
JScrollPane jsp = new JScrollPane(panel) {
#Override
public Dimension getPreferredSize() {
setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
Dimension dim = new Dimension(super.getPreferredSize().width + getVerticalScrollBar().getSize().width, pref_height);
setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
return dim;
}
};
JFrame frame = new JFrame();
frame.add(jsp);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
Seems a little hackish to me, but it works.
As you can see, I'm trying to figure out what to put on this line:
Don't put anything. You should not be attempting to manage the size of the frame. For example, your code doesn't even consider the Borders of the frame. If anything your code would be changed to use the width of the frame, not the scrollpane.
The better solution is to override the getPreferredSize() method of the scroll pane to return the width of super.getPreferredSize() and then specify a reasonable height. You would need to make sure the vertical scrollbar is always visible for the calculation to work.
Then the pack() method will work as expected.
Same thing for the horizontal case:
new JScrollPane(panel) {
public Dimension getPreferredSize() {
Component view = getViewport().getView();
if (view == null) return super.getPreferredSize();
int pref_width = view.getPreferredSize().width;
setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
Dimension dim = new Dimension(pref_width, super.getPreferredSize().height + getHorizontalScrollBar().getSize().height);
setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
return dim;
}
}
Also it adapts properly should you switch out the view inside the scrollpane later.

all individual panels are not shown inside root panel

I want to add multiple jpanels to jpanel.So i added a root panel to jscrollpane.and then added all individual jpanels to this root panel.I made jscrollpane's scrolling policy as needed.i.e HORIZONTAL_SCROLLBAR_AS_NEEDED,VERTICAL_SCROLLBAR_AS_NEEDED.
But the problem is all individual panels are not shown inside root panel.
Code:
JScrollPane scPanel=new JScrollPane();
JPanel rootPanel=new JPanel();
rootPanel.setLayout(new FlowLayout());
JPanel indPanel = new JPanel();
rootPanel.add(indPanel);
JPanel indPanel2 = new JPanel();
rootPanel.add(indPanel2);
//.....like this added indPanals to rootPanel.
scPanel.setViewPortView(rootPanel);
//scPanel.setHorizontalScrollPolicy(HORIZONTAL_SCROLLBAR_AS_NEEDED);
And one more thing is, as i scroll the scrollbar the panels are going out of jscrollpane area.
I am not able to see all individual panels,
Please suggest me.
Edit: code snippet from double post:
MosaicFilesStatusBean mosaicFilesStatusBean = new MosaicFilesStatusBean();
DefaultTableModel tableModel = null;
tableModel = mosaicFilesStatusBean.getFilesStatusBetweenDates(startDate, endDate);
if (tableModel != null) {
rootPanel.removeAll();
rootPanel.setLayout(new BoxLayout(rootPanel, BoxLayout.PAGE_AXIS));
for (int tempRow = 0; tempRow < tableModel.getRowCount(); tempRow++) {
int fileIdTemp = Integer.parseInt(tableModel.getValueAt(tempRow, 0).toString());
String dateFromTemp = tableModel.getValueAt(tempRow, 3).toString();
String dateToTemp = tableModel.getValueAt(tempRow, 4).toString();
int processIdTemp = Integer.parseInt(tableModel.getValueAt(tempRow, 5).toString());
int statusIdTemp = Integer.parseInt(tableModel.getValueAt(tempRow, 6).toString());
String operatingDateTemp = tableModel.getValueAt(tempRow, 7).toString();
MosaicPanel tempPanel =
new MosaicPanel(fileIdTemp, dateFromTemp, dateToTemp, processIdTemp, statusIdTemp, operatingDateTemp);
rootPanel.add(tempPanel);
}
rootPanel.revalidate();
}
The main reason, why you couldn't see your JPanel is that you are using FlowLayout as the LayoutManager for the rootPanel. And since your JPanel added to this rootPanel has nothing inside it, hence it will take it's size as 0, 0, for width and height respectively. Though using GridLayout such situation shouldn't come. Have a look at this code example attached :
import java.awt.*;
import javax.swing.*;
public class PanelAddition
{
private void createAndDisplayGUI()
{
JFrame frame = new JFrame("Panel Addition Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel contentPane = new JPanel();
contentPane.setLayout(new GridLayout(0, 1));
JScrollPane scroller = new JScrollPane();
CustomPanel panel = new CustomPanel(1);
contentPane.add(panel);
scroller.setViewportView(contentPane);
frame.getContentPane().add(scroller, BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
for (int i = 2; i < 20; i++)
{
CustomPanel pane = new CustomPanel(i);
contentPane.add(pane);
contentPane.revalidate();
contentPane.repaint();
}
}
public static void main(String... args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
new PanelAddition().createAndDisplayGUI();
}
});
}
}
class CustomPanel extends JPanel
{
public CustomPanel(int num)
{
JLabel label = new JLabel("" + num);
add(label);
}
#Override
public Dimension getPreferredSize()
{
return (new Dimension(200, 50));
}
}
Don't use FlowLayout for the rootPanel. Instead consider using BoxLayout:
JPanel rootPanel=new JPanel();
// if you want to stack JPanels vertically:
rootPanel.setLayout(new BoxLayout(rootPanel, BoxLayout.PAGE_AXIS));
Edit 1
Here's an SSCCE that's loosely based on your latest code posted:
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.util.Random;
import javax.swing.*;
#SuppressWarnings("serial")
public class PanelsEg extends JPanel {
private static final int MAX_ROW_COUNT = 100;
private Random random = new Random();
private JPanel rootPanel = new JPanel();
public PanelsEg() {
rootPanel.setLayout(new BoxLayout(rootPanel, BoxLayout.PAGE_AXIS));
JScrollPane scrollPane = new JScrollPane(rootPanel);
scrollPane.setPreferredSize(new Dimension(400, 400)); // sorry kleopatra
add(scrollPane);
add(new JButton(new AbstractAction("Foo") {
#Override
public void actionPerformed(ActionEvent arg0) {
foo();
}
}));
}
public void foo() {
rootPanel.removeAll();
// rootPanel.setLayout(new BoxLayout(rootPanel, BoxLayout.PAGE_AXIS)); // only need to set layout once
int rowCount = random.nextInt(MAX_ROW_COUNT);
for (int tempRow = 0; tempRow < rowCount ; tempRow++) {
int fileIdTemp = tempRow;
String data = "Data " + (tempRow + 1);
MosaicPanel tempPanel =
new MosaicPanel(fileIdTemp, data);
rootPanel.add(tempPanel);
}
rootPanel.revalidate();
rootPanel.repaint(); // don't forget to repaint if removing
}
private class MosaicPanel extends JPanel {
public MosaicPanel(int fileIdTemp, String data) {
add(new JLabel(data));
}
}
private static void createAndShowGui() {
PanelsEg mainPanel = new PanelsEg();
JFrame frame = new JFrame("PanelsEg");
frame.setDefaultCloseOperation(JFrame.EXIT_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();
}
});
}
}
This SSCCE works, in that it easily shows removing and adding JPanels to another JPanel that is held by a JScrollPane. If you're still having a problem, you should modify this SSCCE so that it shows your problem.

Stack swing elements from top to bottom

Consider the following figure:
I need to develop a swing GUI the looks like this. I simply named them jLabel's but there a few images and jLabels in it. The default awt background visible is a JPanel and each red background visible is a serperate JPanel. Now I need them to get stacked as shown above. I tried a number of LayoutManagers and still it doesn't work.
The important point here is that the number of red colored divs are not constant. If there is only one red colored div then it must be displayed at the top, not at the center. As far as i know GridBagLayout should work, but it centers the single red colored jpanel available. All the layout managers are centering them but not stacking them from top to bottom.
Even with anchor set to NORTH then the panels will still be centered. You could work around it by adding a dummy panel to fill the remaining space. Personally I'd stay well away from GridBagLayout though.
JFrame frame = new JFrame();
JPanel content = new JPanel();
content.setBorder(BorderFactory.createLineBorder(Color.red));
frame.setContentPane(content);
frame.getContentPane().setLayout(new GridBagLayout());
frame.setSize(400, 300);
for (int i = 0; i < 3; i++) {
JPanel panel = new JPanel();
panel.add(new JLabel("label1"));
panel.add(new JLabel("label2"));
panel.add(new JLabel("label3"));
panel.setBorder(BorderFactory.createLineBorder(Color.red));
GridBagConstraints con = new GridBagConstraints();
con.gridy = i;
con.gridx = 0;
con.anchor = GridBagConstraints.NORTHWEST;
con.ipady = 10;
frame.getContentPane().add(panel, con);
}
// dummy panel to use up the space (force others to top)
frame.getContentPane().add(
new JPanel(),
new GridBagConstraints(0, 3, 1, 1, 1, 1,
GridBagConstraints.NORTHWEST,
GridBagConstraints.VERTICAL, new Insets(0, 0, 0, 0), 0,
0));
frame.setVisible(true);
GroupLayout example (my favourite layout manager).
JFrame frame = new JFrame();
JPanel content = new JPanel();
frame.setContentPane(content);
frame.getContentPane().setLayout(
new BoxLayout(content, BoxLayout.Y_AXIS));
frame.setSize(400, 300);
GroupLayout gLayout = new GroupLayout(content);
content.setLayout(gLayout);
ParallelGroup hGroup = gLayout.createParallelGroup();
gLayout.setHorizontalGroup(hGroup);
SequentialGroup vGroup = gLayout.createSequentialGroup();
gLayout.setVerticalGroup(vGroup);
for (int i = 0; i < 3; i++) {
JPanel panel = new JPanel();
panel.add(new JLabel("label1"));
panel.add(new JLabel("label2"));
panel.add(new JLabel("label3"));
panel.setBorder(BorderFactory.createLineBorder(Color.red));
hGroup.addComponent(panel);
vGroup.addComponent(panel, GroupLayout.PREFERRED_SIZE,
GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE);
vGroup.addGap(10);
}
frame.setVisible(true);
you can use Vertical BoxLayout, for example:
http://www.java-tips.org/java-se-tips/javax.swing/how-to-use-swing-boxlayout.html
nobody tell us that all JComponents must be visible, for example
from code
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.LineBorder;
public class AddComponentsAtRuntime {
private JFrame f;
private JPanel panel;
private JCheckBox checkValidate, checkReValidate, checkRepaint, checkPack;
public AddComponentsAtRuntime() {
f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
panel = new JPanel(new GridLayout(0, 1));
f.add(panel, "Center");
f.add(getCheckBoxPanel(), "South");
f.setLocation(200, 200);
f.pack();
f.setVisible(true);
}
private JPanel getCheckBoxPanel() {
checkValidate = new JCheckBox("validate");
checkValidate.setSelected(false);
checkReValidate = new JCheckBox("revalidate");
checkReValidate.setSelected(false);
checkRepaint = new JCheckBox("repaint");
checkRepaint.setSelected(false);
checkPack = new JCheckBox("pack");
checkPack.setSelected(false);
JButton addComp = new JButton("Add New One");
addComp.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JPanel b = new JPanel(new GridLayout(0, 4));
b.setBackground(Color.red);
b.setBorder(new LineBorder(Color.black, 2));
//b.setPreferredSize(new Dimension(600, 20));
for (int i = 0; i < 4; i++) {
JLabel l = new JLabel("label" + i + 1);
b.add(l);
if (i == 2) {
l.setVisible(false);
}
}
panel.add(b);
makeChange();
System.out.println(" Components Count after Adds :" + panel.getComponentCount());
}
});
JButton removeComp = new JButton("Remove One");
removeComp.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
int count = panel.getComponentCount();
if (count > 0) {
panel.remove(0);
}
makeChange();
System.out.println(" Components Count after Removes :" + panel.getComponentCount());
}
});
JPanel panel2 = new JPanel();
panel2.add(checkValidate);
panel2.add(checkReValidate);
panel2.add(checkRepaint);
panel2.add(checkPack);
checkPack.setSelected(true);
panel2.add(addComp);
panel2.add(removeComp);
return panel2;
}
private void makeChange() {
if (checkValidate.isSelected()) {
panel.validate();
}
if (checkReValidate.isSelected()) {
panel.revalidate();
}
if (checkRepaint.isSelected()) {
panel.repaint();
}
if (checkPack.isSelected()) {
f.pack();
}
}
public static void main(String[] args) {
AddComponentsAtRuntime makingChanges = new AddComponentsAtRuntime();
}
}
You should try the MigLayout it is simple yet powerful. Below I tell miglayout to grow elements, and fill all possible space, then after each element I tell it to go to a new line (wrap). You can find examples and tutorial on MigLayout page http://www.miglayout.com/:
import net.miginfocom.swing.MigLayout;
public class PanelLearning extends JPanel {
public PanelLearning() {
setLayout(new MigLayout("", "[grow, fill]", ""));
for (int i = 0; i < 3; i++) {
JPanel panel = new JPanel();
panel.add(new JLabel("label1"));
panel.add(new JLabel("label2"));
panel.add(new JLabel("label3"));
panel.setBorder(BorderFactory.createLineBorder(Color.red));
add(panel, "span, wrap");
}
}
public static void main(String[] args) {
JFrame frame = new JFrame("Login");
frame.setVisible(true);
frame.setContentPane(new PanelLearning());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.pack();
}
}
Make sure GridBagConstraints.anchor = GridBagConstraints.NORTH when you add components to the panel.

GridBagLayout Don't make components "jump" after add

I want to use GridBagLayout for a layout that has <= 3 columns, and a variable amount of rows(If anyone knows another layout that can do this easily, please tell me), everytime I press the "add" button a square will be added at the first location that is available. Like so:
|x x x|
|x x x|
|x o |
The x's are squares, and when I press add a new square should be added where the o is now.
I managed to "kind of make it work" like so:
public void addSquare(Square square) {
c.fill = GridBagConstraints.NONE;
c.gridx = nrOfSquares % 3;
c.gridy = (int) (nrOfSquares / 3);
c.weighty = 1;
c.weightx = 1;
c.anchor = GridBagConstraints.NORTHWEST;
c.insets = new Insets(5, 5, 5, 5);
this.container.add(square, c);
this.container.revalidate();
++nrOfSquares;
}
the problem is that the second square I add is added like this:
|x x |
please note that there is an extra space between the first square and the second one. I have the same problem when an extra row is added.
Now how do I fix my code so that the squares don't "jump" and are added like in the first example I gave?
EDIT: as requested, a better example after I converted it to a regular GridLayout:
public class Square extends JPanel {
public Square() {
super();
Dimension SIZE = new Dimension(200, 200);
this.setSize(SIZE);
this.setPreferredSize(SIZE);
this.setMinimumSize(SIZE);
this.setMaximumSize(SIZE);
this.setBackground(Color.ORANGE);
this.setVisible(true);
}
}
public class SquareContainer extends JPanel {
protected JPanel realContainer;
public SquareContainer(int width, int height) {
super();
this.setLayout(new BorderLayout());
this.setBackground(Color.WHITE);
this.setSize(width, height);
this.realContainer = new JPanel();
GridLayout layout = new GridLayout(0, 3);
layout.setHgap(10);
layout.setVgap(10);
this.realContainer.setLayout(layout);
this.realContainer.setBackground(this.getBackground());
JScrollPane scroller = new JScrollPane(this.realContainer);
scroller.getVerticalScrollBar().setUnitIncrement(20);
this.add(scroller, BorderLayout.CENTER);
}
public void addSquare(Square square) {
this.realContainer.add(square);
this.realContainer.revalidate();
}
}
And I just add that to a JFrame:
public class TheGreatFrame extends JFrame {
public TheGreatFrame() {
super();
this.setSize(800, 800);
this.setLocationRelativeTo(null);
this.setLayout(new BorderLayout());
this.setResizable(false);
this.add(new SquareContainer(750, 660), BorderLayout.CENTER);
this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
this.setVisible(true);
}
}
A small example program of using GridLayout:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class GridLayoutEg {
private static void createAndShowGui() {
final JPanel centerPanel = new JPanel(new GridLayout(0, 3));
JButton addBtn = new JButton(new AbstractAction("Add Button") {
#Override
public void actionPerformed(ActionEvent e) {
centerPanel.add(new JButton("X"));
centerPanel.revalidate();
centerPanel.repaint();
SwingUtilities.getWindowAncestor(centerPanel).pack();
}
});
JPanel btnPanel = new JPanel();
btnPanel.add(addBtn);
JPanel mainPanel = new JPanel(new BorderLayout());
mainPanel.add(centerPanel, BorderLayout.CENTER);
mainPanel.add(btnPanel, BorderLayout.PAGE_END);
JFrame frame = new JFrame("GridLayoutEg");
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();
}
});
}
}
if all JComponents could have the same HEIGHT and WEIGHT, then look for GridLayout
in case that the JComponent couldn't same WEIGHT, then put each "line" to the separate JPanel (by using BorderLayout or BoxLayout) and use GridLayout for put these JPanels into Container

Categories

Resources