我正在尝试使用我的程序的概念基本上是:
- 主窗口:包含程序主框架的主类,即:
public class MainWindow extends JFrame {
...
}
- 其他类:扩展JPanel的类,以便它们可以作为一个对象或实体轻松添加到MainWindow,即:
public class SomePanel extends JPanel {
...
}
这样,我可以说,对于主窗口:
public MainWindow() {
...
SomePanel sp = new SomePanel();
add(sp);
...
}
当触发某个ActionEvent时,我可以说,在MainWindow类中:
// remove the current panel
getContentPane().remove(sp);
// insert the new panel
getContentPane().add(someOtherPanel);
validate();
repaint();
我想,这个概念就像CardLayout一样,除了我还没有学习过CardLayout之外,我觉得我想尝试这个概念。我可能会在某些时候学习CardLayout,这取决于什么更容易。
但是我的主要问题是,如果所有内容都在不同的类中,我如何根据ActionEvent的触发器远程切换JPanels?我认为类之间必须有一些共享组件,但这似乎不起作用。我是在正确的轨道上吗?
我正在尝试删除()和add()的代码似乎没有工作,因为当我触发组件的ActionEvent(添加了侦听器和所有内容)时没有任何变化。我还包括validate()和repaint()但仍然没有任何反应。
我不再是初学者了,但也不是非常有经验的人,所以如果有一些明显我缺少的话,请耐心等待。谢谢你的帮助。
答案 0 :(得分:7)
你肯定是在正确的轨道上,几乎拥有它。请注意您在构造函数中如何使用add(sp);
,但在底部示例中使用getContentPane().remove(sp);
和getContentPane().add(someOtherPanel);
。 remove(Component c)
的方法绝对是JPanel
方法,所以请使用它。
此外,如果您在一个位置操作组件,一切都会更容易。我喜欢在主要方法或主要类中做到这一点。例如:
public class Start implements ActionListener {
Window theWindow = new Window();
CustomPanel mainMenu = new CustomPanel();
CustomPanel optionsMenu = new CustomPanel();
Button myButton = new Button();
public static void main(String[] args) {
theWindow.add(mainMenu);
mainMenu.add(myButton);
myButton.addActionListener(this);
theWindow.setVisible(true);
theWindow.repaint();
}
public void actionPerformed(Event e) {
theWindow.remove(mainMenu);
theWindow.add(optionsMenu);
theWindow.repaint();
}
请注意,即使不必使用自定义类,也可以轻松完成所有这些操作。我建议构建你的程序,gui就像这样。
同样如下文MadProgrammer所述,您可以使用theWindow.revalidate()
代替repaint()
。
答案 1 :(得分:5)
您可以设计一个模型来控制不同操作显示的内容。然后将共享此模型,以便底层操作可以访问它,并且不需要不必要地暴露组件。但这取决于你的要求......
所以,例如。您可以建立一个模型,允许您将组件与命名操作相关联(例如)。当您的应用程序中发生某些操作时,您会告诉模型setCurrentAction
并将其传递给可用的操作名称。
你可以进一步使用像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
答案 2 :(得分:0)
你可以试试这个:
〜添加两个jpanels
〜每当有事件发生时,切换面板的可见性......
示例:
//global variables
int i = 0;
JPanel p2 = new JPanel();
JPanel p = new JPanel();
当有事件调用此方法时:switchPanels()
,但您可以根据需要命名...:D
public void switchPanels() {
i++;
if(i % 2 == 0){
p.setVisible(true);
p2.setVisible(false);
}else{
p.setVisible(false);
p2.setVisible(true);
}
}