如何从另一个子 JPanel (Java Swing) 中的输入触发一个子 JPanel 中的操作?

How to trigger action in one child JPanel from input in another child JPanel (Java Swing)?

我正在尝试在 Java Swing 中实现 GUI(我是 Swing 的新手)。我有一个包含 2 个面板的父面板。左面板和右面板。左侧面板有一个 JComboBox 下拉菜单。右侧面板是一个包含 7 张卡片的 CardLayout。我想根据左侧面板中 JComboBox 中的选择更改右侧面板中显示的卡片。所有 3 个面板都是独立的 classes:LeftPanel.java、RightPanel.java 和 ParentPanel.java。我很难找到一个地方来放置这个动作的动作监听器。 LeftPanel 看不到 RightPanel 的 CardLayout,ParentPanel 也无法访问子 RightPanel 的 CardLayout。我看到了一些关于访问另一个 JPanel 的 CardLayout 的帖子,但 none 的方法到目前为止对我有用。我的设计有缺陷吗?或者有可能实现这一目标吗?

编辑 感谢您到目前为止的建议。下面给出的是我的 MCVE。请注意,每个 class 都在其自己的 (.java) 文件中。我这样做不是为了便于维护,而是将所有内容都放在框架 class 中。我以前把所有东西都放在一个 class 中,它工作得很好,但它变成了一个包含 2000 多行代码和 20 多个面板的长文件。

//Class MainFrame 包含 Main 方法:

打包tempgui; public class MainFrame 扩展 JFrame{

JFrame Frame1;

public static void main(String[] args){

    new MainFrame();
}

public MainFrame(){

    Frame1 = new JFrame();
    Frame1.setDefaultCloseOperation(EXIT_ON_CLOSE);

    Frame1.getContentPane().add(new ParentPanel(), BorderLayout.CENTER);        

    Frame1.setSize(800, 600);
    Frame1.setLocationRelativeTo(null);
    Frame1.pack();

    Frame1.setVisible(true);
}

}

//Class 父面板: public class ParentPanel 扩展 JPanel{

private JPanel ParentPanel;
private LeftPanel LP;
private RightPanel RP;

public ParentPanel(){

    ParentPanel = new JPanel();
    LP = new LeftPanel();
    RP = new RightPanel();

    ParentPanel.setLayout(new GridLayout(1,2));

    ParentPanel.add(LP);
    ParentPanel.add(RP);

    add(ParentPanel);
}

}

//Class 左面板: public class LeftPanel 扩展 JPanel{

private JPanel LeftPanel;
private JComboBox J1;

public LeftPanel(){

    LeftPanel = new JPanel();

    String[] Arr = {"RP1","RP2"};

    J1 = new JComboBox(Arr);

    LeftPanel.add(J1);

    add(LeftPanel);
}

}

//Class 右面板: public class RightPanel 扩展了 JPanel{

private JPanel RightPanel;
private RP1Panel RP1;
private RP2Panel RP2;
private CardLayout C1;

public RightPanel(){

    RightPanel = new JPanel();
    RP1 = new RP1Panel();
    RP2 = new RP2Panel();

    C1 = new CardLayout();

    RightPanel.setLayout(C1);

    RightPanel.add(RP1, "RP1");
    RightPanel.add(RP2, "RP2");
    C1.show(RightPanel, "RP1");

    add(RightPanel);
}

}

//Class RP1面板: public class RP1Panel 扩展 JPanel{

private JPanel RP1;
private JLabel JRP1;

public RP1Panel(){

    RP1 = new JPanel();
    JRP1 = new JLabel("RP1 Panel");
    RP1.add(JRP1);
    add(RP1);
}

}

//Class RP2面板: public class RP2Panel 扩展 JPanel{

private JPanel RP2;
private JLabel JRP2;

public RP2Panel(){

    RP2 = new JPanel();
    JRP2 = new JLabel("RP2 Panel");
    RP2.add(JRP2);
    add(RP2);
}

}

我会尝试提供我的 类 方法,允许其他 类 从他们那里提取“state”信息,例如组合框,并允许其他 类 改变它们,例如允许将侦听器添加到组合框。例如:

// Class LeftPanel:
class LeftPanel extends JPanel {
    private JPanel leftPanel;
    private JComboBox<String> comboBox; //!!

    // !!
    public LeftPanel(String[] comboTexts) {
        leftPanel = new JPanel();
        comboBox = new JComboBox<>(comboTexts); // !!
        leftPanel.add(comboBox);
        add(leftPanel);
    }

    // !!
    public String getComboSelection() {
        return comboBox.getSelectedItem().toString();
    }

    // !!
    public void comboAddActionListener(ActionListener listener) {
        comboBox.addActionListener(listener);
    }
}

然后其他 类 可以侦听组合框的变化,并在需要时提取选择。右面板同样有一个方法来允许更改它显示的 "card" JPanel。类似于:

// Class RightPanel:
class RightPanel extends JPanel {
    private JPanel rightPanel;
    private RP1Panel rightPanel1;
    private RP2Panel rightPanel2;
    private CardLayout cardLayout;

    public RightPanel() {
        rightPanel = new JPanel();
        rightPanel1 = new RP1Panel();
        rightPanel2 = new RP2Panel();
        cardLayout = new CardLayout();
        rightPanel.setLayout(cardLayout);
        rightPanel.add(rightPanel1, RP1Panel.NAME); //!!
        rightPanel.add(rightPanel2, RP2Panel.NAME);  // !!
        cardLayout.show(rightPanel, RP1Panel.NAME); // !!
        add(rightPanel);
    }

    // !! 
    public void showCard(String name) {
        cardLayout.show(rightPanel, name);
    }
}

而且他们可以在主要方面捆绑在一起:

// Class ParentPanel:
class ParentPanel extends JPanel {
    private JPanel ParentPanel;
    private LeftPanel leftPanel;
    private RightPanel rightPanel;

    public ParentPanel() {
        ParentPanel = new JPanel();
        leftPanel = new LeftPanel(new String[] {RP1Panel.NAME, RP2Panel.NAME});
        rightPanel = new RightPanel();
        ParentPanel.setLayout(new GridLayout(1, 2));
        ParentPanel.add(leftPanel);
        ParentPanel.add(rightPanel);
        add(ParentPanel);

        // !!
        leftPanel.comboAddActionListener(e -> {
            String selection = leftPanel.getComboSelection();
            rightPanel.showCard(selection);
        });
    }
}

整个 MCVE 可能看起来像:

import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.GridLayout;
import java.awt.event.ActionListener;

import javax.swing.*;

public class FooGui {
    public static void main(String[] args) {
        new MainFrame();
    }
}

class MainFrame extends JFrame {
    JFrame Frame1;

    public MainFrame() {
        Frame1 = new JFrame();
        Frame1.setDefaultCloseOperation(EXIT_ON_CLOSE);
        Frame1.getContentPane().add(new ParentPanel(), BorderLayout.CENTER);
        Frame1.setSize(800, 600);
        Frame1.setLocationRelativeTo(null);
        Frame1.pack();
        Frame1.setVisible(true);
    }
}

// Class ParentPanel:
class ParentPanel extends JPanel {
    private JPanel ParentPanel;
    private LeftPanel leftPanel;
    private RightPanel rightPanel;

    public ParentPanel() {
        ParentPanel = new JPanel();
        leftPanel = new LeftPanel(new String[] {RP1Panel.NAME, RP2Panel.NAME});
        rightPanel = new RightPanel();
        ParentPanel.setLayout(new GridLayout(1, 2));
        ParentPanel.add(leftPanel);
        ParentPanel.add(rightPanel);
        add(ParentPanel);

        // !!
        leftPanel.comboAddActionListener(e -> {
            String selection = leftPanel.getComboSelection();
            rightPanel.showCard(selection);
        });
    }
}

// Class LeftPanel:
class LeftPanel extends JPanel {
    private JPanel leftPanel;
    private JComboBox<String> comboBox; //!!

    // !!
    public LeftPanel(String[] comboTexts) {
        leftPanel = new JPanel();
        comboBox = new JComboBox<>(comboTexts); // !!
        leftPanel.add(comboBox);
        add(leftPanel);
    }

    // !!
    public String getComboSelection() {
        return comboBox.getSelectedItem().toString();
    }

    // !!
    public void comboAddActionListener(ActionListener listener) {
        comboBox.addActionListener(listener);
    }
}

// Class RightPanel:
class RightPanel extends JPanel {
    private JPanel rightPanel;
    private RP1Panel rightPanel1;
    private RP2Panel rightPanel2;
    private CardLayout cardLayout;

    public RightPanel() {
        rightPanel = new JPanel();
        rightPanel1 = new RP1Panel();
        rightPanel2 = new RP2Panel();
        cardLayout = new CardLayout();
        rightPanel.setLayout(cardLayout);
        rightPanel.add(rightPanel1, RP1Panel.NAME); //!!
        rightPanel.add(rightPanel2, RP2Panel.NAME);  // !!
        cardLayout.show(rightPanel, RP1Panel.NAME); // !!
        add(rightPanel);
    }

    // !! 
    public void showCard(String name) {
        cardLayout.show(rightPanel, name);
    }
}

// Class RP1Panel:
class RP1Panel extends JPanel {
    // !!
    public static final String NAME = "right panel 1";
    private JPanel RP1;
    private JLabel JRP1;

    public RP1Panel() {
        setName(NAME);
        RP1 = new JPanel();
        JRP1 = new JLabel("RP1 Panel");
        RP1.add(JRP1);
        add(RP1);
    }
}

// Class RP2Panel:
class RP2Panel extends JPanel {
    // !!
    public static final String NAME = "right panel 2";
    private JPanel RP2;
    private JLabel JRP2;

    public RP2Panel() {
        setName(NAME);
        RP2 = new JPanel();
        JRP2 = new JLabel("RP2 Panel");
        RP2.add(JRP2);
        add(RP2);
    }
}