1

这是作业顺便说一句,

我被要求制作一个包含多个 jpanel 的 jframe,这些 jpanels 上附加了按钮和动作侦听器。我必须使用 MVC 模型来做到这一点,但是,由于我的按钮/动作在 jpanels 而不是 jframe 中,我不知道如何恢复它们。我不会放下我所有的代码,但只是看看我尝试做什么所需要的。我想首先从面板 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 JFrameActionListener因为您希望调用getAjouter()实例RechercherAbsenceP3 JPanel

我的解决方案:

将您的ActionListener类转换GestionAbsenceEmployes为接受RechercherAbsenceP3作为参数,以便我们可以getAjouter()像这样调用它的实例:

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但是通过在JPanel向下转换时声明它,因此它无法访问扩展的方法,JPanel RechercherAbsenceP3只能访问默认的方法JPanel

其他一些建议:

  • 不要JFrame不必要地扩展课程

  • 不需要getContentPane.add(..)因为 add(..)已经转移到contentPane

  • 一定要在上面创建和操作 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. 通过将其设为内部类,您可以免费获得所有这些。您的控制器可以访问视图的所有成员变量。因此,您现在可以使用该getAjouter()方法访问 absenseP3 面板。

有关何时使用内部类有意义的更多信息,请参阅http://docs.oracle.com/javase/tutorial/java/javaOO/nested.html 。

于 2012-12-16T20:56:42.933 回答
2

不确定以下方法是否会被视为 MVC,或者它是否会在您的作业中取得好成绩。

我对您当前方法的“问题”是可重用性仅限于模型,并且看起来很难为此代码编写一个体面的测试用例,除非您准备编写包含整个视图的测试。

当我需要编写一个 Swing 应用程序时,我似乎只得到了 2 个类:一个定义数据的模型类和对该数据可用的操作,以及视图类。视图类既可以作为视图,也可以作为控制器。当我在您的示例中有一个按钮时,我会附加一个ActionListener(或使用一个Action),它只是从视图中检索必要的信息而没有任何逻辑。它将所有信息直接传递到所有逻辑所在的模型端。

我在这种方法中看到的两个主要好处:

  • 我可以毫无问题地重新设计我的视图。如果我决定删除 aJButton并向用户提供相同操作的另一种机制,那么我的所有更改都仅限于视图。除了在我的视图类中,我不依赖 UI 元素。我直接在我的视图类中看到所有“信息收集并将其传递给模型”,并且由于该视图的实现,这不会影响其他类。将其与您在source == vue.getAjouter()视图之外的类中进行检查的代码进行比较。
  • 我可以在不需要我的实际视图的情况下测试模型及其所有逻辑。所以我可以在单元测试中跳过整个“启动 Swing UI”,仍然测试我的所有逻辑。如果我想测试 UI(例如,当某个字段留空时测试某个按钮是否被禁用)我可以在集成测试中单独进行测试(因为 UI 往往会减慢您的测试速度)。

我在这方面发现了一篇非常有趣的文章是The Humble dialog box

于 2012-12-16T23:26:46.490 回答