JFrame 和 JPanel 之间的通信
Communication between JFrame and JPanel
我在 NetBeans 中使用 JFrame Form 创建了 JFrame。在此 JFrame 中,我嵌套了第二个 JPanel 的 JPanel。然后我有单独的 JPanel class(我扩展了 JPanel)。
我想使用这个单独的 JPanel 作为 JFrame 中的嵌套。当我单击 JButton 时,我想通知 JFrame,该按钮已被单击。
到目前为止,我已经设法在 JFrame 的 initComponents()
中使用以下内容将单独的 JPanel 获取到 JFrame:
nestedPanel = new separateJPanel
但现在我不知道如何发送按钮已被点击的信息。
有什么技巧可以实现吗?
你可以给frame一个panel属性,给panel一个frame属性,在内存中把它们绑定在一起。通过这种方式,您可以轻松地将数据通过实例字段传递给另一个。
public MyPanel extends JPanel {
MyFrame frame;
MyPanel(MyFrame frame) {
this.panel = panel;
}
}
一种简单的方法是为您的 JPanel class 提供一个委托方法,允许其他 classes 将 ActionListeners 添加到感兴趣的按钮。例如:
public void addButton1ActionListener(ActionListener listener) {
button1.addActionListener(listener);
}
这样,如果 JFrame 持有 JPanel 的实例,它可以调用此方法将侦听器传递给 JButton。例如:
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class Foo {
private static void createAndShowGui() {
Frame1 frame = new Frame1();
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
// I almost never extend JFrame
class Frame1 extends JFrame {
private Panel1 panel1 = new Panel1();
private JLabel label = new JLabel(" ", SwingConstants.CENTER);
public Frame1() {
super("Foo");
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
add(panel1, BorderLayout.CENTER);
add(label, BorderLayout.SOUTH);
pack();
setLocationByPlatform(true);
panel1.addButton1ActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
label.setText("Button pressed");
}
});
}
}
class Panel1 extends JPanel {
private JButton button1 = new JButton("Button");
public Panel1() {
add(button1);
}
public void addButton1ActionListener(ActionListener listener) {
button1.addActionListener(listener);
}
}
请注意,此解决方案适用于简单的玩具程序,但如果您的想法是创建一个真正的大型应用程序,则它不会很好地扩展,因为它会增加代码的耦合并降低内聚性。在这种情况下,更好的方法是努力创建一个使用更多模型-视图-控制或 MCV 架构的程序。
我在 NetBeans 中使用 JFrame Form 创建了 JFrame。在此 JFrame 中,我嵌套了第二个 JPanel 的 JPanel。然后我有单独的 JPanel class(我扩展了 JPanel)。
我想使用这个单独的 JPanel 作为 JFrame 中的嵌套。当我单击 JButton 时,我想通知 JFrame,该按钮已被单击。
到目前为止,我已经设法在 JFrame 的 initComponents()
中使用以下内容将单独的 JPanel 获取到 JFrame:
nestedPanel = new separateJPanel
但现在我不知道如何发送按钮已被点击的信息。
有什么技巧可以实现吗?
你可以给frame一个panel属性,给panel一个frame属性,在内存中把它们绑定在一起。通过这种方式,您可以轻松地将数据通过实例字段传递给另一个。
public MyPanel extends JPanel {
MyFrame frame;
MyPanel(MyFrame frame) {
this.panel = panel;
}
}
一种简单的方法是为您的 JPanel class 提供一个委托方法,允许其他 classes 将 ActionListeners 添加到感兴趣的按钮。例如:
public void addButton1ActionListener(ActionListener listener) {
button1.addActionListener(listener);
}
这样,如果 JFrame 持有 JPanel 的实例,它可以调用此方法将侦听器传递给 JButton。例如:
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class Foo {
private static void createAndShowGui() {
Frame1 frame = new Frame1();
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
// I almost never extend JFrame
class Frame1 extends JFrame {
private Panel1 panel1 = new Panel1();
private JLabel label = new JLabel(" ", SwingConstants.CENTER);
public Frame1() {
super("Foo");
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
add(panel1, BorderLayout.CENTER);
add(label, BorderLayout.SOUTH);
pack();
setLocationByPlatform(true);
panel1.addButton1ActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
label.setText("Button pressed");
}
});
}
}
class Panel1 extends JPanel {
private JButton button1 = new JButton("Button");
public Panel1() {
add(button1);
}
public void addButton1ActionListener(ActionListener listener) {
button1.addActionListener(listener);
}
}
请注意,此解决方案适用于简单的玩具程序,但如果您的想法是创建一个真正的大型应用程序,则它不会很好地扩展,因为它会增加代码的耦合并降低内聚性。在这种情况下,更好的方法是努力创建一个使用更多模型-视图-控制或 MCV 架构的程序。