Java 尝试使用GridBagLayout获得swing菜单
我正在尝试构建一个包含两个垂直列的应用程序,锚定在左侧, 右边有一个大盒子。我可以把第一份菜单放在右边, 但由于某些原因,第二个菜单不会出现在第一个菜单旁边。我已经读到一些关于额外的空间被推向最后一列和最后一行(右边)。我该怎么处理呢 另外,我正在使用网格袋布局 以下是我得到的: 主用户视图类: 软件包图形用户界面Java 尝试使用GridBagLayout获得swing菜单,java,swing,layout-manager,gridbaglayout,Java,Swing,Layout Manager,Gridbaglayout,我正在尝试构建一个包含两个垂直列的应用程序,锚定在左侧, 右边有一个大盒子。我可以把第一份菜单放在右边, 但由于某些原因,第二个菜单不会出现在第一个菜单旁边。我已经读到一些关于额外的空间被推向最后一列和最后一行(右边)。我该怎么处理呢 另外,我正在使用网格袋布局 以下是我得到的: 主用户视图类: 软件包图形用户界面 import actions.DepositAddButtonAction; import actions.DepositButtonAction; import javax.sw
import actions.DepositAddButtonAction;
import actions.DepositButtonAction;
import javax.swing.*;
import javax.swing.border.Border;
import java.awt.*;
public class UserView {
public JFrame frame;
private JPanel menuPanel;
private JPanel secondMenuPanel;
private JPanel contentPanel;
private JButton depositButton;
private JButton creditButton;
private JButton exchangeButton;
private JButton simulationButton;
private JButton informationButton;
private JLabel menuLabel;
private GridBagLayout gridBagLayout;
private GridBagConstraints constraints;
private Border border;
public UserView() {
frame = new JFrame("E-Banking");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
menuPanel = new JPanel();
secondMenuPanel = new JPanel();
contentPanel = new JPanel();
depositButton = new JButton("Deposit: ", new ImageIcon(UserView.class.getResource("/money_box_icon.png")));
creditButton = new JButton("Credit: ", new ImageIcon(UserView.class.getResource("/credit_icon.png")));
exchangeButton = new JButton("Exchange: ", new ImageIcon(UserView.class.getResource("/exchange_icon.png")));
simulationButton = new JButton("Simulation: ", new ImageIcon(UserView.class.getResource("/simulation_icon.png")));
informationButton = new JButton("Information: ", new ImageIcon(UserView.class.getResource("/info_icon.png")));
menuLabel = new JLabel(new ImageIcon(UserView.class.getResource("/bank_icon.png")), SwingConstants.LEFT);
gridBagLayout = new GridBagLayout();
constraints = new GridBagConstraints();
border = BorderFactory.createLineBorder(new Color(102, 102, 153), 1, true);
frame.setSize(800, 600);
applyButtonStyles();
initialize();
}
private void applyButtonStyles() {
depositButton.setHorizontalTextPosition(SwingConstants.RIGHT);
creditButton.setHorizontalTextPosition(SwingConstants.RIGHT);
exchangeButton.setHorizontalTextPosition(SwingConstants.RIGHT);
simulationButton.setHorizontalTextPosition(SwingConstants.RIGHT);
informationButton.setHorizontalTextPosition(SwingConstants.RIGHT);
menuLabel.setHorizontalAlignment(SwingConstants.RIGHT);
menuPanel.setBorder(border);
secondMenuPanel.setBorder(border);
secondMenuPanel.setVisible(false);
contentPanel.setBorder(border);
contentPanel.setVisible(false);
}
private void initialize() {
menuLabel.setText("E-Banking");
constraints.gridx = 0;
constraints.gridy = 0;
constraints.anchor = GridBagConstraints.FIRST_LINE_START;
constraints.fill = GridBagConstraints.BOTH;
constraints.insets = new Insets(4, 4, 4, 4);
menuPanel.setLayout(gridBagLayout);
menuPanel.add(menuLabel);
constraints.gridy++;
menuPanel.add(depositButton, constraints);
constraints.gridy++;
menuPanel.add(creditButton, constraints);
constraints.gridy++;
menuPanel.add(exchangeButton, constraints);
constraints.gridy++;
menuPanel.add(simulationButton, constraints);
constraints.gridy++;
menuPanel.add(informationButton, constraints);
constraints.gridx = 1;
constraints.gridy = 0;
frame.getContentPane().setLayout(gridBagLayout);
constraints.gridx = 0;
constraints.gridy = 0;
constraints.weightx = 0.4;
constraints.weighty = 0.4;
constraints.fill = GridBagConstraints.NONE;
frame.getContentPane().add(menuPanel, constraints);
constraints.gridx++;
frame.getContentPane().add(secondMenuPanel, constraints);
constraints.gridx++;
frame.getContentPane().add(contentPanel, constraints);
constraints.gridx++;
DepositAddButtonAction depositAddButtonAction = new DepositAddButtonAction(contentPanel);
DepositButtonAction depositButtonAction = new DepositButtonAction(secondMenuPanel, contentPanel, depositAddButtonAction, null, null);
depositButton.addActionListener(depositButtonAction);
}
}
表示第一个按钮行为的另一个类:
package actions;
import gui.UserView;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class DepositButtonAction implements ActionListener {
private JPanel secondMenuPanel;
private JPanel contentPanel;
private JButton addButton;
private JButton queryButton;
private JLabel operationLabel;
private GridBagLayout gridBagLayout;
private GridBagConstraints constraints;
public DepositButtonAction(JPanel secondMenuPanel, JPanel contentPanel, ActionListener otherDepositAddButtonAction,
ActionListener otherDepositRemoveButtonAction, ActionListener otherDepositQueryButtonAction) {
this.secondMenuPanel = secondMenuPanel;
secondMenuPanel.setVisible(false);
this.contentPanel = contentPanel;
addButton = new JButton("Request", new ImageIcon(UserView.class.getResource("/add_icon.png")));
queryButton = new JButton("Query", new ImageIcon(UserView.class.getResource("/info_icon.png")));
operationLabel = new JLabel(new ImageIcon(UserView.class.getResource("/options_icon.png")));
operationLabel.setText("Options ");
gridBagLayout = new GridBagLayout();
constraints = new GridBagConstraints();
applyStyles();
addButton.addActionListener(otherDepositAddButtonAction);
// removeButton.addActionListener(otherDepositRemoveButtonAction);
// queryButton.addActionListener(otherDepositQueryButtonAction);
}
private void applyStyles() {
secondMenuPanel.setLayout(gridBagLayout);
addButton.setHorizontalTextPosition(SwingConstants.RIGHT);
queryButton.setHorizontalTextPosition(SwingConstants.RIGHT);
}
private void initialize() {
constraints.gridx = 0;
constraints.gridy = 0;
constraints.anchor = GridBagConstraints.FIRST_LINE_START;
constraints.fill = GridBagConstraints.BOTH;
constraints.insets = new Insets(4, 4, 4, 4);
secondMenuPanel.add(operationLabel, constraints);
constraints.gridy++;
secondMenuPanel.add(addButton, constraints);
constraints.gridy++;
secondMenuPanel.add(queryButton, constraints);
}
@Override
public void actionPerformed(ActionEvent arg0) {
secondMenuPanel.setVisible(true);
contentPanel.setVisible(false);
secondMenuPanel.removeAll();
contentPanel.removeAll();
contentPanel.revalidate();
contentPanel.repaint();
initialize();
secondMenuPanel.revalidate();
secondMenuPanel.repaint();
}
}
我想要得到的是:
提前谢谢 “constraints.weightx”是你的朋友
从“double java.awt.GridBagConstraints.weightx”的Javadoc中:
网格行李布局管理器将列的重量计算为列中所有组件的最大重量X。如果生成的布局在水平方向上小于需要填充的区域,则额外的空间将按其权重比例分配给每列。权重为零的列不接收额外空间
这意味着,如果指定值“0”,则下一个组件将分布在上一个组件的旁边
在测试代码之后,我能够通过操纵initialize()函数上的constraints.weightx实现您想要的功能。不过有一个技巧,我只能在所有的菜单面板都可见的情况下应用它
我所做的就是这样,所有的菜单面板都是可见的:
constraints.weightx = secondMenuPanel.isVisible() ? 0.0 : 0.4;
constraints.weighty = 0.4;
constraints.fill = GridBagConstraints.NONE;
frame.getContentPane().add(menuPanel, constraints);
constraints.gridx++;
constraints.weightx = 0.4;
frame.getContentPane().add(secondMenuPanel, constraints);
constraints.gridx++;
结果:
如果需要隐藏零部件(仅在按下按钮时显示),则需要更新主框架布局的约束,以便它们正确显示
我希望这对您有所帮助。约束.weightx是您的朋友
从“double java.awt.GridBagConstraints.weightx”的Javadoc中:
网格行李布局管理器将列的重量计算为列中所有组件的最大重量X。如果生成的布局在水平方向上小于需要填充的区域,则额外的空间将按其权重比例分配给每列。权重为零的列不接收额外空间
这意味着,如果指定值“0”,则下一个组件将分布在上一个组件的旁边
在测试代码之后,我能够通过操纵initialize()函数上的constraints.weightx实现您想要的功能。不过有一个技巧,我只能在所有的菜单面板都可见的情况下应用它
我所做的就是这样,所有的菜单面板都是可见的:
constraints.weightx = secondMenuPanel.isVisible() ? 0.0 : 0.4;
constraints.weighty = 0.4;
constraints.fill = GridBagConstraints.NONE;
frame.getContentPane().add(menuPanel, constraints);
constraints.gridx++;
constraints.weightx = 0.4;
frame.getContentPane().add(secondMenuPanel, constraints);
constraints.gridx++;
结果:
如果需要隐藏零部件(仅在按下按钮时显示),则需要更新主框架布局的约束,以便它们正确显示
我希望这能对您有所帮助。我尝试了两个垂直的
框es(布局),用于JPanel
(按钮面板)中的按钮,该面板具有两列一行的GridLayout
。此按钮面板位于JFrame
的左侧(BorderLayout.WEST)
示例代码:
import java.awt.*;
import javax.swing.*;
public class TestingLayout {
public static void main(String[] args) {
gui();
}
private static void gui() {
JFrame frame = new JFrame();
frame.setTitle("JButtons Layout");
JPanel pane = new JPanel();
pane.setLayout(new GridLayout(1, 2));
pane.add(getLeftButtons());
pane.add(getRightButtons());
frame.add(pane, BorderLayout.WEST);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setSize(800, 500);
frame.setVisible(true);
}
private static Box getLeftButtons() {
Box box = Box.createVerticalBox();
box.add(new JButton("b1"));
box.add(new JButton("b2"));
box.add(new JButton("b3"));
box.add(new JButton("b4"));
box.add(new JButton("b5"));
return box;
}
private static Box getRightButtons() {
Box box = Box.createVerticalBox();
box.add(new JButton("b11"));
box.add(new JButton("b12"));
box.add(new JButton("b13"));
return box;
}
}
示例的输出:
我已经尝试过使用两个垂直的框es(布局)来设置JPanel
(按钮面板)中的按钮,该按钮具有两列一行的网格布局。此按钮面板位于JFrame
的左侧(BorderLayout.WEST)
示例代码:
import java.awt.*;
import javax.swing.*;
public class TestingLayout {
public static void main(String[] args) {
gui();
}
private static void gui() {
JFrame frame = new JFrame();
frame.setTitle("JButtons Layout");
JPanel pane = new JPanel();
pane.setLayout(new GridLayout(1, 2));
pane.add(getLeftButtons());
pane.add(getRightButtons());
frame.add(pane, BorderLayout.WEST);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setSize(800, 500);
frame.setVisible(true);
}
private static Box getLeftButtons() {
Box box = Box.createVerticalBox();
box.add(new JButton("b1"));
box.add(new JButton("b2"));
box.add(new JButton("b3"));
box.add(new JButton("b4"));
box.add(new JButton("b5"));
return box;
}
private static Box getRightButtons() {
Box box = Box.createVerticalBox();
box.add(new JButton("b11"));
box.add(new JButton("b12"));
box.add(new JButton("b13"));
return box;
}
}
示例的输出:
请记住,您不局限于使用单个布局管理器。您可以通过使用多个容器来组合布局管理器,从而使您能够关注每个容器的各个需求,进一步隔离功能并降低重叠布局需求的复杂性
您还应该看看,这将为您提供在不同视图之间翻转的方法
为此,我采取了一种稍微不同的方式,我从“菜单容器”的概念开始,它可以包含“子菜单”
我想做的事情是将API的各个部分解耦,并减少API的任何一部分对其余部分的知识量
基本上,这体现在子菜单窗格
中,它只是一些按钮的容器,这些按钮通过菜单操作
类配置和管理,除此之外,它什么也不做
public interface MenuAction extends Action {
public MenuController getController();
}
public abstract class AbstractMenuAction extends AbstractAction implements MenuAction {
private MenuController controller;
public AbstractMenuAction(MenuController controller, String name) {
this.controller = controller;
putValue(NAME, name);
}
@Override
public MenuController getController() {
return controller;
}
}
MenuAction
基于,它提供了一个自包含且可配置的工作单元
为了更好的衡量,我在菜单窗格和菜单操作之间加入了一个控制器
public interface MenuController {
public void addSubMenu(SubMenuPane subMenuPane);
public void popLastMenu();
}
public class DefaultMenuController implements MenuController {
private MenuPane menuPane;
public DefaultMenuController(MenuPane menuPane) {
this.menuPane = menuPane;
}
@Override
public void addSubMenu(SubMenuPane subMenuPane) {
menuPane.addSubMenuPane(subMenuPane);
}
@Override
public void popLastMenu() {
menuPane.popLastMenu();
}
}
这里的意图是,我不希望这些操作能够对菜单窗格进行负面修改,相反,我将它们限制为仅两个操作
好吧,但这对你有什么帮助
好吧,让我们建立一个菜单并找出
MenuPane menuPane = new MenuPane();
DefaultMenuController controller = new DefaultMenuController(menuPane);
SubMenuPane ebanking = new SubMenuPane("E-Banking");
ebanking.addAction(new AbstractMenuAction(controller, "Deposit") {
@Override
public void actionPerformed(ActionEvent e) {
getController().popLastMenu();
SubMenuPane deposit = new SubMenuPane("Options").addAction(new AbstractMenuAction(getController(), "Request") {
@Override
public void actionPerformed(ActionEvent e) {
// Use Card layout to show next avaliable options
}
}).addAction(new AbstractMenuAction(getController(), "Query") {
@Override
public void actionPerformed(ActionEvent e) {
// Use Card layout to show next avaliable options
}
});
getController().addSubMenu(deposit);
}
}).addAction(new AbstractMenuAction(controller, "Credit") {
@Override
public void actionPerformed(ActionEvent e) {
getController().popLastMenu();
SubMenuPane deposit = new SubMenuPane("Credit-Options").addAction(new AbstractMenuAction(getController(), "Request") {
@Override
public void actionPerformed(ActionEvent e) {
// Use Card layout to show next avaliable options
}
}).addAction(new AbstractMenuAction(getController(), "Query") {
@Override
public void actionPerformed(ActionEvent e) {
// Use Card layout to show next avaliable options
}
});
getController().addSubMenu(deposit);
}
}).addAction(new AbstractMenuAction(controller, "Exchange") {
@Override
public void actionPerformed(ActionEvent e) {
getController().popLastMenu();
SubMenuPane deposit = new SubMenuPane("Exchange-Options").addAction(new AbstractMenuAction(getController(), "Request") {
@Override
public void actionPerformed(ActionEvent e) {
// Use Card layout to show next avaliable options
}
}).addAction(new AbstractMenuAction(getController(), "Query") {
@Override
public void actionPerformed(ActionEvent e) {
// Use Card layout to show next avaliable options
}
});
getController().addSubMenu(deposit);
}
}).addAction(new AbstractMenuAction(controller, "Simulation") {
@Override
public void actionPerformed(ActionEvent e) {
getController().popLastMenu();
SubMenuPane deposit = new SubMenuPane("Simulation-Options").addAction(new AbstractMenuAction(getController(), "Request") {
@Override
public void actionPerformed(ActionEvent e) {
// Use Card layout to show next avaliable options
}
}).addAction(new AbstractMenuAction(getController(), "Query") {
@Override
public void actionPerformed(ActionEvent e) {
// Use Card layout to show next avaliable options
}
});
getController().addSubMenu(deposit);
}
}).addAction(new AbstractMenuAction(controller, "Information") {
@Override
public void actionPerformed(ActionEvent e) {
getController().popLastMenu();
SubMenuPane deposit = new SubMenuPane("Information-Options").addAction(new AbstractMenuAction(getController(), "Request") {
@Override
public void actionPerformed(ActionEvent e) {
// Use Card layout to show next avaliable options
}
}).addAction(new AbstractMenuAction(getController(), "Query") {
@Override
public void actionPerformed(ActionEvent e) {
// Use Card layout to show next avaliable options
}
});
getController().addSubMenu(deposit);
}
});
controller.addSubMenu(ebanking);
好吧,这是很多“什么…代码”。为了简洁起见,我使用了很多匿名类,实际上,我可能为每个菜单操作设置了子类,但这提供了基本的基础工作
关键是,每个子菜单都可以简单方便地制作,独立于菜单页
,因为它们通过控制器绑定在一起
您可以进一步扩展控制器,以提供附加功能,以触发创建子视图的操作,或提供直接通过控制器打开您提供的子视图的方法
我想展示这个想法的原因是,当您添加新的子菜单时,它将影响剩余的内容区域,如果您试图在单个布局/容器中维护它,那么您将不断地努力将所有内容保持在一起并很好地协同工作<