簡體   English   中英

從JPanel內部切換JFrame中的JPanel

[英]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。 如果將控制器附加到每個視圖,將模型附加到每個控制器,則可以在它們之間切換而無需在視圖或控制器中添加過多的邏輯,但仍可以將視圖與模型分離。 我把使用CardLayoutNull 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM