I'm writing a Java GUI application, and is something like this:
JPanel main = new JPanel(new GridLayout(1, 1));
JPanel buttonPanel = new JPanel();
buttonPanel.add(button);
main.add(buttonPanel)
I want to add a button to the grid, but i want it centered on the grid panel.
Adding the button to another JPanel allows me to center it to the Grid.
Is there any shorter way to do this?
For example:
JPanel main = new JPanel(new GridLayout(1, 1));
JPanel buttonPanel = JPanel();
main.add(new JPanel().add(button));
This is not working for me.
Thanks :)
I agree with the other commenters that reducing the number of lines of code probably isn't as neccessary as you think it is: Generally speaking, your goal should be to reduce code complexity, not code length, and efforts to minimize length often lead to code that is more complex/hard to understand rather than less.
That said, applying basic OO principles can enable you to shorten your code while maintaining (if not increasing) its clarity:
class CenteredContentPanel extends JPanel {
CenteredContentPanel(JComponent addTo){
this.setLayout(new GridLayout(1,1));
JPanel parentPanel = new JPanel();
parentPanel.add(addTo);
this.add(parentPanel);
}
}
Now, you can add as many of these as you please to a parent container with a single line of code:
JPanel main = new JPanel();
main.add(new CenteredContentPanel(button));
//repeat above line to add as many "centered" components as you need to
(code is untested, as I don't have access to an IDE at the moment, but you get the gist...)
You need to add main to the frame:
add(main.add(new JPanel().add(button)));
This works fine for me:
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class MyFrameClass extends JFrame
{
public MyFrameClass(){
JPanel main = new JPanel(new GridLayout(1, 1));
JButton button = new JButton();
add(main.add(new JPanel().add(button)));
setSize(800,600);
setVisible(true);
}
public static void main (String [] args)
{
new MyFrameClass();
}
}
Related
I am just learning Swing. I am trying my best to create a menu for a nutritional value calculator. I don't understand why the setVisibleRowCount() method does not work. I set the value to 1, but the rows are still visible. I would love a good explanation on the problem.
package inFine;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Main {
public static void main(String[] args) {
JFrame frame=new JFrame("Calculator Valori nutritive");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.setSize(500,500);
frame.setLocation(500,100);
frame.setLayout(new BorderLayout());
String []MicDejun= {"Cereale","Ou fiert","Ou prajit","Omleta","Salata rosii","Salata cu bacon ","Ovaz","Sandwitch"};
String []Pranz= {"Spanac","Cartofi prajiti","Linte","Piure","Orez Simplu", "Orez Legume","Brocoli","Piept de pui "
,"Macrou","Somon","Dorada","Ceafa de porc"};
String []Cina= {"Lasagna","Paste","Pizza","Fasole carnati","Encilada","Tigaie picanta","Tigaie tiganeasca","Tocanita"};
String []Snack= {"Chips Lays","Chips Lidl","Chips Carefur","Ciocolata","Corn","Inghetata","Placinta"};
JPanel P_Centru,P_Nord = new JPanel(),P_South=new JPanel();
JPanel P_MicDejun,P_Pranz,P_Cina,P_Snack;
JLabel T_MicDejun=new JLabel("Mic Dejun: ");
JLabel T_Pranz=new JLabel("Pranz: ");
JLabel T_Cina=new JLabel("Cina: ");
JLabel T_Snack=new JLabel("Snack: ");
JList <String>L_MicDejun=new JList<>(MicDejun);
L_MicDejun.setVisibleRowCount(1);
JList <String>L_Pranz=new JList<>(Pranz);
L_Pranz.setVisibleRowCount(1);
JList <String>L_Cina=new JList<>(Cina);
L_Cina.setVisibleRowCount(1);
JList <String>L_Snacks=new JList<>(Snack);
L_Snacks.setVisibleRowCount(1);
JScrollPane scr1=new JScrollPane(L_MicDejun);
JScrollPane scr2=new JScrollPane(L_Pranz);
JScrollPane scr3=new JScrollPane(L_Cina);
JScrollPane scr4=new JScrollPane(L_Snacks);
P_MicDejun=new JPanel();
set(T_MicDejun);
P_MicDejun.add(T_MicDejun);
P_MicDejun.add(L_MicDejun);
P_MicDejun.add(scr1);
P_Pranz=new JPanel();
set(T_Pranz);
P_Pranz.add(T_Pranz);
P_Pranz.add(L_Pranz);
P_Pranz.add(scr2);
P_Cina=new JPanel();
set(T_Cina);
P_Cina.add(T_Cina);
P_Cina.add(L_Cina);
P_Cina.add(scr3);
P_Snack=new JPanel();
set(T_Snack);
P_Snack.add(T_Snack);
P_Snack.add(L_Snacks);
P_Snack.add(scr4);
P_Centru=new JPanel();
P_Centru.setLayout(new GridLayout(4,1));
P_Centru.add(P_MicDejun);
P_Centru.add(P_Pranz);
P_Centru.add(P_Cina);
P_Centru.add(P_Snack);
frame.add(BorderLayout.NORTH,P_Nord);
frame.add(BorderLayout.CENTER,P_Centru);
frame.add(BorderLayout.SOUTH,P_South);
}
public static void set (JLabel a)
{
a.setFont(new java.awt.Font("Arial",Font.PLAIN,12));
a.setForeground(Color.black);
}
}
The fundamental problem is that a component can only appear in one container. The tables are added to the scroll panes in their constructor. They do not need to be separately added to .. anything else. Here is the immediate effect of doing that.
Note: Adding a call to frame.pack(); after everything else in the constructor would make the components in the GUI appear more reliably. There are other problems with the code as well, but the important things are the basics covered above.
I'm using the NetBeans GUI builder to handle my layout (I'm terrible with LayoutManagers) and am trying to place a simple JLabel so that it is always centered (horizontally) inside its parent JPanel. Ideally, this would maintain true even if the JPanel was resized, but if that's a crazy amount of coding than it is sufficient to just be centered when the JPanel is first created.
I'm bad enough trying to handle layouts myself, but since the NetBeans GUI Builder autogenerates immutable code, it's been impossible for me to figure out how to do this centering, and I haven't been able to find anything online to help me.
Thanks to anybody who can steer me in the right direction!
Here are four ways to center a component:
import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;
class CenterComponent {
public static JLabel getLabel(String text) {
return getLabel(text, SwingConstants.LEFT);
}
public static JLabel getLabel(String text, int alignment) {
JLabel l = new JLabel(text, alignment);
l.setBorder(new LineBorder(Color.RED, 2));
return l;
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JPanel p = new JPanel(new GridLayout(2,2,4,4));
p.setBackground(Color.black);
p.setBorder(new EmptyBorder(4,4,4,4));
JPanel border = new JPanel(new BorderLayout());
border.add(getLabel(
"Border", SwingConstants.CENTER), BorderLayout.CENTER);
p.add(border);
JPanel gridbag = new JPanel(new GridBagLayout());
gridbag.add(getLabel("GridBag"));
p.add(gridbag);
JPanel grid = new JPanel(new GridLayout());
grid.add(getLabel("Grid", SwingConstants.CENTER));
p.add(grid);
// from #0verbose
JPanel box = new JPanel();
box.setLayout(new BoxLayout(box, BoxLayout.X_AXIS ));
box.add(Box.createHorizontalGlue());
box.add(getLabel("Box"));
box.add(Box.createHorizontalGlue());
p.add(box);
JFrame f = new JFrame("Streeeetch me..");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setContentPane(p);
f.pack();
f.setLocationByPlatform(true);
f.setVisible(true);
}
});
}
}
By using Borderlayout, you can put any of JComponents to the CENTER area. For an example, see an answer to Stack Overflow question Get rid of the gap between JPanels. This should work.
Even with BoxLayout you can achieve that:
JPanel listPane = new JPanel();
listPane.setLayout(new BoxLayout(listPane, BoxLayout.X_AXIS ));
JLabel label = new JLabel();
listPane.add(Box.createHorizontalGlue());
listPane.add(label);
listPane.add(Box.createHorizontalGlue());
mKorbel's solution is perfect for your goal. Anyway I always like to suggest BoxLayout because it's very flexible.
Mara: "thanks for your response, however the NetBeans GUI Build uses GroupLayout and this is not overridable."
Not true! Right click anywhere inside JFrame (or any other GUI container) in NetBeans GUI builder and select "Set Layout". By default is selected "Free Design", which is Group layout, but you can select any other layout including Border layout as advised by mKorbel.
There's many ways to do this, depending on the layout manager(s) you use. I suggest you read the Laying Out Components Within a Container tutorial.
I believe the following will work, regardless of layout manager:
JLabel.setHorizontalAlignment(SwingConstants.CENTER)
I know this question has been asked a lot and I have done my research but still can not find anything. Below is proof of this before anyone gets upset:
I found this link:
https://coderanch.com/t/563764/java/Blank-Frame-Panel
and this:
Adding panels to frame, but not showing when app is run
and this:
Why shouldn't I call setVisible(true) before adding components?
and this:
JPanel not showing in JFrame?
But the first question says use repaint which I tried with no fix and the second and third to last questions talk about putting setVisible after components added which I have.
The last one talks about making the users JPanelArt a extension (done so) of JPanel instead of JFrame and not to make a frame in a frame constructor (also have not done)
When ever I run this I just get a blank frame, as if the panel was never added in.
I apologise if I have missed something in those links. Anyway below is my classes:
GUI.java (extends JFrame)
package javaapplication2;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class GUI extends JFrame{
public GUI(String name) {
super(name);
getContentPane().setLayout(null);
JPanel myPanel1 = new GUIPanel();
myPanel1.setLocation(20, 20);
getContentPane().add(myPanel1);
setDefaultCloseOperation(EXIT_ON_CLOSE);
pack();
setResizable(true);
}
public static void main(String[] args) {
JFrame frame = new GUI("Game");
frame.setVisible(true);
}
}
GUIPanel.java (extends JPanel)
package javaapplication2;
import java.awt.*;
import javax.swing.*;
public class GUIPanel extends JPanel {
JButton start;
JButton inspect1;
JButton inspect2;
JButton inspect3;
JButton suspect;
public GUIPanel() {
setLayout(new BorderLayout());
start = new JButton("Start Game");
inspect1 = new JButton("Inspect 1");
inspect2 = new JButton("Inspect 2");
inspect3 = new JButton("Inspect 3");
suspect = new JButton("Choose Suspect");
add(start, BorderLayout.WEST);
add(inspect1, BorderLayout.WEST);
add(inspect2, BorderLayout.WEST);
add(inspect3, BorderLayout.WEST);
add(suspect, BorderLayout.WEST);
}
}
I know it is very simple, but that is because I am following a tutorial from my lecturer to get the hang of things as I previously used a GUI builder which someone in this community pointed out to me is not good to start with (very correct!)
The issue lies in your GUI class when you call getContentPane().setLayout(null). Because of this method call, your JFrame is not displaying anything. If you remove it, your elements should show up.
I also noticed that you were setting each JButton to have a constraint of BorderLayout.WEST. This will most likely put your JButtons on top of each other and render only one of them.
I have this incredibly easy task of wanting a nice centered JPanel inside another JPanel. The parent is set to 900, 550, and the child should be approximately 200,400 or so.
To do this, I thought giving the parent a BorderLayout and then setting the setPreferredSize(200, 400) of the child. This child would be in the CENTER. Two empty JPanels would be on the EAST and WEST. Of course this did not work. Giving the two sidepanels a setPreferredSize() of course DID work. Problem with this is that narrowing the Frame causes the center pane to go away.
Here's some sample code that should give show the issue:
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Component;
import java.awt.Dimension;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class Temporary {
public static Temporary myObj = null;
private JFrame mainFrame;
public void go(){
mainFrame = new JFrame("Swing");
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainFrame.setPreferredSize(new Dimension(900,550));
JPanel mainCards = new JPanel(new CardLayout());
mainCards.add(loginLayer(), "Login");
mainFrame.setContentPane(mainCards);
mainFrame.pack();
mainFrame.setLocationRelativeTo(null);
mainFrame.setVisible(true);
}
public JPanel loginLayer(){
JPanel masterPane = new JPanel(new BorderLayout());
JPanel centerPane = new JPanel();
centerPane.setLayout(new BoxLayout(centerPane, BoxLayout.Y_AXIS));
centerPane.setPreferredSize(new Dimension(100,200));
JLabel label = new JLabel("Swing is overly");
label.setAlignmentX(Component.CENTER_ALIGNMENT);
centerPane.add(label);
JButton button = new JButton("complicated");
button.setAlignmentX(Component.CENTER_ALIGNMENT);
centerPane.add(button);
JTextField textField = new JTextField(10);
centerPane.add(textField);
JPanel filler = new JPanel();
JPanel filler2 = new JPanel();
masterPane.add(filler, BorderLayout.WEST);
masterPane.add(centerPane, BorderLayout.CENTER);
masterPane.add(filler2, BorderLayout.EAST);
return masterPane;
}
public static void main(String[] args){
myObj = new Temporary();
myObj.go();
}
}
BorderLayout will, by it's nature, give as much of the available space as it can to the CENTER component. This is how it's designed.
If you want the component to be centered within the parent container, BUT maintain it's preferred size, you should consider using a GridBagLayout instead. Without any additional constraints, this should achieve the result you're after
For example...
public JPanel loginLayer(){
JPanel masterPane = new JPanel(new GridBagLayout);
JPanel centerPane = new JPanel();
centerPane.setLayout(new BoxLayout(centerPane, BoxLayout.Y_AXIS));
JLabel label = new JLabel("Swing is overly");
label.setAlignmentX(Component.CENTER_ALIGNMENT);
centerPane.add(label);
JButton button = new JButton("complicated");
button.setAlignmentX(Component.CENTER_ALIGNMENT);
centerPane.add(button);
JTextField textField = new JTextField(10);
centerPane.add(textField);
masterPane.add(centerPane);
// Add additional borders to providing padding around the center pane
// as you need
return masterPane;
}
I would also avoid actively setting the preferred size of component in this way, as it's possible that the components you're adding to it will exceed your expectations, instead, make use of things like EmptyBorder (for example) to add additional white space arouond the component and it's contents
In Java Swing, you generally want to avoid creating a bunch of statically positioned items with preferred sizes and absolute positions, because things get weird with resizing (as you've noticed). Instead you want to rely on the fluid LayoutManagers. There is an excellent tutorial here. Or, if you want to supply a mock-up of some sort to show the actual UI you are trying to create, I could provide some more feedback.
So I have a slight issue with adding two JPanels to a main main panel. I've put it as a quick example of what I want to do since you don't want to be looking through loads of lines of unnecessary code :). I want panel one to be added first (north) and then panel two (south). I've tried using Border layout and positioning them invoking north and south on BorderLayout when adding the panels but still no luck.
Thanks in advance.
private JPanel one,two;
public Example(){
one = new JPanel();
one.setSize(new Dimension(400,400));
two = new JPanel(new GridLayout(7,8));
two.setSize(new Dimension(400,400));
one.setBackground(Color.BLACK);
two.setBackground(Color.BLUE);
JPanel mainpanel = new JPanel();
mainpanel.setBackground(Color.orange);
mainpanel.add(one);
mainpanel.add(two);
add(mainpanel);
setSize(500,500);
setVisible(true);
}
If you want to use BorderLayout, then BorderLayout.CENTER takes up as much space as it can, and the other directions take only what they need. If you add extra stuff to the JPanels, they will get bigger, based on the needs of the objects they contain.
If you want to just divide the space evenly within the main JPanel, try this:
JPanel mainpanel = new JPanel(new GridLayout(2, 1));
That creates a GridLayout with 2 rows and 1 column...
Try this code. There was issue that apparently if you install grid layout on a panel and you add no components it will not take space.
import java.awt.BorderLayout;
import java.awt.Color;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Example extends JFrame
{
private JPanel one, two;
public Example()
{
one = new JPanel();
two = new JPanel();///new GridLayout(7, 8));
one.setBackground(Color.BLACK);
two.setBackground(Color.BLUE);
JPanel mainpanel = new JPanel(new BorderLayout());
mainpanel.setBackground(Color.orange);
mainpanel.add(one, BorderLayout.NORTH);
mainpanel.add(two, BorderLayout.SOUTH);
setContentPane(mainpanel);
setSize(500, 500);
setVisible(true);
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
Example f = new Example();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
});
}
}
GridLayout ignores the values set in setSize method of contained components. If you want to control the size of each component, consider using GridBagLayout.