如何从另一个子 JPanel(Java Swing)中的输入触发一个子 JPanel 中的操作?
Posted
技术标签:
【中文标题】如何从另一个子 JPanel(Java Swing)中的输入触发一个子 JPanel 中的操作?【英文标题】:How to trigger action in one child JPanel from input in another child JPanel (Java Swing)? 【发布时间】:2017-07-24 14:59:54 【问题描述】:我正在尝试在 Java Swing 中实现 GUI(我是 Swing 新手)。我有一个包含 2 个面板的父面板。一个左面板和一个右面板。左侧面板有一个 JComboBox 下拉菜单。右侧面板是带有 7 张卡片的 CardLayout。我想根据左侧面板中 JComboBox 中的选择更改右侧面板中显示的卡片。所有 3 个面板都是独立的类:LeftPanel.java、RightPanel.java 和 ParentPanel.java。我很难找到一个地方来放置这个动作的动作监听器。 LeftPanel 看不到 RightPanel 的 CardLayout,ParentPanel 也无法访问子 RightPanel 的 CardLayout。我看到了一些关于访问另一个 JPanel 的 CardLayout 的帖子,但到目前为止,没有一种方法对我有用。我的设计有缺陷吗?或者有可能实现这一目标吗?
编辑 感谢您迄今为止的建议。下面给出的是我的 MCVE。请注意,每个类都在其自己的 (.java) 文件中。我这样做不是为了方便维护而将所有内容都放在 Frame 类中。我以前在一堂课里有所有东西,它工作得很好,但它变成了一个包含 2000 多行代码和 20 多个面板的长文件。
//包含Main方法的类MainFrame:
包 tempgui; 公共类 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);
//类父面板: 公共类 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);
//类LeftPanel: 公共类 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);
//类右面板: 公共类 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);
//类RP1Panel: 公共类 RP1Panel 扩展 JPanel
private JPanel RP1;
private JLabel JRP1;
public RP1Panel()
RP1 = new JPanel();
JRP1 = new JLabel("RP1 Panel");
RP1.add(JRP1);
add(RP1);
//类RP2Panel: 公共类 RP2Panel 扩展 JPanel
private JPanel RP2;
private JLabel JRP2;
public RP2Panel()
RP2 = new JPanel();
JRP2 = new JLabel("RP2 Panel");
RP2.add(JRP2);
add(RP2);
【问题讨论】:
"Or is it possible to achieve this?"
-- 是的,非常肯定。 "Is there a flaw in my design?"
-- 没有相关代码,最好是有效的minimal reproducible example,无法说出您的问题出在哪里。同样,考虑创建和发布一个 MCVE,一个小程序,小到可以作为代码格式的文本发布在您的问题中,一个可以编译和运行的程序,它可以向我们展示您的问题。它不是你的整个程序,它没有它的所有功能,但它再次为我们运行,它向我们展示了问题。
“所有 3 个面板都是单独的类” 解决这个难题的第一步可能是“不要不必要地扩展组件类”。您能在这里解释一下扩展面板的情况吗?
【参考方案1】:
我会尝试为我的类提供允许其他类从中提取“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);
然后其他类可以监听组合框的变化,并在需要时提取选择。右侧面板同样具有允许更改其显示的“卡片”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);
【讨论】:
非常感谢!这非常适合我的情况。我想我可以使用类似的方法在一个 JPanel 上实现 Back、Next 按钮来控制在另一个 JPanel 上的 Cards 之间来回翻转。类似于创建向导对话框。以上是关于如何从另一个子 JPanel(Java Swing)中的输入触发一个子 JPanel 中的操作?的主要内容,如果未能解决你的问题,请参考以下文章
Java Swing - 如何更改 JPanel 的 TitledBorder 上的字体大小?
Java Swing 在单击我要删除的 jpanel 中存在的 Jbutton 时删除 Jpanel
React Native ScrollView - 如何从另一个子组件按钮滚动到子组件?