【问题标题】:Sending messages between two JPanel objects在两个 JPanel 对象之间发送消息
【发布时间】:2023-03-28 13:30:01
【问题描述】:

我有一个包含 JPanel 的 Java JFrame。在该 JPanel 中,有两个单独的 JPanel。当用户单击第一个 JPanel 中的按钮时,需要向另一个 JPanel 发送一条消息,通知它单击了哪个按钮。在这样的对象之间发送消息的最简单方法是什么?

【问题讨论】:

    标签: java oop swing user-interface jpanel


    【解决方案1】:

    您可以创建一个自定义事件,并为其附加一个或多个侦听器。

    实现的正确方法是让 Button ActionListener 触发事件,然后让您的两个面板成为该事件的侦听器。

    【讨论】:

    【解决方案2】:

    对于 mKorbel(和原始海报):
    我推荐的是更松散的耦合,一个 JPanel 不知道另一个 JPanel,并且所有连接都是通过某种控制完成的。例如,借用你的一些代码:

    CopyTextNorthPanel2.java

    import java.awt.*;
    import javax.swing.*;
    
    public class CopyTextNorthPanel2 extends JPanel {
    
       private static final long serialVersionUID = 1L;
       public JTextField northField;
    
       public CopyTextNorthPanel2() {
          northField = new JTextField("Welcome World");
          northField.setFont(new Font("Serif", Font.BOLD, 20));
          northField.setPreferredSize(new Dimension(300, 25));
          add(northField);
       }
    
       public String getNorthFieldText() {
          return northField.getText();
       }
    }
    

    CopyTextSouthPanel2.java

    import java.awt.event.*;
    import javax.swing.*;
    
    public class CopyTextSouthPanel2 extends JPanel {
    
       private static final long serialVersionUID = 1L;
       private JTextField firstText = new JTextField("Desired TextField");
       private JButton copyButton = new JButton("Copy text from JTextFields");
       private CopyTextControl2 control;
    
       public CopyTextSouthPanel2() {
          copyButton.addActionListener(new ActionListener() {
             public void actionPerformed(ActionEvent e) {
                if (control != null) {
                   control.copyAction();
                }
             }
          });
    
          add(firstText);
          add(copyButton);
       }
    
       public void setControl(CopyTextControl2 control) {
          this.control = control;
       }
    
       public void setFirstText(String text) {
          firstText.setText(text);
       }
    }
    

    CopyTextControl2.java

    public class CopyTextControl2 {
       private CopyTextNorthPanel2 northPanel;
       private CopyTextSouthPanel2 southPanel;
    
       public void copyAction() {
          if (northPanel != null && southPanel != null) {
             southPanel.setFirstText(northPanel.getNorthFieldText());
          }
       }
    
       public void setNorthPanel(CopyTextNorthPanel2 northPanel) {
          this.northPanel = northPanel;
       }
    
       public void setSouthPanel(CopyTextSouthPanel2 southPanel) {
          this.southPanel = southPanel;
       }
    
    }
    

    CopyText2.java

    import java.awt.*;
    import javax.swing.*;
    
    public class CopyText2 {
    
       private static void createAndShowUI() {
          CopyTextNorthPanel2 northPanel = new CopyTextNorthPanel2();
          CopyTextSouthPanel2 southPanel = new CopyTextSouthPanel2();
          CopyTextControl2 control = new CopyTextControl2();
    
          southPanel.setControl(control);
          control.setNorthPanel(northPanel);
          control.setSouthPanel(southPanel);
    
          JPanel mainPanel = new JPanel(new BorderLayout());
          mainPanel.add(northPanel, BorderLayout.NORTH);
          mainPanel.add(Box.createRigidArea(new Dimension(100, 100)), BorderLayout.CENTER);
          mainPanel.add(southPanel, BorderLayout.SOUTH);
    
          JFrame frame = new JFrame("Copy Text");
          frame.getContentPane().add(mainPanel);
          frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
          frame.pack();
          frame.setLocationRelativeTo(null);
          frame.setVisible(true);
       }
    
       public static void main(String[] args) {
          java.awt.EventQueue.invokeLater(new Runnable() {
             public void run() {
                createAndShowUI();
             }
          });
       }
    }
    

    【讨论】:

    • 谢谢,不包括电池,在我的时区仍然可以看到相同的内容,超过午夜 2 小时,睡眠时间 +1
    • 感谢课程,如果有多个连接,则为绿色,则更好...
    • +1 建议松散耦合 -0.5 表示不够远 :-)
    • @HovercraftFullOfEels 已经过测试并且有效!这种技术有名字吗?另外,这与观察者模式是不同还是相同?
    【解决方案3】:

    在你的班级中名列前茅

    public MyClass implements ActionListener {
    
    ...
    myButton.addActionListener(this);
    ...
    
    public void actionPerformed(ActionEvent e) {
          //for example if you have more than one events that you need to handle
          if(e.getSource().equals(myButton) {
               //update your do some work on you jpanels
          }
    }
    

    但实际上,我认为是时候开始考虑设计模式了。您所描述的是observer 模式的完美候选者,也可能是command 模式

    【讨论】:

      【解决方案4】:

      例如,通过使用类之间的构造函数或(用于调试问题)使用getParent()从所需的JComponent(s) 中提取值

      import java.awt.*;
      import javax.swing.*;
      
      public class CopyTextFrame extends JFrame {
      
          private static final long serialVersionUID = 1L;
          private CopyTextNorthPanel northPanel;
          private CopyTextCenterPanel centerPanel;
          private CopyTextSouthPanel southPanel;
      
          public void makeUI() {
              northPanel = new CopyTextNorthPanel();
              centerPanel = new CopyTextCenterPanel();
              southPanel = new CopyTextSouthPanel();
              northPanel.setName("northPanel");
              centerPanel.setName("centerPanel");
              southPanel.setName("southPanel");
              centerPanel = new CopyTextCenterPanel();
              centerPanel.setPreferredSize(new Dimension(300, 40));
              southPanel = new CopyTextSouthPanel();
              southPanel.setSourceTextField(northPanel.desText);
              northPanel.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1));
              centerPanel.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1));
              southPanel.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1));
              setLayout(new BorderLayout(5, 5));
              setDefaultCloseOperation(EXIT_ON_CLOSE);
              add(northPanel, BorderLayout.NORTH);
              add(centerPanel, BorderLayout.CENTER);
              add(southPanel, BorderLayout.SOUTH);
              pack();
              setVisible(true);
          }
      
          public static void main(String[] args) {
      
              SwingUtilities.invokeLater(new Runnable() {
      
                  @Override
                  public void run() {
                      new CopyTextFrame().makeUI();
                  }
              });
          }
      }  
      

      +

      import javax.swing.*;
      
      public class CopyTextCenterPanel extends JPanel {
      
          private static final long serialVersionUID = 1L;
      
          public CopyTextCenterPanel() {
          }
      }
      

      +

      import java.awt.*;
      import javax.swing.*;
      
      public class CopyTextNorthPanel extends JPanel {
      
          private static final long serialVersionUID = 1L;
          public JTextField desText;
      
          public CopyTextNorthPanel() {
              desText = new JTextField("Welcome World");
              desText.setFont(new Font("Serif", Font.BOLD, 20));
              desText.setPreferredSize(new Dimension(300, 25));
              desText.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1));
              desText.addComponentListener(null);
              desText.setName("desText");
              add(desText);
          }
      
          public JTextField getDesText() {
              return desText;
          }
      }
      

      +

      import java.awt.*;
      import java.awt.event.ActionEvent;
      import javax.swing.*;
      
      public class CopyTextSouthPanel extends JPanel {
      
          private static final long serialVersionUID = 1L;
          private JTextField firstText;
          private JButton copyButton;
          private JTextField sourceTextField;
          private String lds = "";
      
          public CopyTextSouthPanel() {
              firstText = new JTextField("Desired TextField");
              firstText.setMinimumSize(new Dimension(300, 25));
              firstText.setPreferredSize(new Dimension(300, 25));
              firstText.setMaximumSize(new Dimension(300, 25));
      
              copyButton = new JButton("Copy text from JTextFields");
              copyButton.setMinimumSize(new Dimension(200, 25));
              copyButton.setPreferredSize(new Dimension(200, 25));
              copyButton.setMaximumSize(new Dimension(200, 25));
              copyButton.addActionListener(new java.awt.event.ActionListener() {
      
                  @Override
                  public void actionPerformed(java.awt.event.ActionEvent evt) {
                      copyButtonActionPerformed(evt);
                  }
      
                  private void copyButtonActionPerformed(ActionEvent evt) {
                      System.out.print("Button pressed" + "\n");
                      Component[] comp = CopyTextSouthPanel.this.getParent().getComponents();
                      int nO = comp.length;
                      for (int i = 0; i < comp.length; ++i) {
                          if (comp[i] instanceof JPanel) {
                              String name = ((JPanel) comp[i]).getName();
                              if (name.equals("northPanel")) {
                                  JPanel panel = (JPanel) comp[i];
                                  Component[] comp1 = panel.getComponents();
                                  int nO1 = comp1.length;
                                  for (int ii = 0; ii < comp1.length; ++ii) {
                                      if (comp1[ii] instanceof JTextField) {
                                          String name1 = ((JTextField) comp1[ii]).getName();
                                          if (!(name1 == null)) {
                                              if (name1.equals("desText")) {
                                                  JTextField text = (JTextField) comp1[ii];
                                                  String str = text.getText();
                                                  firstText.setText(str);
                                                  System.out.print("set value -> " + str + "\n");
                                                  break;
                                              }
                                          }
                                      }
                                  }
                                  break;
                              }
                          }
                      }
                      lds = sourceTextField.getText();
                      if (lds != null || (!(lds.isEmpty()))) {
                          firstText.setText(" Msg -> " + lds);
                      }
                  }
              });
              add(firstText, BorderLayout.EAST);
              add(copyButton, BorderLayout.WEST);
          }
      
          public void setSourceTextField(JTextField source) {
              this.sourceTextField = source;
          }
      }
      

      【讨论】:

      • 您正在硬编码获取对其中一个面板的引用,这似乎是一个非常脆弱的解决方案。更好的是让两个 JPanel 互不了解,并根据其他答案使用侦听器。
      • @Hovercraft Full Of Eels by depends 你的 cmets 很难说什么明智的,构造函数和最终的 Getter/Setter 也是硬编码的,我认为这两者仍然被认为是 JComponents 的基本内容,对我来说如果每个连接都发生错误,创建对象类的方法同样脆弱
      • 请看我的回答来理解我的意思。
      猜你喜欢
      • 2011-02-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-30
      • 2015-07-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多