您可以设计一个模型来控制不同操作显示的内容。然后将共享此模型,以便底层操作可以访问它,并且不需要不必要地公开组件。但这将取决于您的要求...
所以,例如。您可以建立一个模型,允许您将组件与命名操作(例如)相关联。当您的应用程序中发生某些操作时,您将告诉模型setCurrentAction
并将其传递给要使其可用的操作的名称。
此外,您可以使用类似 a 的东西ChangeListener
来通知相关方当前视图已更改并且应该相应地向上。
这样你就可以将模型与 UI 解耦
更新了一个例子
这是一个概念证明。重点是演示一种可以将模型与 UI 解耦的方法,因此模型不关心谁控制输出,只关心它可以告诉某人......
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashMap;
import java.util.Map;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.EventListenerList;
public class PageFlipper {
public static void main(String[] args) {
new PageFlipper();
}
public PageFlipper() {
startUI();
}
public void startUI() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new MainView());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class MainView extends JPanel {
private DefaultViewModel model;
public MainView() {
setLayout(new BorderLayout());
model = new DefaultViewModel();
model.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
System.out.println("Current view = " + model.getCurrentViewName());
removeAll();
add(model.getCurrentView());
revalidate();
repaint();
}
});
model.addView("Menu", new ActionPane("Menu", "Settings", model));
model.addView("Settings", new ActionPane("Settings", "Menu", model));
model.setCurrentView("Menu");
}
}
public class ActionPane extends JPanel {
private final String nextView;
private final ViewModel model;
public ActionPane(String name, String nextView, ViewModel model) {
this.nextView = nextView;
this.model = model;
setLayout(new BorderLayout());
JLabel label = new JLabel(name);
label.setHorizontalAlignment(JLabel.CENTER);
label.setVerticalAlignment(JLabel.CENTER);
add(label);
JButton btn = new JButton("Next");
btn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
ActionPane.this.model.setCurrentView(ActionPane.this.nextView);
}
});
add(btn, BorderLayout.SOUTH);
}
}
public interface ViewModel {
public void setCurrentView(String name);
public Component getCurrentView();
public void addChangeListener(ChangeListener listener);
public void removeChangeListener(ChangeListener listener);
}
public class DefaultViewModel implements ViewModel {
private final Map<String, Component> views;
private final EventListenerList listenerList;
private String currentView;
public DefaultViewModel() {
views = new HashMap<>(25);
listenerList = new EventListenerList();
}
public void addView(String name, Component comp) {
views.put(name, comp);
}
public void removeView(String name) {
views.remove(name);
}
@Override
public void setCurrentView(String name) {
if (currentView == null ? name != null : !currentView.equals(name)) {
currentView = name;
fireStateChanged();
}
}
public String getCurrentViewName() {
return currentView;
}
@Override
public Component getCurrentView() {
return currentView == null ? null : views.get(currentView);
}
@Override
public void addChangeListener(ChangeListener listener) {
listenerList.add(ChangeListener.class, listener);
}
@Override
public void removeChangeListener(ChangeListener listener) {
listenerList.remove(ChangeListener.class, listener);
}
protected void fireStateChanged() {
ChangeListener[] listeners = listenerList.getListeners(ChangeListener.class);
if (listeners.length > 0) {
ChangeEvent evt = new ChangeEvent(this);
for (ChangeListener listener : listeners) {
listener.stateChanged(evt);
}
}
}
}
}
您可以轻松修改它以获得更有意义的视图/操作名称(即使用某种Object
代替String
)以及提供更高级的导航(next
例如previous
)