I have a new issue where I have reached trough all my hair all the way to the skull while scratching for a solution. I have simulated my problem underneath, (I don't know if this is normal procedure, but I tend to simplify to understand the problem and try to fix it). I need to have a two columns JPanel divided in a 70/30% portion. User will add a TON of JLabels and JTextFields, etc, all different of widths in these separate columns. I cannot use GridLayout because not all objects are the same width. When user will insert too many objects i want the entire JPanel to scroll. I have implemented 3 JPanels so far, one main that is a BoxLayout where inside there are 2 FlowLayout JPanels and in each sub JPanel I have added my objects. The problem is that I want the JScrollPane to be applied to the MainPanel and not individually to each sub JPanel or else it would be ugly. I don't know how to setSize only to the Width and not the height in such a way that the JScroll applies to my entire MainPanel. Thanks and best regards
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Toolkit;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
public class alignments {
Toolkit toolkit;
JFrame frame;
JPanel mainPanel, leftPanel, rightPanel;
public static void main(String[] args) {
alignments align = new alignments();
}
alignments() {
frame = new JFrame();
setDimm();
mainPanel = new JPanel();
leftPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 10, 5));
rightPanel = new JPanel();
mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.X_AXIS));
leftPanel.setBackground(Color.gray);
leftPanel.setBorder(BorderFactory.createLineBorder(Color.red));
rightPanel.setBackground(Color.yellow);
rightPanel.setBorder(BorderFactory.createLineBorder(Color.CYAN));
// LEFT AREA BUTTONS
String[] arry = { "FIRST BUTTON", "3", "SECOND BUTTON", "4000", "FIRST BUTTON", "3", "SECOND BUTTON", "4000",
"FIRST BUTTON", "3", "SECOND BUTTON", "4000", "FIRST BUTTON", "3", "SECOND BUTTON", "4000",
"FIRST BUTTON", "3", "SECOND BUTTON", "4000", "FIRST BUTTON", "3", "SECOND BUTTON", "4000",
"FIRST BUTTON", "3", "SECOND BUTTON", "4000", "FIRST BUTTON", "3", "SECOND BUTTON", "4000",
"FIRST BUTTON", "3", "SECOND BUTTON", "4000", "FIRST BUTTON", "3", "SECOND BUTTON", "4000",
"FIRST BUTTON", "3", "SECOND BUTTON", "4000", "FIRST BUTTON", "3", "SECOND BUTTON", "4000",
"FIRST BUTTON", "3", "SECOND BUTTON", "4000", "FIRST BUTTON", "3", "SECOND BUTTON", "4000",
"FIRST BUTTON", "3", "SECOND BUTTON", "4000", "FIRST BUTTON", "3", "SECOND BUTTON", "4000",
"FIRST BUTTON", "3", "SECOND BUTTON", "4000", "FIRST BUTTON", "3", "SECOND BUTTON", "4000",
"FIRST BUTTON", "3", "SECOND BUTTON", "4000", "FIRST BUTTON", "3", "SECOND BUTTON", "4000",
"FIRST BUTTON", "3", "SECOND BUTTON", "4000", "FIRST BUTTON", "3", "SECOND BUTTON", "4000",
"FIRST BUTTON", "3", "SECOND BUTTON", "4000", "FIRST BUTTON", "3", "SECOND BUTTON", "4000",
"FIRST BUTTON", "3", "SECOND BUTTON", "4000", "FIRST BUTTON", "3", "SECOND BUTTON", "4000",
"FIRST BUTTON", "3", "SECOND BUTTON", "4000", "FIRST BUTTON", "3", "SECOND BUTTON", "4000",
"FIRST BUTTON", "3", "SECOND BUTTON", "4000", "FIRST BUTTON", "3", "SECOND BUTTON", "4000" };
for (int i = 0; i < arry.length; i++) {
JButton button = new JButton(arry[i]);
leftPanel.add(button);
}
String[] arry2 = { "WOW", "MEGA FAIN", "TURBO", "WOW", "MEGA FAIN", "TURBO", "WOW", "MEGA FAIN", "TURBO", "WOW",
"MEGA FAIN", "TURBO", "WOW", "MEGA FAIN", "TURBO", "WOW", "MEGA FAIN", "TURBO", "WOW", "MEGA FAIN",
"TURBO", "WOW", "MEGA FAIN", "TURBO", "WOW", "MEGA FAIN", "TURBO" };
for (int i = 0; i < arry2.length; i++) {
JLabel labels = new JLabel(arry2[i]);
rightPanel.add(labels);
}
// The problem I suspect is here because of course if I set the height
// then the scroll will not work anymore. If I don't set up the sizes
// then the first FlowLayout will cover 100% of the main JPanel.
leftPanel.setMaximumSize(new Dimension(600, 600));
leftPanel.setMinimumSize(new Dimension(600, 600));
leftPanel.setPreferredSize(new Dimension(600, 600));
rightPanel.setMaximumSize(new Dimension(200, 600));
rightPanel.setMinimumSize(new Dimension(200, 600));
rightPanel.setPreferredSize(new Dimension(200, 600));
mainPanel.add(leftPanel);
mainPanel.add(rightPanel);
JScrollPane pane = new JScrollPane(mainPanel);
frame.add(pane);
frame.setVisible(true);
}
void setDimm() {
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(800, 600);
frame.getContentPane().setBackground(Color.white);
toolkit = frame.getToolkit();
Dimension size = toolkit.getScreenSize();
frame.setLocation((size.width - frame.getWidth()) / 2, (size.height - frame.getHeight()) / 2);
}
}
Damn these flow layouts. I do not know if my answer is the best way to accomplish it (doesn't feel like it) but it seems to work. Instead of an outer panel with a BoxLayout
X axis, you could use a JSplitPane. It allows user to choose the percentage of the right/left panel. However, if you insist of having it with 70% percentage you will have to add a ComponentListener#componentResized
listener to your frame in order to persist this percentage. Some comments inside the code. I tried a lot of variations and only this seem to work fine. Try to spend some more time for changes i have made and forgot to mention with comment.
public class Alignments { //Class names should start with an uppercase :)
private JFrame frame;
private JPanel leftPanel, rightPanel;
public static void main(String[] args) {
//All swing apps must run on their own thread
SwingUtilities.invokeLater(() -> {
Alignments align = new Alignments();
});
}
public Alignments() {
frame = new JFrame();
frame.setLayout(new BorderLayout());
leftPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 10, 5));
rightPanel = new JPanel(new FlowLayout());
leftPanel.setBackground(Color.gray);
leftPanel.setBorder(BorderFactory.createLineBorder(Color.red));
rightPanel.setBackground(Color.yellow);
rightPanel.setBorder(BorderFactory.createLineBorder(Color.CYAN));
// LEFT AREA BUTTONS
String[] arry = { "FIRST BUTTON", "3", "SECOND BUTTON", "4000", "FIRST BUTTON", "3", "SECOND BUTTON", "4000", "FIRST BUTTON",
"3", "SECOND BUTTON", "4000", "FIRST BUTTON", "3", "SECOND BUTTON", "4000", "FIRST BUTTON", "3", "SECOND BUTTON",
"4000", "FIRST BUTTON", "3", "SECOND BUTTON", "4000", "FIRST BUTTON", "3", "SECOND BUTTON", "4000", "FIRST BUTTON",
"3", "SECOND BUTTON", "4000", "FIRST BUTTON", "3", "SECOND BUTTON", "4000", "FIRST BUTTON", "3", "SECOND BUTTON",
"4000", "FIRST BUTTON", "3", "SECOND BUTTON", "4000", "FIRST BUTTON", "3", "SECOND BUTTON", "4000", "FIRST BUTTON",
"3", "SECOND BUTTON", "4000", "FIRST BUTTON", "3", "SECOND BUTTON", "4000", "FIRST BUTTON", "3", "SECOND BUTTON",
"4000", "FIRST BUTTON", "3", "SECOND BUTTON", "4000", "FIRST BUTTON", "3", "SECOND BUTTON", "4000", "FIRST BUTTON",
"3", "SECOND BUTTON", "4000", "FIRST BUTTON", "3", "SECOND BUTTON", "4000", "FIRST BUTTON", "3", "SECOND BUTTON",
"4000", "FIRST BUTTON", "3", "SECOND BUTTON", "4000", "FIRST BUTTON", "3", "SECOND BUTTON", "4000", "FIRST BUTTON",
"3", "SECOND BUTTON", "4000", "FIRST BUTTON", "3", "SECOND BUTTON", "4000", "FIRST BUTTON", "3", "SECOND BUTTON",
"4000", "FIRST BUTTON", "3", "SECOND BUTTON", "4000", "FIRST BUTTON", "3", "SECOND BUTTON", "4000", "FIRST BUTTON",
"3", "SECOND BUTTON", "4000", "FIRST BUTTON", "3", "SECOND BUTTON", "4000", "FIRST BUTTON", "3", "SECOND BUTTON",
"40001", "40001", "40001", "40001", "40001", "40001", "40001", "40001", "40001", "40003" };
for (int i = 0; i < arry.length; i++) {
JButton button = new JButton(arry[i]);
leftPanel.add(button);
}
String[] arry2 = { "WOW", "MEGA FAIN", "TURBO", "WOW", "MEGA FAIN", "TURBO", "WOW", "MEGA FAIN", "TURBO", "WOW", "MEGA FAIN",
"TURBO", "WOW", "MEGA FAIN", "TURBO", "WOW", "MEGA FAIN", "TURBO", "WOW", "MEGA FAIN", "TURBO", "WOW", "MEGA FAIN",
"TURBO", "WOW", "MEGA FAIN", "TURBO" };
for (int i = 0; i < arry2.length; i++) {
JLabel labels = new JLabel(arry2[i]);
rightPanel.add(labels);
}
JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
splitPane.setLeftComponent(leftPanel);
splitPane.setRightComponent(rightPanel);
splitPane.setDividerSize(0); //User cannot move the divider
JScrollPane scrollPane = new JScrollPane(splitPane);
frame.add(scrollPane);
frame.addComponentListener(new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent e) {
int width = frame.getWidth() * 70 / 100; //70% of frame's width
splitPane.setDividerLocation(width);
Component comp = getComponentWithBiggestHeight(leftPanel);
if (comp != null) {
int trueHeightOfLeftPanel = comp.getBounds().y + comp.getHeight() + 5; //+ some bottom insets?
//Setting splitPane's width to 1 will make it being wrapped horizontally
splitPane.setPreferredSize(new Dimension(1, trueHeightOfLeftPanel));
}
}
});
setDimm();
frame.setVisible(true);
}
private Component getComponentWithBiggestHeight(JPanel panel) {
Component component = null;
int max = -1;
for (Component c : panel.getComponents()) {
if (c.getBounds().y > max) {
component = c;
}
}
return component;
}
public void setDimm() {
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(800, 600);
frame.getContentPane().setBackground(Color.white);
frame.setLocationRelativeTo(null); //to the center of the screen
}
}
Tiny Preview: