1

これは宿題ですが、

ボタンとアクションリスナーが接続された複数のjpanelを含むjframeを作成するように求められます。それを行うにはMVCモデルを使用する必要がありますが、ボタン/アクションがjframeではなくjpanelにあるため、それらを復元する方法がわかりません。私は自分のコードをすべて書き留めるつもりはありませんが、自分がやろうとしていることを確認するために必要なものだけを書き留めます。最初にパネル3から「ajouter」ボタンを取得して、アクションを実行したいと思います。

これがパネル3です

import java.awt.FlowLayout;
import javax.swing.JButton;
import javax.swing.JPanel;

import ca.uqam.inf2120.tp2.modele.GestionAbsenceEmployes;

public class RechercherAbsenceP3 extends JPanel {

    private GestionAbsenceEmployes aControleur;
    private JButton ajouter, modifier, supprimer, afficher, fermer;
    FlowLayout gestionnaireComposant;

    RechercherAbsenceP3() {
    try {
        jbInitP3();
    } catch (Exception e) {
        e.printStackTrace();
    }
        ajouter.addActionListener(aControleur);
        modifier.addActionListener(aControleur);
        supprimer.addActionListener(aControleur);
        afficher.addActionListener(aControleur);
        fermer.addActionListener(aControleur);
    }

    private void jbInitP3() throws Exception {

    gestionnaireComposant = new FlowLayout(FlowLayout.RIGHT);

    this.setLayout(gestionnaireComposant);

    ajouter = new JButton("Ajouter");
    modifier = new JButton("Modifier");
    modifier.setEnabled(false);
    supprimer = new JButton("Supprimer");
    supprimer.setEnabled(false);
    afficher = new JButton("Afficher");
    afficher.setEnabled(false);
    fermer = new JButton("Fermer");

    this.add(ajouter);
    this.add(modifier);
    this.add(supprimer);
    this.add(afficher);
    this.add(fermer);

    }

    public JButton getAjouter() {
        return ajouter;
    }
}

これが窓です

package ca.uqam.inf2120.tp2.interfacegraphique;

import java.awt.BorderLayout;
import ca.uqam.inf2120.tp2.interfacegraphique.RechercherAbsenceP3;
import javax.swing.JFrame;
import javax.swing.JPanel;

import ca.uqam.inf2120.tp2.modele.GestionAbsenceEmployes;

public class CreerRechercherAbsence extends JFrame {

    private GestionAbsenceEmployes aControleur;
    private JPanel absenceP1, absenceP2, absenceP3;

    private BorderLayout gestionnaireComposant;

    public CreerRechercherAbsence() {
        super("Gestionnaire des employés absents");

        try {
            jbInit();
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        aControleur = new GestionAbsenceEmployes(this); 

    }

    void jbInit() throws Exception {

        gestionnaireComposant = new BorderLayout(5, 5);
        this.getContentPane().setLayout(gestionnaireComposant);

        absenceP1 = new RechercherAbsenceP1();
        absenceP2 = new RechercherAbsenceP2();
        absenceP3 = new RechercherAbsenceP3();

        this.getContentPane().add(absenceP1, BorderLayout.NORTH);
        this.getContentPane().add(absenceP2, BorderLayout.CENTER);
        this.getContentPane().add(absenceP3, BorderLayout.SOUTH);
    }

}

未完成のコントローラー:

    package ca.uqam.inf2120.tp2.modele;

    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;

    import ca.uqam.inf2120.tp1.partie1.adt.impl.ListeAdtArrayListImpl;
    import ca.uqam.inf2120.tp2.interfacegraphique.CreerRechercherAbsence;

    public class GestionAbsenceEmployes implements ActionListener{

        private AbsenceEmploye modele;
        private CreerRechercherAbsence vue;

        public GestionAbsenceEmployes(CreerRechercherAbsence uneVue) {
            this.modele = new AbsenceEmploye();
            vue = uneVue;
        }

        public AbsenceEmploye getModele() {
            return modele;
        }


        @Override
        public void actionPerformed(ActionEvent event) {
            Object source = event.getSource();
            if(source == vue.getAjouter()) {

            }
        }

}

vue.getAjouter()を追加すると、それが何であるかわかりません!!!

私は何をしますか/間違えますか?

4

3 に答える 3

2

問題は、インスタンスを呼び出したいときに、どこでgetAjouter()インスタンスCreerRechercherAbsence JFrameを呼び出しているかということです。ActionListenergetAjouter()RechercherAbsenceP3 JPanel

私の解決策:

次のようにインスタンスを呼び出すことができるように、ActionListenerクラスをパラメーターとしてGestionAbsenceEmployes受け入れるように変換します。RechercherAbsenceP3getAjouter()

class GestionAbsenceEmployes implements ActionListener {

    private AbsenceEmploye modele;
    private RechercherAbsenceP3 vue;

    public GestionAbsenceEmployes(RechercherAbsenceP3 uneVue) {
        this.modele = new AbsenceEmploye();
        vue = uneVue;
    }

    public AbsenceEmploye getModele() {
        return modele;
   }

    @Override
    public void actionPerformed(ActionEvent event) {
        Object source = event.getSource();
        if (source == vue.getAjouter()) {
        }
    }
}

あなたがするよりも:

    aControleur = new GestionAbsenceEmployes(absenceP3);

ただし、上記のステートメントが機能するためには、これを変更する必要があります。

private JPanel absenceP1, absenceP2,absenceP3;

CreerRechercherAbsenceクラスでこれに:

private JPanel absenceP1, absenceP2;
private RechercherAbsenceP3 absenceP3;

JPanel機能を追加するために拡張するため、それをダウンキャストするときにRechercherAbsenceP3宣言することにより、拡張されたメソッドにはアクセスできず、デフォルトのメソッドにのみアクセスできます。JPanelJPanel RechercherAbsenceP3JPanel

その他の提案:

  • JFrame不必要にクラスを延長しないでください

  • contentPaneに流用さgetContentPane.add(..)れ ているので必要ありませんadd(..)

  • で Swing コンポーネントを作成して操作してください。Event Dispatch Thread

于 2012-12-16T20:53:53.287 に答える
2

これが私がそれを行う方法です。GestionAbsenceEmployesの非静的内部クラスを作成しますCreerRechercherAbsence

public class CreerRechercherAbsence extends JFrame {

    private GestionAbsenceEmployes aControleur;
    private JPanel absenceP1, absenceP2;
    private RechercherAbsenceP3 absenceP3;

    // code omitted
    public CreerRechercherAbsence() {
        super("Gestionnaire des employés absents");

        try {
            jbInit();
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        aControleur = new GestionAbsenceEmployes(); 
    }

    // code omitted
    class GestionAbsenceEmployes implements ActionListener{

        private AbsenceEmploye modele;

        public GestionAbsenceEmployes() {
            this.modele = new AbsenceEmploye();
        }

        public AbsenceEmploye getModele() {
            return modele;
        }


        @Override
        public void actionPerformed(ActionEvent event) {
            Object source = event.getSource();
            if(source == absenceP3.getAjouter()) {

            }
        }
    }

thisコンストラクターに渡す必要はなく、コントローラーは への参照を必要としませんvue。これを内部クラスにすることで、これらすべてを無料で取得できます。コントローラーは、ビューのすべてのメンバー変数にアクセスできます。これで、メソッドを使用して absenseP3 パネルにアクセスできるようになりましたgetAjouter()

内部クラスを使用する意味がある場合の詳細については、 http://docs.oracle.com/javase/tutorial/java/javaOO/nested.htmlを参照してください。

于 2012-12-16T20:56:42.933 に答える
2

次のアプローチが MVC と見なされるかどうか、または課題で良い点が得られるかどうかはわかりません。

あなたの現在のアプローチに関する私の「問題」は、再利用性がモデルに限定されており、ビュー全体を含むテストを作成する準備ができていない限り、このコードのまともなテストケースを作成するのが難しいように見えることです。

Swing アプリケーションを作成する必要がある場合、2 つのクラスしか作成できないようです。データとそのデータで使用可能な操作を定義するモデル クラスと、ビュー クラスです。ビュー クラスは、ビューとコントローラーの両方として機能します。あなたの例のようにボタンがある場合、ロジックなしでビューから必要な情報を取得するだけのActionListenerをそれにアタッチします (または を使用します)。Actionすべての情報は、すべてのロジックが配置されているモデル側に直接渡されます。

このアプローチには、次の 2 つの主なメリットがあります。

  • 問題なくビューを再設計できます。を削除してJButton、同じ操作のための別のメカニズムをユーザーに提供することにした場合、すべての変更はビューに限定されます。ビュー クラス以外の UI 要素には依存していません。ビュークラスですべての「情報を収集してモデルに渡す」ことを直接確認します。そのビューの実装により、これは他のクラスには影響しません。source == vue.getAjouter()それを、ビューの外にあるクラスにチェックがあるコードと比較してください。
  • 実際のビューがなくても、モデルとそのすべてのロジックをテストできます。したがって、単体テストで「Swing UI を起動する」全体をスキップして、すべてのロジックをテストできます。UI をテストしたい場合 (たとえば、フィールドが空白のままのときに特定のボタンが無効になっているかどうかをテストする場合)、統合テストでこれを個別にテストできます (UI を使用するとテストが遅くなる傾向があるため)。

この点で非常に興味深い記事を見つけたのは、謙虚なダイアログボックスです

于 2012-12-16T23:26:46.490 に答える