我的 Java Swing JPanel 居中功能不起作用。为什么?
My Java Swing JPanel centering function does not work. Why?
中间的"JPanel",我想把对齐操作移到separate function,但不知怎么的不行。这些操作都是在本地进行的,所有工作都很好。
desCont = new DesignController();
JPanel centerBox = desCont.createCenterPanel();
this.add(centerBox);
设计控制器class 来源:
public class DesignController {
(...)
public JPanel createCenterPanel(){
JPanel centerPanel = new JPanel();
JPanel hbox = new JPanel();
JPanel vbox = new JPanel();
centerPanel.setLayout(new BoxLayout(centerPanel, BoxLayout.X_AXIS ));
centerPanel.add(Box.createHorizontalGlue());
centerPanel.add(hbox);
centerPanel.add(Box.createHorizontalGlue());
hbox.setLayout(new BoxLayout(hbox, BoxLayout.Y_AXIS ));
hbox.add(Box.createVerticalGlue());
hbox.add(vbox);
hbox.add(Box.createVerticalGlue());
return centerPanel;
}
}
更新:
示例文件重构问题的必要元素:
public class CenterTest {
private JFrame frame;
private static CardLayout cardLayout = new CardLayout();
private JPanel headPanel;
private static JPanel contentPanel;
private JPanel footerPanel;
private static JPanel mainPanel;
private AppConstants appVars;
-->default main method (generated by IDE)
-->default constructor (generated by IDE)
/**
* Initialize the contents of the frame.
*/
private void initialize() {
appVars = new AppConstants();
frame = new JFrame();
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
frame.setBounds(100, 100, appVars.initWidth, appVars.initHeight);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainPanel = new JPanel();
frame.getContentPane().add(mainPanel, BorderLayout.CENTER);
mainPanel.setLayout(new BorderLayout(0, 0));
headPanel = new JPanel();
headPanel.setBackground(Color.LIGHT_GRAY);
headPanel.setPreferredSize(new Dimension( appVars.initHeaderPanelWidth, appVars.headerPanelHeight ));
mainPanel.add(headPanel, BorderLayout.NORTH);
contentPanel = new JPanel();
contentPanel.setPreferredSize(new Dimension(appVars.initContentWidth, appVars.initContentHeight));
mainPanel.add(contentPanel, BorderLayout.CENTER);
contentPanel.setLayout(cardLayout);
footerPanel = new JPanel();
footerPanel.setBackground(Color.GREEN);
footerPanel.setPreferredSize(new Dimension(appVars.initFooterPanelWidth, appVars.footerPanelHeight));
mainPanel.add(footerPanel, BorderLayout.SOUTH);
addCard(new CenterPanel(), "center-panel");
}
public static void addCard(JPanel panel, String name){
contentPanel.add(panel, name);
cardLayout.show(contentPanel, name);
}
}
class CenterPanel extends JPanel {
private static final long serialVersionUID = 1L;
/**
* Include DesignController class.
*/
private DesignController desCont;
/**
* Include global variables class.
*/
private AppConstants appVars;
public CenterPanel(){
appVars = new AppConstants();
desCont = new DesignController();
/* ------------ THIS SECTION IS NOT CORRECTLY WORKING ----------------- */
JPanel hBox = desCont.createCenterPanel();
hBox.setBackground(Color.YELLOW);
this.add(hBox);
/* ------------ THIS SECTION IS NOT CORRECTLY WORKING ----------------- */
/* ------------ THIS SECTION IS CORRECTLY WORKING ----------------- */
/*JPanel hbox = new JPanel();
JPanel vbox = new JPanel();
vbox.setBackground(new Color(0, 204, 204));
vbox.setPreferredSize(new Dimension(appVars.initContentWidth, appVars.initContentHeight));
setLayout(new BoxLayout(this, BoxLayout.X_AXIS ));
add(Box.createHorizontalGlue());
add(hbox);
add(Box.createHorizontalGlue());
hbox.setLayout(new BoxLayout(hbox, BoxLayout.Y_AXIS ));
hbox.add(Box.createVerticalGlue());
hbox.add(vbox);
hbox.add(Box.createVerticalGlue());*/
/* ------------ THIS SECTION IS CORRECTLY WORKING ----------------- */
}
}
class DesignController {
private AppConstants appVars = new AppConstants();
public JPanel createCenterPanel(){
JPanel centerPanel = new JPanel();
JPanel hbox = new JPanel();
JPanel vbox = new JPanel();
vbox.setBackground(new Color(0, 204, 204));
vbox.setPreferredSize(new Dimension(appVars.initContentWidth, appVars.initContentHeight));
centerPanel.setLayout(new BoxLayout(centerPanel, BoxLayout.X_AXIS ));
centerPanel.add(Box.createHorizontalGlue());
centerPanel.add(hbox);
centerPanel.add(Box.createHorizontalGlue());
hbox.setLayout(new BoxLayout(hbox, BoxLayout.Y_AXIS ));
hbox.add(Box.createVerticalGlue());
hbox.add(vbox);
hbox.add(Box.createVerticalGlue());
return centerPanel;
}
}
class AppConstants {
/**
* Define initial width of window <br/>
* <b>900</b>
*/
public int initWidth = 900;
/**
* Define initial height of window <br/>
* <b>600</b>
*/
public int initHeight = 600;
/**
* Define initial width of window header, same as window width <br/>
* <b>900</b>
*/
public int initHeaderPanelWidth = initWidth;
/**
* Define height of windows header panel <br/>
* <b>80</b>
*/
public int headerPanelHeight = 80;
/**
* Define initial width of window footer, same as window width <br/>
* <b>900</b>
*/
public int initFooterPanelWidth = initWidth;
/**
* Define height of windows footer panel <br/>
* <b>50</b>
*/
public int footerPanelHeight = 50;
/**
* Define initial width of content panel, same as window width <br/>
* <b>900</b>
*/
public int initContentWidth = 900;
/**
* Define height of content panel <br/>
* <b>window initial height - (header panel height + footer panel height)</b>
*/
public int initContentHeight = initHeight - (headerPanelHeight + footerPanelHeight);
}
你的做法是错误的。你不能 return "center panel"。
为了使面板居中,您需要这样的结构:
HorizontalPanel
VerticalPanel
CenterPanel
vertical/horizontal 面板是包装器,您需要将水平面板添加到框架中,因为它是组件的父面板。
如果将 "CenterPanel" 添加到框架,那么您将丢失 vertical/horizontal 包装器面板,因为 Swing 组件只能有一个父级。因此框架成为 "CenterPanel".
的新父级
因此您的方法设计需要类似于:
public static Component centerPanel(Component panelToBeCentered)
{
JPanel vertical = ...
vertical.add( panelToBeCentered );
JPanel horizontal = ...
horizontal.add( vertical );
return horizontal;
}
要使用代码,您需要执行以下操作:
JPanel center = new JPanel();
center.add(...);
frame.add( DesignController.centerPanel( center ) );
请注意,在使用 BoxLayout 时,您可以使用方便的静态方法:
Box vertical = Box.createVerticalBox();
Box horizontal Box.createHorizontalBox();
创建一个容器来容纳您的组件。
更简单的是您不需要使用嵌套框。您可以只使用 GridBagLayout
。 GridBagLayout 的默认约束会导致组件居中:
JPanel center = new JPanel();
JPanel wrapper = new JPanel( new GridBagLayout() );
wrapper.add(center, new GridBagConstraints());
frame.add( wrapper );
我修改的函数,基于@camickr 的回答:
将 parentPanel 布局设置为 BoxLayout.X_AXIS 并添加一个新的 JPanel 作为hbox horizontalGlues 之间。之后我将 hbox 布局设置为 BoxLayout.Y_AXIS 并创建一个新的 JPanel inside hbox 作为vbox verticalGlues.
public JPanel createCenterPanel(JComponent parentPanel){
JPanel hbox = new JPanel();
JPanel vbox = new JPanel();
vbox.setBackground(new Color(0, 0, 255));
parentPanel.setLayout(new BoxLayout(parentPanel, BoxLayout.X_AXIS ));
parentPanel.add(Box.createHorizontalGlue());
parentPanel.add(hbox);
parentPanel.add(Box.createHorizontalGlue());
hbox.setLayout(new BoxLayout(hbox, BoxLayout.Y_AXIS ));
hbox.add(Box.createVerticalGlue());
hbox.add(vbox);
hbox.add(Box.createVerticalGlue());
return hbox;
}
中间的"JPanel",我想把对齐操作移到separate function,但不知怎么的不行。这些操作都是在本地进行的,所有工作都很好。
desCont = new DesignController();
JPanel centerBox = desCont.createCenterPanel();
this.add(centerBox);
设计控制器class 来源:
public class DesignController {
(...)
public JPanel createCenterPanel(){
JPanel centerPanel = new JPanel();
JPanel hbox = new JPanel();
JPanel vbox = new JPanel();
centerPanel.setLayout(new BoxLayout(centerPanel, BoxLayout.X_AXIS ));
centerPanel.add(Box.createHorizontalGlue());
centerPanel.add(hbox);
centerPanel.add(Box.createHorizontalGlue());
hbox.setLayout(new BoxLayout(hbox, BoxLayout.Y_AXIS ));
hbox.add(Box.createVerticalGlue());
hbox.add(vbox);
hbox.add(Box.createVerticalGlue());
return centerPanel;
}
}
更新:
示例文件重构问题的必要元素:
public class CenterTest {
private JFrame frame;
private static CardLayout cardLayout = new CardLayout();
private JPanel headPanel;
private static JPanel contentPanel;
private JPanel footerPanel;
private static JPanel mainPanel;
private AppConstants appVars;
-->default main method (generated by IDE)
-->default constructor (generated by IDE)
/**
* Initialize the contents of the frame.
*/
private void initialize() {
appVars = new AppConstants();
frame = new JFrame();
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
frame.setBounds(100, 100, appVars.initWidth, appVars.initHeight);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainPanel = new JPanel();
frame.getContentPane().add(mainPanel, BorderLayout.CENTER);
mainPanel.setLayout(new BorderLayout(0, 0));
headPanel = new JPanel();
headPanel.setBackground(Color.LIGHT_GRAY);
headPanel.setPreferredSize(new Dimension( appVars.initHeaderPanelWidth, appVars.headerPanelHeight ));
mainPanel.add(headPanel, BorderLayout.NORTH);
contentPanel = new JPanel();
contentPanel.setPreferredSize(new Dimension(appVars.initContentWidth, appVars.initContentHeight));
mainPanel.add(contentPanel, BorderLayout.CENTER);
contentPanel.setLayout(cardLayout);
footerPanel = new JPanel();
footerPanel.setBackground(Color.GREEN);
footerPanel.setPreferredSize(new Dimension(appVars.initFooterPanelWidth, appVars.footerPanelHeight));
mainPanel.add(footerPanel, BorderLayout.SOUTH);
addCard(new CenterPanel(), "center-panel");
}
public static void addCard(JPanel panel, String name){
contentPanel.add(panel, name);
cardLayout.show(contentPanel, name);
}
}
class CenterPanel extends JPanel {
private static final long serialVersionUID = 1L;
/**
* Include DesignController class.
*/
private DesignController desCont;
/**
* Include global variables class.
*/
private AppConstants appVars;
public CenterPanel(){
appVars = new AppConstants();
desCont = new DesignController();
/* ------------ THIS SECTION IS NOT CORRECTLY WORKING ----------------- */
JPanel hBox = desCont.createCenterPanel();
hBox.setBackground(Color.YELLOW);
this.add(hBox);
/* ------------ THIS SECTION IS NOT CORRECTLY WORKING ----------------- */
/* ------------ THIS SECTION IS CORRECTLY WORKING ----------------- */
/*JPanel hbox = new JPanel();
JPanel vbox = new JPanel();
vbox.setBackground(new Color(0, 204, 204));
vbox.setPreferredSize(new Dimension(appVars.initContentWidth, appVars.initContentHeight));
setLayout(new BoxLayout(this, BoxLayout.X_AXIS ));
add(Box.createHorizontalGlue());
add(hbox);
add(Box.createHorizontalGlue());
hbox.setLayout(new BoxLayout(hbox, BoxLayout.Y_AXIS ));
hbox.add(Box.createVerticalGlue());
hbox.add(vbox);
hbox.add(Box.createVerticalGlue());*/
/* ------------ THIS SECTION IS CORRECTLY WORKING ----------------- */
}
}
class DesignController {
private AppConstants appVars = new AppConstants();
public JPanel createCenterPanel(){
JPanel centerPanel = new JPanel();
JPanel hbox = new JPanel();
JPanel vbox = new JPanel();
vbox.setBackground(new Color(0, 204, 204));
vbox.setPreferredSize(new Dimension(appVars.initContentWidth, appVars.initContentHeight));
centerPanel.setLayout(new BoxLayout(centerPanel, BoxLayout.X_AXIS ));
centerPanel.add(Box.createHorizontalGlue());
centerPanel.add(hbox);
centerPanel.add(Box.createHorizontalGlue());
hbox.setLayout(new BoxLayout(hbox, BoxLayout.Y_AXIS ));
hbox.add(Box.createVerticalGlue());
hbox.add(vbox);
hbox.add(Box.createVerticalGlue());
return centerPanel;
}
}
class AppConstants {
/**
* Define initial width of window <br/>
* <b>900</b>
*/
public int initWidth = 900;
/**
* Define initial height of window <br/>
* <b>600</b>
*/
public int initHeight = 600;
/**
* Define initial width of window header, same as window width <br/>
* <b>900</b>
*/
public int initHeaderPanelWidth = initWidth;
/**
* Define height of windows header panel <br/>
* <b>80</b>
*/
public int headerPanelHeight = 80;
/**
* Define initial width of window footer, same as window width <br/>
* <b>900</b>
*/
public int initFooterPanelWidth = initWidth;
/**
* Define height of windows footer panel <br/>
* <b>50</b>
*/
public int footerPanelHeight = 50;
/**
* Define initial width of content panel, same as window width <br/>
* <b>900</b>
*/
public int initContentWidth = 900;
/**
* Define height of content panel <br/>
* <b>window initial height - (header panel height + footer panel height)</b>
*/
public int initContentHeight = initHeight - (headerPanelHeight + footerPanelHeight);
}
你的做法是错误的。你不能 return "center panel"。
为了使面板居中,您需要这样的结构:
HorizontalPanel
VerticalPanel
CenterPanel
vertical/horizontal 面板是包装器,您需要将水平面板添加到框架中,因为它是组件的父面板。
如果将 "CenterPanel" 添加到框架,那么您将丢失 vertical/horizontal 包装器面板,因为 Swing 组件只能有一个父级。因此框架成为 "CenterPanel".
的新父级因此您的方法设计需要类似于:
public static Component centerPanel(Component panelToBeCentered)
{
JPanel vertical = ...
vertical.add( panelToBeCentered );
JPanel horizontal = ...
horizontal.add( vertical );
return horizontal;
}
要使用代码,您需要执行以下操作:
JPanel center = new JPanel();
center.add(...);
frame.add( DesignController.centerPanel( center ) );
请注意,在使用 BoxLayout 时,您可以使用方便的静态方法:
Box vertical = Box.createVerticalBox();
Box horizontal Box.createHorizontalBox();
创建一个容器来容纳您的组件。
更简单的是您不需要使用嵌套框。您可以只使用 GridBagLayout
。 GridBagLayout 的默认约束会导致组件居中:
JPanel center = new JPanel();
JPanel wrapper = new JPanel( new GridBagLayout() );
wrapper.add(center, new GridBagConstraints());
frame.add( wrapper );
我修改的函数,基于@camickr 的回答:
将 parentPanel 布局设置为 BoxLayout.X_AXIS 并添加一个新的 JPanel 作为hbox horizontalGlues 之间。之后我将 hbox 布局设置为 BoxLayout.Y_AXIS 并创建一个新的 JPanel inside hbox 作为vbox verticalGlues.
public JPanel createCenterPanel(JComponent parentPanel){
JPanel hbox = new JPanel();
JPanel vbox = new JPanel();
vbox.setBackground(new Color(0, 0, 255));
parentPanel.setLayout(new BoxLayout(parentPanel, BoxLayout.X_AXIS ));
parentPanel.add(Box.createHorizontalGlue());
parentPanel.add(hbox);
parentPanel.add(Box.createHorizontalGlue());
hbox.setLayout(new BoxLayout(hbox, BoxLayout.Y_AXIS ));
hbox.add(Box.createVerticalGlue());
hbox.add(vbox);
hbox.add(Box.createVerticalGlue());
return hbox;
}