JScrollPane does not appear when using it on a JPanel - java

I have been trying for hours to find a way to solve the issue, but I had no luck with that. Here is a sample code:
import java.awt.BorderLayout;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
public class Example extends JFrame
{
private static final long serialVersionUID = 1L;
public Example()
{
JPanel contentPane = (JPanel) getContentPane();
contentPane.setLayout(new BorderLayout());
JPanel panTop = new JPanel(new BorderLayout());
//JPanel panBottom = new JPanel(new BorderLayout());
JPanel panTopCenter = new JPanel();
//JPanel panTopLeft = new JPanel();
//JPanel panTopRight = new JPanel();
panTop.add(panTopCenter, BorderLayout.CENTER);
//panTop.add(panTopLeft, BorderLayout.WEST);
//panTop.add(panTopRight, BorderLayout.EAST);
contentPane.add(panTop, BorderLayout.CENTER);
//contentPane.add(panBottom, BorderLayout.SOUTH);
JPanel pan = new JPanel();
pan.setLayout(new BoxLayout(pan, BoxLayout.Y_AXIS));
for(int i = 0; i < 50; i++) pan.add(new JButton("Button " + i));
JScrollPane scrollPane = new JScrollPane(pan);
panTopCenter.add(scrollPane);
pack();
setLocationRelativeTo(null);
setVisible(true);
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
new Example();
}
});
}
}
Snapshot:

I always have to set the viewport's preferred size like this.
import java.awt.*;
import javax.swing.*;
public class Example extends JFrame {
public Example() {
setDefaultCloseOperation(EXIT_ON_CLOSE);
Box box = new Box(BoxLayout.Y_AXIS);
for (int i = 0; i < 50; i++) {
box.add(new JButton("Button " + i));
}
JScrollPane sp = new JScrollPane(box);
Dimension d = new Dimension(box.getComponent(0).getPreferredSize());
sp.getVerticalScrollBar().setUnitIncrement(d.height);
d.height *= 10; // Show at least 10 buttons
sp.getViewport().setPreferredSize(d);
add(sp, BorderLayout.CENTER);
pack();
setLocationRelativeTo(null);
setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
Example e = new Example();
}
});
}
}

Don't set any sizes! The scroll-bar appears if this change is made.
JPanel panTopCenter = new JPanel(new GridLayout());
The basic problem is that FlowLayout will show components at the smallest size needed to display it, and for a scroll-pane, that is (decided to be) 0x0. By using a GridLayout with no arguments in the constructor and adding the scroll-pane as the only component, it will be forced to fill the available space.

You have to set the preferred-size, in the case that JScrollPane is single JComponent in the container or top-level container.
scrollPane.setPreferredSize(new Dimension(100,500));
Better would be to use GridLayout for the same type of JComponents.

The best solution, quick and easy, is using JXPanel from SwingX, which is quasi-standard and implements Scrollable.

Related

Resizing of multiple JPanels to fit window

I'm pretty new to the Java Swing toolkit and have created a series of JPanel with JLabel components corresponding to each panel's index and value. However I can’t seem to make the panels correctly resize, when the window is too small to resize all the panels at once. Resulting in the an extra red margin to the right of all the panels (See. Window).
Is there a way to make the Sub Panels/Spacer Panels resize in such a way that does not allow for the extra margin? Or setup a better swing layout to handle such resizing?
Code demo:
import java.awt.*;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.BoxLayout;
public class Frame extends JFrame {
private int numBox = 20;
public class SubPanel extends JPanel {
public SubPanel(int i) {
setMinimumSize(new Dimension(20, 20));
setMaximumSize(new Dimension(1000, i*30));
setBackground(Color.BLACK);
setLayout(new BorderLayout());
setAlignmentY(Component.BOTTOM_ALIGNMENT);
JLabel labelValue = new JLabel(String.valueOf(30 * i), JLabel.CENTER);
labelValue.setForeground(Color.WHITE);
add(labelValue, BorderLayout.NORTH);
JLabel labelIndex = new JLabel(String.valueOf(i), JLabel.CENTER);
labelIndex.setForeground(Color.WHITE);
add(labelIndex, BorderLayout.SOUTH);
}
}
public class SpacerPanel extends JPanel {
public SpacerPanel() {
setBackground(Color.WHITE);
setMaximumSize(new Dimension(3, 10000));
setMinimumSize(new Dimension(3, 0));
}
}
public Frame(String title) {
super(title);
JPanel mainPanel = new JPanel();
mainPanel.setBackground(Color.RED);
mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.LINE_AXIS));
for (int i = 1; i < numBox + 1; i++) {
mainPanel.add(new SpacerPanel());
mainPanel.add(new SubPanel(i));
}
mainPanel.add(new SpacerPanel());
add(mainPanel);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
public static void main(String[] args) {
new Frame("Frame").setSize(1200, 700);
}
}
If you have 40 components and you resize the frame by a few pixels, the BoxLayout is having problems allocating those pixels to each of the components.
Instead you can use the Relative Layout which allows you to specify how those pixels should be allocated.
The RelativeLayout also allows you to specify a gap between each component so you don't need to add the SpacerPanel.
However, you will need to modify the logic of the "subPanel". The height of the labels needs to be fixed so they can be painted black. So I created a "labelPanel" to hold the labels.
The restructured code using the RelativeLayout would be:
import java.awt.*;
import javax.swing.*;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.BoxLayout;
public class Frame extends JFrame {
private int numBox = 20;
public class SubPanel extends JPanel {
public SubPanel(int i) {
// setMinimumSize(new Dimension(20, 20));
// setMaximumSize(new Dimension(1000, i*30));
// setPreferredSize(new Dimension(20, i*30));
setBackground(Color.RED);
setLayout(new BorderLayout());
// setAlignmentY(Component.BOTTOM_ALIGNMENT);
JPanel labelPanel = new JPanel( new BorderLayout() );
labelPanel.setBackground( Color.BLACK );
labelPanel.setPreferredSize(new Dimension(20, i*30));
add(labelPanel, BorderLayout.PAGE_END);
JLabel labelValue = new JLabel(String.valueOf(30 * i), JLabel.CENTER);
labelValue.setForeground(Color.WHITE);
labelPanel.add(labelValue, BorderLayout.NORTH);
JLabel labelIndex = new JLabel(String.valueOf(i), JLabel.CENTER);
labelIndex.setForeground(Color.WHITE);
labelPanel.add(labelIndex, BorderLayout.SOUTH);
}
}
public class SpacerPanel extends JPanel {
public SpacerPanel() {
setBackground(Color.WHITE);
setMaximumSize(new Dimension(3, 10000));
setMinimumSize(new Dimension(3, 0));
}
}
public Frame(String title) {
super(title);
JPanel mainPanel = new JPanel();
// mainPanel.setBackground(Color.RED);
mainPanel.setBackground(Color.WHITE);
// mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.LINE_AXIS));
RelativeLayout rl = new RelativeLayout(RelativeLayout.X_AXIS, 5);
rl.setFill( true );
rl.setRoundingPolicy(RelativeLayout.EQUAL);
rl.setAlignment(RelativeLayout.TRAILING);
mainPanel.setLayout( rl );
Float constraint = new Float(1);
for (int i = 1; i < numBox + 1; i++) {
// mainPanel.add(new SpacerPanel());
// mainPanel.add(new SubPanel(i));
mainPanel.add(new SubPanel(i), constraint);
}
// mainPanel.add(new SpacerPanel());
add(mainPanel);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
public static void main(String[] args) {
new Frame("Frame").setSize(1200, 700);
}
}
Or this approach is closer to your original posting. It still uses the spacer and the height of the black columns will shrink as the frame height is decreased:
import java.awt.*;
import javax.swing.*;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.BoxLayout;
public class Frame2 extends JFrame {
private int numBox = 20;
public class SubPanel extends JPanel {
public SubPanel(int i) {
// setMinimumSize(new Dimension(20, 20));
// setMaximumSize(new Dimension(1000, i*30));
// setBackground(Color.BLACK);
setBackground(Color.RED);
// setLayout(new BorderLayout());
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
add(Box.createVerticalGlue());
// setAlignmentY(Component.BOTTOM_ALIGNMENT);
JPanel labelPanel = new JPanel();
labelPanel.setLayout(new BoxLayout(labelPanel, BoxLayout.Y_AXIS));
labelPanel.setBackground( Color.BLACK );
labelPanel.setPreferredSize(new Dimension(50, i*30));
labelPanel.setMaximumSize(new Dimension(1000, labelPanel.getPreferredSize().height));
add(labelPanel, BorderLayout.CENTER);
JLabel labelValue = new JLabel(String.valueOf(30 * i), JLabel.CENTER);
labelValue.setForeground(Color.WHITE);
labelValue.setAlignmentX(JLabel.CENTER_ALIGNMENT);
// add(labelValue, BorderLayout.NORTH);
labelPanel.add(labelValue);
labelPanel.add(Box.createVerticalGlue());
JLabel labelIndex = new JLabel(String.valueOf(i), JLabel.CENTER);
labelIndex.setForeground(Color.WHITE);
labelIndex.setAlignmentX(JLabel.CENTER_ALIGNMENT);
// add(labelIndex, BorderLayout.SOUTH);
labelPanel.add(labelIndex);
}
}
public class SpacerPanel extends JPanel {
public SpacerPanel() {
setBackground(Color.WHITE);
setMaximumSize(new Dimension(3, 10000));
setMinimumSize(new Dimension(3, 0));
}
}
public Frame2(String title) {
super(title);
JPanel mainPanel = new JPanel();
mainPanel.setBackground(Color.RED);
// mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.LINE_AXIS));
RelativeLayout rl = new RelativeLayout(RelativeLayout.X_AXIS, 0);
rl.setFill( true );
rl.setRoundingPolicy(RelativeLayout.EQUAL);
rl.setAlignment(RelativeLayout.TRAILING);
mainPanel.setLayout( rl );
Float constraint = new Float(1);
for (int i = 1; i < numBox + 1; i++) {
mainPanel.add(new SpacerPanel());
// mainPanel.add(new SubPanel(i));
mainPanel.add(new SubPanel(i), constraint);
}
mainPanel.add(new SpacerPanel());
add(mainPanel);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
public static void main(String[] args) {
new Frame2("Frame").setSize(1200, 700);
}
}

How to align vertically buttons of different sizes within a GridBagLayout?

I'm starting with swing, I have some questions about how to align elements within a GridBagLayout, I'm not sure either whether this is the correct approach, please advice.
I have the below code
import javax.swing.*;
import java.awt.*;
public class App {
public void start() {
JPanel mainPanel = new JPanel(new FlowLayout());
mainPanel.setBorder(BorderFactory.createLineBorder(Color.CYAN, 20));
//buttons for initial options
JButton button1 = new JButton("This is option A");
JButton button2 = new JButton("option B");
JButton button3 = new JButton("Another text");
JPanel second = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.anchor = GridBagConstraints.CENTER;
second.setBackground(Color.GREEN);
second.add(button1, gbc);
second.add(button2, gbc);
second.add(button3, gbc);
mainPanel.add(second, BorderLayout.CENTER);
//frame configuration
JFrame frame = new JFrame();
frame.setContentPane(mainPanel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(800, 600);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
frame.setResizable(false);
}
public static void main(String[] args) throws Exception {
UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
SwingUtilities.invokeLater(() -> new App().start());
}
}
My goal is to produce the following output:
So far I have tried with BoxLayout with vertical alignment and it works but the problem is that it overwrites the preferred sized of the buttons and I want them all to be the same width.
Also, I tried with GridLayout and BorderLayout adding the elements to NORTH, CENTER, and SOUTH but the sizes of the buttons change.
What is the recommended way to center the elements but keeping their dimensions?
I would nest layouts:
A JPanel that holds the buttons and uses a new GridLayout(0, 1, 0, vGap) -- a grid that holds one column and variable number of rows, with a vGap gap between buttons.
Add that JPanel into another JPanel that uses GridBagLayout, and add it in a default way (no GridBagConstraints) which will center the first JPanel into the second. This would obviously have to somehow be the size desired. This can be achieved by either
overriding getPreferredSize() in a sensible way
Calling setPreferredSize(new Dimension(someWidth, someHeight)) -- this isn't quite as "clean"
Giving this a border, specifically a BorderFactor.EmptyBorder(gap, gap, gap, gap) where gap is the size of the border around the JPanel...
Done.
Test code that uses the GridBagLayout:
import java.awt.Dimension;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import javax.swing.*;
public class ButtonLayout extends JPanel {
public static final int MY_WIDTH = 750;
public static final int MY_HEIGHT = 500;
private static final float BTN_SIZE = 24f;
private String[] buttonTexts = {"This is Option A", "Option B",
"Something Else Entirely"};
public ButtonLayout() {
int colGap = 20;
JPanel buttonPanel = new JPanel(new GridLayout(0, 1, 0, colGap));
for (String btnText : buttonTexts) {
JButton button = new JButton(btnText);
// set first letter of text as mnemonic (alt-char shortcut)
int mnemonic = (int) btnText.charAt(0);
button.setMnemonic(mnemonic);
// make button bigger by increasing its font
button.setFont(button.getFont().deriveFont(BTN_SIZE));
// add to the GridLayout-using JPanel
buttonPanel.add(button);
}
// set layout of main panel to GridBag
setLayout(new GridBagLayout());
// add the button panel in a "default" manner (no constraints)
// which centers this panel
add(buttonPanel);
}
#Override
public Dimension getPreferredSize() {
Dimension superSize = super.getPreferredSize();
int width = Math.max(MY_WIDTH, superSize.width);
int height = Math.max(MY_HEIGHT, superSize.height);
return new Dimension(width, height);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
private static void createAndShowGui() {
ButtonLayout mainPanel = new ButtonLayout();
JFrame frame = new JFrame("ButtonLayout");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
Example 2 that uses EmptyBorder:
import java.awt.GridLayout;
import javax.swing.*;
#SuppressWarnings("serial")
public class ButtonLayout extends JPanel {
public static final int MY_WIDTH = 750;
public static final int MY_HEIGHT = 500;
private static final float BTN_SIZE = 24f;
private String[] buttonTexts = {"This is Option A", "Option B",
"Something Else Entirely"};
public ButtonLayout() {
int colGap = 20;
JPanel buttonPanel = new JPanel(new GridLayout(0, 1, 0, colGap));
for (String btnText : buttonTexts) {
JButton button = new JButton(btnText);
// set first letter of text as mnemonic (alt-char shortcut)
int mnemonic = (int) btnText.charAt(0);
button.setMnemonic(mnemonic);
// make button bigger by increasing its font
button.setFont(button.getFont().deriveFont(BTN_SIZE));
// add to the GridLayout-using JPanel
buttonPanel.add(button);
}
add(buttonPanel);
int top = 60;
int left = top;
int bottom = 2 * top;
int right = left;
setBorder(BorderFactory.createEmptyBorder(top, left, bottom, right));
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
private static void createAndShowGui() {
ButtonLayout mainPanel = new ButtonLayout();
JFrame frame = new JFrame("ButtonLayout");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
I'm not sure I completely understand the issue, but if you want to vertically align the buttons, BUT allow them to keep their preferred size, just don't provide any kind of fill constraint, for example
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class SoTest {
public static void main(String[] args) {
new SoTest();
}
public SoTest() {
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();
gbc.gridwidth = GridBagConstraints.REMAINDER;
add(new JButton("This is option A"), gbc);
add(new JButton("Option B"), gbc);
add(new JButton("Another button"), gbc);
}
}
}
Or, if you want them to have the same width, use a fill constraint
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class SoTest {
public static void main(String[] args) {
new SoTest();
}
public SoTest() {
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();
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.fill = GridBagConstraints.BOTH;
add(new JButton("This is option A"), gbc);
add(new JButton("Option B"), gbc);
add(new JButton("Another button"), gbc);
}
}
}
If you want to mix a more complex layout, then you should consider making use of compound layouts
But wait, there's no outline...
So, a number of ways you "might" be able to do this, for example, you could use a CompoundBorder....
setBorder(new CompoundBorder(new LineBorder(Color.CYAN, 16), new EmptyBorder(32, 32, 32, 32)));
But the devil is in the detail

Java program doesn't show swing elements until resized?

Could anyone please explain why this may be happening?
Image is here Image I couldn't upload because I'm a new user.
setTitle("jNote");
pack();
setVisible(true);
setLayout(new BorderLayout());
setDefaultCloseOperation(EXIT_ON_CLOSE);
Image icon = Toolkit.getDefaultToolkit().getImage("jNote.png");
setIconImage(icon);
Usually GUI size can be suggested by the contents. If called after the components are added, pack() will cause the GUI to be the minimum size it needs to display them.
import java.awt.BorderLayout;
import javax.swing.*;
public class JNote {
public JComponent getGui(int rows, int cols) {
JPanel p = new JPanel(new BorderLayout(2,2));
p.add(new JLabel("1"), BorderLayout.LINE_START);
JTextArea ta = new JTextArea(rows, cols);
JScrollPane sp = new JScrollPane(
ta,
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
p.add(sp);
p.add(
new JLabel("Rows: " + rows + " " + "Columns: " + cols),
BorderLayout.PAGE_END);
return p;
}
public static void main(String[] args) {
Runnable r = new Runnable(){
public void run() {
int cols = 20;
JNote jNote = new JNote();
for (int rows=6; rows>0; rows-=2) {
JFrame f = new JFrame("jNote " + rows + "x" + cols);
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.setLocationByPlatform(true);
f.add(jNote.getGui(rows, cols));
f.pack();
f.setVisible(true);
}
}
};
SwingUtilities.invokeLater(r);
}
}
When setting dimensions via preferred sizes, you must call pack() in order to apply your preferred sizes. Resizing a frame packs it as well, hence your observations.
// component initializations
yourFrame.pack();
This is what you should do:
import java.awt.Dimension;
import java.awt.Image;
import java.awt.Toolkit;
import javax.swing.*;
public class JordanOsborn extends JFrame{
JPanel panel = new JPanel();
public JordanOsborn(){
super("jNote");
panel.setPreferredSize(new Dimension(400,300));
add(panel);
Image icon = Toolkit.getDefaultToolkit().getImage("jNote.png");
setIconImage(icon);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable(){
public void run() {
new JordanOsborn();
}
});
}
}

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.

Setting divider location on a JSplitPane doesn't work

I'm trying to set the divider location of a JSplitPane but it seems not to work.
Here's an SSCCE:
import java.awt.Color;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSplitPane;
public class JSplitProblem extends JFrame {
public JSplitProblem(){
JPanel upperPanel = new JPanel();
upperPanel.setLayout(new BoxLayout(upperPanel, BoxLayout.X_AXIS));
JPanel leftPanel = new JPanel();
leftPanel.setLayout(new BoxLayout(leftPanel, BoxLayout.Y_AXIS));
JPanel red = new JPanel();
red.setBackground(Color.red);
leftPanel.add(red);
JPanel rightPanel = new JPanel();
rightPanel.setLayout(new BoxLayout(rightPanel, BoxLayout.Y_AXIS));
JPanel blue = new JPanel();
blue.setBackground(Color.blue);
rightPanel.add(blue);
upperPanel.add(leftPanel);
upperPanel.add(rightPanel);
JPanel bottomPanel = new JPanel();
bottomPanel.setBackground(Color.black);
JSplitPane mainSplittedPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, upperPanel,bottomPanel);
mainSplittedPane.setOneTouchExpandable(true);
mainSplittedPane.setDividerLocation(0.5);
this.add(mainSplittedPane);
this.setSize(800,600);
this.setResizable(true);
this.setVisible(true);
}
public static void main(String[] args) {
new JSplitProblem();
}
}
I would like the black bottom panel to lay on a 50% of the whole area by default. What am I doing wrong?
If you want both halves of the split pane to share in the split pane's extra or removed space, set the resize weight to 0.5: (Tutorial)
JSplitPane mainSplittedPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, upperPanel,bottomPanel);
mainSplittedPane.setOneTouchExpandable(true);
mainSplittedPane.setResizeWeight(0.5);
nothing complicated in this case, with rules
1) PrefferedSize must returns Childs not as I wrong to set in my case too :-), then my answer isn't #kleopatra resist too
2) put everything about rezize, size, whatever for JSplitPane into invokeLater()
.
.
import java.awt.*;
import javax.swing.*;
public class JSplitProblem extends JFrame {
private static final long serialVersionUID = 1L;
private JSplitPane mainSplittedPane;
public JSplitProblem() {
JPanel upperPanel = new JPanel();
upperPanel.setLayout(new BoxLayout(upperPanel, BoxLayout.X_AXIS));
JPanel leftPanel = new JPanel();
leftPanel.setLayout(new BoxLayout(leftPanel, BoxLayout.Y_AXIS));
JPanel red = new JPanel();
red.setBackground(Color.red);
leftPanel.add(red);
JPanel rightPanel = new JPanel();
rightPanel.setLayout(new BoxLayout(rightPanel, BoxLayout.Y_AXIS));
JPanel blue = new JPanel();
blue.setBackground(Color.blue);
rightPanel.add(blue);
upperPanel.add(leftPanel);
upperPanel.add(rightPanel);
JPanel bottomPanel = new JPanel();
bottomPanel.setBackground(Color.black);
mainSplittedPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, upperPanel, bottomPanel);
mainSplittedPane.setOneTouchExpandable(true);
mainSplittedPane.setDividerLocation(0.5);
add(mainSplittedPane);
setPreferredSize(new Dimension(400, 300));
setDefaultCloseOperation(EXIT_ON_CLOSE);
setResizable(true);
setVisible(true);
pack();
restoreDefaults();
}
private void restoreDefaults() {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
mainSplittedPane.setDividerLocation(mainSplittedPane.getSize().height /2);
//mainSplittedPane.setDividerLocation(mainSplittedPane.getSize().width /2);
}
});
}
public static void main(String[] args) {
JSplitProblem jSplitProblem = new JSplitProblem();
}
}
I'm not sure, but I think you should try to pack() your frame. And if that doesn't work, try to reset the divider location after you packed the frame.
Just add the code below, and that will be fairly enough.
mainSplittedPane.setResizeWeight(0.5);

Categories

Resources