2

作成したパネル内からJFrameのメインパネル(アプリケーションの最上位コンテンツ)を切り替えるボタンに基づいて動的アプリケーションを構築しようとしています。

この質問は、開発の質問ではなく、設計の質問に関連しています。自分のデザインはよくわかりませんが、説明しようと思います。

JTabbedPane(およびその中に複数のタブ)を含むアプリケーションを表すJFrameがあります。各タブにはデフォルトのJPanelが含まれており、そのJPanel内で、ビューをレンダリングしているコントローラーを呼び出しています(MVCパターンを使用しようとしています)。

しかし、いわゆるビューから、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の参照を与える必要がないほど十分に優れていますか?どうすればそれを実行できますか?

私のテキストにそれほど多くの誤りがないことを願っています。英語は私の母国語ではありません。さらに、私の英語でのライティングスキルの修正は大歓迎です。

ありがとうございました。

4

3 に答える 3

1

あなたの JTabbedPane はパネルに関心のあるクラスだと思います.JTabbedPane は内容を切り替えます。

したがって、JTabbedPane を ?TabbedPane に拡張し (? は「My」またはプロジェクトの命名規則を表す)、次のように 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() を起動させます。

于 2012-07-24T19:37:19.637 に答える
0

個人的には、タブ付きペインとビュー間の切り替えの両方を使用する設計を再考します。通常は、タブ付きペインが優先されます。

ただし、それでもそのようにする必要がある場合は、ビューを別の方法で考えてみてください。JPanels は実際にはビューだと思います。コントローラーを各ビューに、モデルを各コントローラーにアタッチすると、ビューやコントローラーにロジックを追加しすぎることなく、モデルからビューを分離しながら、それらを切り替えることができます。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
    }

}

コントローラー.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());
    }

}

モデル.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);
于 2012-07-26T10:13:12.447 に答える
0

私はモデルに戻ってみます。モデルは、ビューのリストと、ビュー参照が与えられた場合に次のビュー (つまり ) を返す手段を保持しますmodel.getNextView(view)

このモデルは、必要に応じてすべてのタブを構築できるコントローラー (これでは、pafau が言及したカスタム JTabbedPane と言えます) に渡すことができます。このようにして、ビューからナビゲーション メカニズムを分離し、代わりにロジックをモデルに委譲します。

于 2012-07-24T22:51:45.797 に答える