簡體   English   中英

如果類B的實例是類A的成員,那么當按下類B中的按鈕時,類B如何調用類A的方法?

[英]If an instance of class B is a member of class A, how can class B call a method of class A when a button in class B is pressed?

我正在嘗試使用MVC編碼實踐來制作GUI來為桌面RPG生成字符。 我將有幾個“控制面板”類,每個類都有一組特定的按鈕來處理角色創建過程的不同方面(滾動屬性,購買設備等)。 我的Controller類將每個“控制面板”類的實例作為成員。 我的通用代碼在這里:

公共類控制器{

private Model m; //class Model not shown
private Viewer v; //class Viewer not shown
private JFrame frame;
private ControlPanelOne cpo;
private ControlPanelTwo cpt; //class ControlPanelTwo not shown

public Controller(){
    m = new Model();
    v = new Viewer();
    frame = new JFrame();
    frame.setLayout(…);
    cpo = new ControlPanelOne();
    cpt = new ControlPanelTwo();
    frame.add(cpo.getPanel());
    frame.add(cpt.getPanel());}

public void update(){
    m.update();
    v.update();}}

公共類ControlPanelOne {

private JPanel panel;
private JButton button;

public ControlPanelOne(){
    panel = new JPanel();
    button = new JButton(“press me”);
    panel.add(button);
    button.addActionListener(new ActionListener(){
        public void actionPerformed(ActionEvent e){
            //do some stuff;
            //call Controller’s update method;}})} //the important bit!

public JPanel getPanel(){
    return panel;}}

公共課程測試人員{

public static void main(String[] args){

    Controller c = new Controller();}}

當按下ControlPanelOne的按鈕時,如何獲取ControlPanelOne以查看並調用Controller的update()方法?

我嘗試使ControlPanelOne擴展Controller,以便在按下ControlPanelOne的按鈕時可以調用super.update(),但是隨后實例化Controller時(例如在Tester類中),其ControlPanelOne成員也被實例化,由此Controller和ControlPanelOne的構造函數被稱為構造的無限循環。

試圖通過將Controller的update()方法設置為靜態來欺騙編譯器是行不通的,因為實例m和v不是靜態的。

如果可以幫助,我不想使ControlPanelOne成為Controller的內部類。 還會有其他“控制面板”類(ControlPanelTwo等),而且恐怕使它們成為所有內部類都會使Controller的代碼冗長而混亂。 我希望每個“控制面板”作為一個單獨的類來處理一個特定的功能,以保持整潔,並易於維護和模塊化代碼重用。

顯然,ControlPanelOne不應將Controller作為成員變量,因為a)從概念上講是向后的,並且b)其他“控制面板”的實例將需要自己的Controller實例…

我曾經讓Controller擴展JFrame和ControlPanelOne擴展JPanel(以便Controller可以直接add()ContollPanelOne的實例,而不是調用ControlPanelOne的getPanel()方法),但我讀到使類擴展此類組件而不是使此類組件成為您的組件成員。班級形式差。 但是如果能以某種方式幫助回到Controller和ControlPanelOne擴展JFrame和JPanel的話……

也許我對MVC的想法是錯誤的...

請指教

確實,您沒有遵循MVC模式。 該模式的要旨是提供模型,視圖和控制器的清晰分隔。 因此,任何相互繼承或組合的嘗試都將使利益喪失。

我要做的是使AbstractAction像這樣:

public class UpdateAction extends AbstractAction { 

    private Controller controller;

    ...
    @Override
    public void actionPerformed(ActionEvent ae) {
        controller.update();
    }
}

然后,初始化並在視圖外部設置按鈕,該視圖無需知道其顯示內容。 它只需要知道它的工作就是展示東西。 您可以讓控制器extend JFrame並將JPanel添加到其中。

JButton button = new JButton("Button");
button.setAction(new UpdateAction(this));
... more button set up
... add button to views
... add views to frame

現在,每當單擊按鈕時,它將調用控制器的update()方法。

當按下ControlPanelOne的按鈕時,如何獲取ControlPanelOne以查看並調用Controller的update()方法?

通常,這是通過使用觀察者模式來實現的 ,其中控制器將在某些事件發生時向要注冊的視圖注冊興趣,視圖將在事件發生時在適當時調用每個注冊方。 這樣,視圖就不在乎控制器,而只在乎它需要生成適當的事件。

如果我很好理解B類是A類的組成部分
B類不知道類A,即使它是該類的成員,也沒有對其的引用。 這稱為合成是一種“具有”關系。 如果您想了解該類,則還應該在類B中有一個類A的實例,或者將類A的方法設為靜態。

class B {
    btnPressed() {
        /*To call this method you need or an object of class A, or static method in class A*/
        methodA(); //Method form class A

        op1:
        a = new A();
        a.methodA();

        op2:
        //make methodA static in class A 
        A.methodA();
    }
}

class A {
    b = new B();

    methodA();
}

希望這可以幫助。

您的直接目標是在ControlPanelOne的構造函數中匿名實現的ActionListeneractionPerformed方法內的Controller實例上調用update ControlPanelOneController實例的構造函數組成。 實際上,您需要從ControllerControlPanelOne的循環引用,反之亦然。

這是一個簡單的方法。 您可以在此處簽出最少工作的項目。

首先,您的Controller

public class Controller {

    private Model m; //class Model not shown
    private Viewer v; //class Viewer not shown
    private JFrame frame;
    private ControlPanelOne cpo;
    private ControlPanelTwo cpt; //class ControlPanelTwo not shown

    public Controller() {
        m = new Model();
        v = new Viewer();
        frame = new JFrame();
        frame.setLayeredPane(null); // Do something

        cpo = new ControlPanelOne(this); // Supply self to the instance of ControlPanelOne
        cpt = new ControlPanelTwo();

        frame.add(cpo.getPanel());
        frame.add(cpt.getPanel());
    }

    public void update() {
        m.update();
        v.update();
    }
}

接下來, ControlPanelOne

public class ControlPanelOne {

    private JPanel panel;
    private JButton button;

    public ControlPanelOne(final Controller controller){
        panel = new JPanel();
        button = new JButton("press me");
        panel.add(button);
        button.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                //do some stuff;

                controller.update();

            }
        });
    }


    public Component getPanel() {
        return null;
    }
}

要記住的重要事情是在構造函數中聲明Controller final提供的實例(您可以在此處找到原因)。 在Java 8中,這不是必需的,但是仍然是習慣。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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