0

「ホームページ」(JFrame「フレーム」に描画される)、「ページ2」、「ページ3」の3つのページを持つソフトウェアを作成したいと思います。

2ページ目と3ページ目は「コマ」に描かれています。

1 つはページの左側にあるナビゲーション ペインを使用し、メイン コンテンツは右側に保持されます。

現在、2 ページ目にしか移動できません。JFrame でページ 2 を描画するために呼び出されたクラスは、ページ 3 を呼び出すことができないようです。

私のコードは次のとおりです。

// The Home Page

package Try;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class HomePage {
    JPanel panelHomeWrapper = new JPanel();
    JPanel panelNavigation = new JPanel();
    JPanel panelDisplay = new JPanel();

    JButton buttonNavigation = new JButton("Button Home = Menu Items");
    JButton buttonBody = new JButton("Button body Page Home = Home body Items");

    public static void main (String[] args) {
        HomePage home = new HomePage();
        home.homePanel();
    }

    public void homePanel () {
        JFrame frame = new JFrame("Home");

        JButton button = new JButton("Button");

        ActionListener actionListener = new ActionListener() {
            public void actionPerformed(ActionEvent actionEvent) {
                System.out.println("Panel 2 was called.");

                Page2 panel2 = new Page2();

                panelNavigation.remove(buttonNavigation);
                panelDisplay.remove(buttonBody);

                panelNavigation.add(panel2.buttonNavigation);
                panelDisplay.add(panel2.buttonBody);

                panelNavigation.validate();
                panelNavigation.repaint();

                panelDisplay.validate();
                panelDisplay.repaint();
            }
        };

        button.addActionListener(actionListener);


        buttonNavigation.addActionListener(actionListener);

        panelNavigation.add(buttonNavigation);
        panelDisplay.add(buttonBody);

        panelHomeWrapper.add(panelNavigation);
        panelHomeWrapper.add(panelDisplay);

        frame.add(panelHomeWrapper);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(455, 355);
        frame.setVisible(true);
    }
} // End of Home Page

ページ2

// Page 2

package Try;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JPanel;

public class Page2 {
    JButton buttonNavigation = new JButton("Button 2 = Menu Items");
    JButton buttonBody = new JButton("Button body Page 2 = Page 2 body Items");

    ActionListener actionListenerCallAnotherPage = new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent actionEvent) {
            System.out.println("Button Body 3 was called.");

            HomePage home = new HomePage();
            Page3 panel3 = new Page3();

            home.panelDisplay.remove(buttonBody);
            home.panelDisplay.add(panel3.buttonBody3);

            home.panelDisplay.validate();
            home.panelDisplay.repaint();

        }
    };

    public void addAction () {
        buttonNavigation.addActionListener(actionListenerCallAnotherPage);
    }
}

3ページ

// Page 3

package Try;

import javax.swing.JButton;

public class Page3 {
    JButton buttonBody3 = new JButton("Page 3");
} // End of Page 3

2 番目のクラス (ページ 2) を 3 番目のクラス (ページ 3) に呼び出す方法を教えてください。よろしくお願いします。

4

1 に答える 1

2

addAction問題は、Page2クラスのメソッドが呼び出されないという事実にあるようです。actionListenerCallAnotherPagebuttonNavigation JButton...に登録する責任があるようです。

さて、そうは言っても...これは、ほとんど得られない大変な作業のように思えます。

この方法でナビゲーションをハード チェーンしようとする代わりに、ナビゲーションを管理する何らかのモデルを使用する必要があります。

基本的に、このモデルの参照を各ページに順番に渡し、各ページの準備が整ったら、モデルに次のページに移動するように要求します。モデルは、現在のページが変更され、それに応じてビュー自体が更新されることをメイン ビューに示すために、ある種の変更イベントを発生させます。

と組み合わせてこれを行うことができますCardLayout。つまり、モデルへのコンポーネントの参照を与える必要さえありませんが、代わりに に関連付けられている「ページ名」を使用してCardLayout、プログラムをさらに分離します...

モデルベースのアプローチ

基本的な考え方は、ビューを互いに分離することです。データを共有する必要がある場合でも、何らかのデータ モデルを使用しますが、ナビゲーション モデルに集中してください。

何が必要...

  • 使用可能なすべてのビューとそれらを表示する順序についてのアイデア
  • 現在の「アクティブな」ビュー
  • ビューを変更する方法、たとえば前/次...
  • 状態の変化に関する通知を提供する何らかの方法...
  • また、実際のコンポーネントからモデルを切り離したいと考えています。「厳密に」言えば間違いではありませんが、自分のコンポーネントが自分の知らないうちに変更される可能性のある場所に渡されるのは好きではありません。ビューを更新するのもモデルの責任ではありません。それはコントローラーの責任です...これは、画面に表示されていた実際のコンポーネントがモデルとは無関係であることも意味します...

何かのようなもの...

public interface ViewModel {

    /**
     * Returns the name of the current "active" view name
     * @return
     */
    public String getCurrentView();

    /**
     * Instructs the model to move to the next view if one is
     * available...
     */
    public void nextView();

    /**
     * Instructs the model to move to the previous view if one is
     * available...
     */
    public void previousView();

    /**
     * Returns the number of views in this model
     */
    public int size();

    /**
     * Returns the name of the view at the specified index...
     * @param index
     * @return 
     */
    public String getViewAt(int index);

    /**
     * Adds a ChangeListeners to the model, which will be notified when
     * the current view changes
     */
    public void addChangeListener(ChangeListener listener);

    /**
     * Remove a ChangeListeners from the model
     */
    public void removeChangeListener(ChangeListener listener);

}

...例えば

今、私はすべての退屈で反復的な作業を行う抽象的な実装が好きです...

public abstract class AbstractViewModel implements ViewModel {

    private EventListenerList listenerList;
    private List<String> views;

    public void addView(String name) {
        getViews().add(name);
    }

    public void removeView(String name) {
        getViews().remove(name);
    }

    @Override
    public int size() {
        return views.size();
    }

    @Override
    public String getCurrentView() {
        return getViewAt(getCurrentViewIndex());
    }

    protected abstract int getCurrentViewIndex();

    protected List<String> getViews() {
        if (views == null) {
            views = new ArrayList<>(25);
        }
        return views;
    }

    @Override
    public String getViewAt(int index) {
        return index >= 0 && index < size() ? getViews().get(index) : null;
    }

    @Override
    public void addChangeListener(ChangeListener listener) {
        getListenerList().add(ChangeListener.class, listener);
    }

    @Override
    public void removeChangeListener(ChangeListener listener) {
        getListenerList().remove(ChangeListener.class, listener);
    }

    protected EventListenerList getListenerList() {
        if (listenerList == null) {
            listenerList = new EventListenerList();
        }
        return listenerList;
    }

    protected void fireStateChanged() {
        ChangeListener[] listeners = getListenerList().getListeners(ChangeListener.class);
        if (listeners.length > 0) {
            ChangeEvent evt = new ChangeEvent(this);
            for (ChangeListener listener : listeners) {
                listener.stateChanged(evt);
            }
        }
    }    
}

これにより、ニーズを満たすためにさまざまな実装を考案できます...

たとえば、ここでは「線形」ビュー モデルを提供しました。このモデルは、最後のビューまでずっと移動して停止するか、最初のビューまでずっと移動して停止します。モードのいずれかの端に到達すると、もう一方の端に反転する円形のビュー モデルを作成するのにそれほど時間はかかりません...

public class LinearViewModel extends AbstractViewModel {

    private int currentIndex;

    @Override
    protected int getCurrentViewIndex() {
        return currentIndex;
    }

    @Override
    public void nextView() {
        if (currentIndex + 1 < size()) {
            currentIndex++;
            fireStateChanged();
        }
    }

    @Override
    public void previousView() {
        if (currentIndex - 1 >= 0) {
            currentIndex--;
            fireStateChanged();
        }
    }    
}

開始するには、ビュー名を代表的なコンポーネントにマップする何らかの方法が必要です。また、モデルの変更を監視する方法も必要です...

private Map<String, Component> mapViews;
private Component currentView;
private LinearViewModel model;

public ViewModelTest() {

    // Maps the view name to the component...
    mapViews = new HashMap<>(25);
    model = new LinearViewModel();
    mapViews.put("Page01", new Page01());
    mapViews.put("Page02", new Page02());
    mapViews.put("Page03", new Page03());
    mapViews.put("Page04", new Page04());

    // Add the view names to the model...
    model.addView("Page01");
    model.addView("Page02");
    model.addView("Page03");
    model.addView("Page04");

    // Initialise out view with the first page...
    currentView = mapViews.get("Page01");
    add(currentView);

    // Monitor for changes...
    model.addChangeListener(new ChangeListener() {
        @Override
        public void stateChanged(ChangeEvent e) {
            remove(currentView);
            currentView = mapViews.get(model.getCurrentView());
            add(currentView);
            revalidate();
        }
    });

}

さて、あなたはおそらく、私のビューが次/前のビューにどのように移動するのか疑問に思っているでしょう...?

そうではありません。代わりに、メイン画面に存在するナビゲーション バーを作成し、モデル自体と対話するために使用します...各ページ/ビューをプロセス全体から分離したままにします...

于 2013-08-21T06:34:01.307 に答える