CardLayout
CardLayout 布局管理器是一个非常有用的布局管理器,可以用来在不同的容器之间切换。
对我来说,它的一个限制因素是,通常需要拥有您想要切换到、实例化和添加的每个容器。就内存使用而言,这可能会使其“繁重”,并且在面板之间传递信息时会变得困难 - 因为它很难抽象工作流程,并非不可能,只是有问题。
其中一个不错的功能是根据所有其他容器自动确定所需的 UI 大小。
见How to Use CardLayout
自定义导航
我经常发现自己需要做的一件事是通过 UI 进行某种非线性进程,并且需要能够有效地将信息来回传递到不同的容器。
可以通过使用delegation、observer pattern和dependency injection来完成。
这里的基本原则是,您可能有许多导航控制器,每个控制器都管理一个特定的工作流程,独立于所有其他控制器。这种分离简化了应用程序的需求,并且在需要时更容易移动事物,因为任何一个工作流都不会与另一个工作流耦合。
这里没有演示的另一个方面是向导航控制器返回信息的能力,例如,如果您有一个登录/注册工作流程,工作流程可以通过返回一个“用户”实例来结束控制器然后能够确定他们接下来需要通过哪个工作流程(管理员/版主/基本/等)
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame();
frame.add(new MasterPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class MasterPane extends JPanel {
private MenuPane menuPane;
public MasterPane() {
setLayout(new BorderLayout());
presentMenu();
}
protected void presentMenu() {
removeAll();
if (menuPane == null) {
menuPane = new MenuPane(new MenuPane.NavigationListener() {
@Override
public void presentRedPane(MenuPane source) {
RedPane redPane = new RedPane(new ReturnNavigationListener<RedPane>() {
@Override
public void returnFrom(RedPane source) {
presentMenu();
}
});
present(redPane);
}
@Override
public void presentGreenPane(MenuPane source) {
GreenPane greenPane = new GreenPane(new ReturnNavigationListener<GreenPane>() {
@Override
public void returnFrom(GreenPane source) {
presentMenu();
}
});
present(greenPane);
}
@Override
public void presentBluePane(MenuPane source) {
BluePane bluePane = new BluePane(new ReturnNavigationListener<BluePane>() {
@Override
public void returnFrom(BluePane source) {
presentMenu();
}
});
present(bluePane);
}
});
}
add(menuPane);
revalidate();
repaint();
}
protected void present(JPanel panel) {
removeAll();
add(panel);
revalidate();
repaint();
}
}
public class MenuPane extends JPanel {
public static interface NavigationListener {
public void presentRedPane(MenuPane source);
public void presentGreenPane(MenuPane source);
public void presentBluePane(MenuPane source);
}
private NavigationListener navigationListener;
public MenuPane(NavigationListener navigationListener) {
this.navigationListener = navigationListener;
setBorder(new EmptyBorder(16, 16, 16, 16));
setLayout(new GridBagLayout());
JButton red = new JButton("Red");
red.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
getNavigationListener().presentRedPane(MenuPane.this);
}
});
JButton green = new JButton("Green");
green.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
getNavigationListener().presentGreenPane(MenuPane.this);
}
});
JButton blue = new JButton("Blue");
blue.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
getNavigationListener().presentBluePane(MenuPane.this);
}
});
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.fill = GridBagConstraints.BOTH;
add(red, gbc);
add(green, gbc);
add(blue, gbc);
}
protected NavigationListener getNavigationListener() {
return navigationListener;
}
}
public interface ReturnNavigationListener<T> {
public void returnFrom(T source);
}
public class RedPane extends JPanel {
private ReturnNavigationListener<RedPane> navigationListener;
public RedPane(ReturnNavigationListener<RedPane> navigationListener) {
this.navigationListener = navigationListener;
setBackground(Color.RED);
setLayout(new BorderLayout());
add(new JLabel("Roses are red", JLabel.CENTER));
JButton back = new JButton("Back");
back.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
getReturnNavigationListener().returnFrom(RedPane.this);
}
});
add(back, BorderLayout.SOUTH);
}
public ReturnNavigationListener<RedPane> getReturnNavigationListener() {
return navigationListener;
}
}
public class BluePane extends JPanel {
private ReturnNavigationListener<BluePane> navigationListener;
public BluePane(ReturnNavigationListener<BluePane> navigationListener) {
this.navigationListener = navigationListener;
setBackground(Color.BLUE);
setLayout(new BorderLayout());
add(new JLabel("Violets are blue", JLabel.CENTER));
JButton back = new JButton("Back");
back.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
getReturnNavigationListener().returnFrom(BluePane.this);
}
});
add(back, BorderLayout.SOUTH);
}
public ReturnNavigationListener<BluePane> getReturnNavigationListener() {
return navigationListener;
}
}
public class GreenPane extends JPanel {
private ReturnNavigationListener<GreenPane> navigationListener;
public GreenPane(ReturnNavigationListener<GreenPane> navigationListener) {
this.navigationListener = navigationListener;
setBackground(Color.GREEN);
setLayout(new BorderLayout());
add(new JLabel("Kermit is green", JLabel.CENTER));
JButton back = new JButton("Back");
back.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
getReturnNavigationListener().returnFrom(GreenPane.this);
}
});
add(back, BorderLayout.SOUTH);
}
public ReturnNavigationListener<GreenPane> getReturnNavigationListener() {
return navigationListener;
}
}
}