![](/img/trans.png)
[英]Replacing current JPanel from JButton inside the JPanel not the JFrame
[英]Switching JPanel in JFrame from inside the JPanel
我正在嘗試基於按鈕創建動態應用程序,這些按鈕可從創建的面板內部切換JFrame的主面板(這是應用程序的頂部內容)。
該問題與設計問題有關,而不是開發問題。 我不確定我的設計,但是我會盡力解釋。
我有一個JFrame代表我的應用程序,其中包含一個JTabbedPane(和其中的多個Tabs)。 每個選項卡都包含一個默認的JPanel,並且在該JPanel中,我正在調用呈現我的View的控制器(我正在嘗試使用MVC模式)。
但是從所謂的View中,我有一些按鈕,這些按鈕必須切換JPanel的內容(包含在JTabbedPane中的Jpanel)。 而且我正在尋找切換視圖的最佳方法,同時又不違反OOP的標准規則。
示意圖:
JFrame
JTabbedPane
JPanel
View1
Button (pointing somehow to View2)
JPanel
View3
Button (pointing somehow to View4)
當我從視圖1中單擊按鈕時,我想要這樣:
JFrame
JTabbedPane
JPanel
View2
...
JPanel
View3
Button (pointing somehow to View4)
並且,一旦加載了View 2,如果我通過JTabbedPane轉到View3並單擊View3.button,我想擁有以下內容:
JFrame
JTabbedPane
JPanel
View2
...
JPanel
View4
...
正如我所說的,這更多是設計問題。 我的“設計”是否足夠好,不必為每個組件提供JFrame的引用? 我該如何執行呢?
我希望我的文字沒有太多錯誤,英語不是我的母語。 此外,歡迎對我的英語寫作技能進行任何更正。
謝謝。
我想說您的JTabbedPane是對面板感興趣的類-因為它是JTabbedPane,它將切換其內容。
因此,我想將JTabbedPane擴展到?TabbedPane(其中?代表“我的”或項目中的任何命名約定),並使其擴展ActionListener,如下所示:
public class MyTabbedPane extends JTabbedPane implements ActionListener {
...
public void actionPerformed(ActionEvent aev) {
// replace panels
revalidate();
repaint();
}
}
然后在需要的地方(可能是按鈕)將選項卡式窗格注冊為操作偵聽器。
如果要切換到多個面板,則需要更多代碼來傳遞狀態。 您可以編寫自己的偵聽器:
public class PanelSwitchActionListener {
public void panelSwitchRequested(...);
}
然后,傳遞Enum表示要切換到哪個面板,或者甚至將面板本身放在panelSwitchRequested()方法的(...)部分中。 然后在按鈕上添加一個Action(Listener),並使它們針對已注冊的PanelSwitchActionListener(希望是您的JTabbedPane)觸發panelSwitchRequested()。
我會嘗試回到模型上。 該模型將維護一個視圖列表,以及一個給定視圖引用的方法,它可以返回下一個視圖(即model.getNextView(view)
)。
該模型可以傳遞給您的控制器(在此我要說一個自定義的JTabbedPane,如pafau所述),它可以根據需要構造所有選項卡。 這樣,您就可以將導航機制與視圖分離,並將邏輯委托給模型。
就個人而言,我將重新考慮同時使用選項卡式窗格和視圖之間切換的設計。 通常是/或者帶有選項卡式窗格是首選。
但是,如果仍然需要這種方式,請嘗試以不同的方式考慮您的觀點。 我認為JPanels實際上是Views。 如果將控制器附加到每個視圖,將模型附加到每個控制器,則可以在它們之間切換而無需在視圖或控制器中添加過多的邏輯,但仍可以將視圖與模型分離。 我把使用CardLayout和Null Object的一個粗略示例放在一起,但否則相當簡單。 當然,所有類都應重命名為適合您的項目的名稱。
View.java
public class View extends JPanel {
private CardLayout layout;
public View(Controller controller, JComponent... subviews) {
layout = new CardLayout();
setLayout(layout);
for (int index = 0; index < subviews.length; ++index) {
JButton changeButton = new JButton("Change");
changeButton.addActionListener(controller);
subviews[index].add(changeButton);
add(subviews[index], "View" + index);
}
}
public void setSubview(int index) {
layout.show(this, "View" + index);
}
}
NullView.java
public class NullView extends View {
public NullView() {
super(null);
}
@Override
public void setSubview(int index) {
// do nothing
}
}
Controller.java
public class Controller implements ActionListener {
private Model model;
private View view;
public Controller(Model model) {
this.model = model;
this.view = new NullView();
}
public void setView(View view) {
this.view = view;
}
public void actionPerformed(ActionEvent e) {
model.nextIndex();
view.setSubview(model.getCurIndex());
}
}
Model.java
public class Model {
private int nViews;
private int curIndex;
public Model(int nViews) {
if (nViews <= 0) nViews = 1;
this.nViews = nViews;
}
public void nextIndex() {
curIndex = (curIndex + 1) % nViews;
}
public int getCurIndex() {
return curIndex;
}
}
在內容窗格中:
Controller controller1 = new Controller(new Model(2));
View view1 = new View(controller1, subview1, subview2);
controller1.setView(view1);
Controller controller2 = new Controller(new Model(3));
View view2 = new View(controller2, subview3, subview4, subview5);
controller2.setView(view2);
JTabbedPane tabbedPane = new JTabbedPane();
tabbedPane.addTab("Tab1", view1);
tabbedPane.addTab("Tab2", view2);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.