I have a JFrame which contains at the moment 4 panels. One of these panels is a keyboard and the other 3 frames are control panels for the keyboard as seen in the following picture:
I have been trying to find a way to shrink the width of the control panels with GridLayout so that they dont take up the whole width of the frame but unfortnunately my code is not working right. Addionally I would like to push the piano roll at the bottom of the screen. This is my code so far:
JFrame frame = new JFrame();
JPanel container = new JPanel();
container.setSize(1000, 1000);
container.setLayout(new GridLayout(5,5));
// add control panels to JPanel
int y = 0;
for(int i =0; i < oscillators.length; i) {
JPanel panel = new JPanel();
panel.setSize(289, 100);
panel.setBorder(Utils.WindowDesign.LINE_BORDER);
panel.setLayout(null);
container.add(oscillators[i]);
y =105;
}
// add keyboard to panel
keyboard = new PianoKeys(this);
keyboard.setFocusable(true);
container.add(keyboard);
// make frame visible
frame.setSize(1000, 1000);
frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
frame.setBackground(Color.WHITE);
frame.setLayout(new BorderLayout());
frame.add(container);
frame.setVisible(true);
Could someone perhaps explain to me why this doesnt work as expected? I am setting the width of the control panels to 289 and my grid contains 5 columns and 5 rows so I am not sure why the control panels end up expanding to the whole width. I appreciate any help you can provide!
CodePudding user response:
SetPreferredSize
is normally used for layout negotiating. In your case however SetMaxSize
on the panel.
Do not normally use null layouts.
What happened is that the default layout manager of the JFrame is a BorderLayout. This enlarges the content to the JFrame's content pane.
I am not sure whether a GridLayout is what you want. A GridBagLayout would also allow grid cells to merge. There are layouts which allow you to anchor an element to the bottom. In GridBagLayout one can use a constraint to align a smaller-than-cell component to the SOUTH (bottom). That would be with a gap.
One remark:
I am in favor of an other coding style, having one MyJFrame class with components inside. And doing:
public static void main(String[] args) {
MyJFrame frame = new MyJFrame();
SwingUtilities.invokeLater(() -> frame.setVisible());
}
This allows to use a GUI designer (=code generator), which saves a lot of experimenting, even for an experienced programmer.
CodePudding user response:
Interesting question. Therefore, I did some research.
One idea to solve: Switch from GridLayout to BoxLayout
Quoting from Documentation:
"The BoxLayout class puts components in a single row or column. It respects the components' requested maximum sizes and also lets you align components. For further details, see How to Use BoxLayout." A Visual Guide to Layout Managers
Short Example:
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
public class GridLayoutExample extends JFrame {
GridLayoutExample(){
JPanel listPane = new JPanel();
//listPane.setLayout(new GridLayout(5,0));
listPane.setLayout(new BoxLayout(listPane, BoxLayout.PAGE_AXIS));
this.add(listPane);
for(int i = 0; i < 5; i ){
JLabel imgLabel = new JLabel(generateImage(20 20 * i, 10 10 * i));
listPane.add(imgLabel);
}
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.pack();
this.setVisible(true);
}
public static void main(String[] args) {
new GridLayoutExample();
}
private static ImageIcon generateImage(int width, int height){
BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
//create random image pixel by pixel
for(int y = 0; y < height; y ){
for(int x = 0; x < width; x ){
int a = (int)(Math.random()*256); //alpha
int r = (int)(Math.random()*256); //red
int g = (int)(Math.random()*256); //green
int b = (int)(Math.random()*256); //blue
int p = (a<<24) | (r<<16) | (g<<8) | b; //pixel
img.setRGB(x, y, p);
}
}
return new ImageIcon(img);
}
}
You can compare GridLayout and BoxLayout by changing the following lines:
//listPane.setLayout(new GridLayout(5,0));
listPane.setLayout(new BoxLayout(listPane, BoxLayout.PAGE_AXIS));
Showing the difference - GridLayout:
BoxLayout:
I hope this is helpful.
Credits for random picture generation to dyclassroom.com