java - 使用界面更新 GUI

标签 java user-interface interface jtextarea

一位经验丰富的开发人员告诉我,传递 GUI 实例是一个坏主意。

基本上我有一个构建和显示 GUI 的类。在 actionListener 中,我创建了一个执行一些时间密集型任务的对象,并且我想在任务的某些里程碑完成时显示状态。

这是该类的一个非常简化的版本:

public class MyGui extends JFrame {

   private static final long serialVersionUID = 1L;

   private JPanel mainPanel;
   private JPanel selectionPanel;
   private JPanel activityPanel;
   private JPanel executePanel;

   private JButton connectButton;
   private JButton disconnectButton;
   private JButton abortButton;

   private JList aList;

   private JComboBox comboBox;

   private JRadioButton primaryButton;
   private JRadioButton secondaryButton;

   private static JTextArea activityTextArea;

   MyGui() {

      this.setTitle("My Tool");

      mainPanel = new JPanel();
      mainPanel.setLayout(new GridLayout(3, 1));
      mainPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
      mainPanel.setBackground(Color.darkGray);
      this.add(mainPanel);

      createMainSelectionArea();
      createNodeSelectionArea();
      createStatusArea();
      createExecuteArea();

      mainPanel.add(selectionPanel);
      mainPanel.add(activityPanel);
      mainPanel.add(executePanel);

      this.add(mainPanel);
      this.setResizable(false);

      addActivity("test1");
      addActivity("test2");
      addActivity("test3");
      addActivity("test4");
      addActivity("test5");
      addActivity("test6");

      this.setSize(600, 400);
      this.setVisible(true);
      this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
   }

   private void createMainSelectionArea() {

      RadioButtonListener radioButtonListener = new RadioButtonListener();

      primaryButton = new JRadioButton("Primary");
      primaryButton.setBackground(Color.darkGray);
      primaryButton.setForeground(Color.white);
      primaryButton.addActionListener(radioButtonListener);

      secondaryButton = new JRadioButton("Secondary");
      secondaryButton.setBackground(Color.darkGray);
      secondaryButton.setForeground(Color.white);
      secondaryButton.addActionListener(radioButtonListener);

      ButtonGroup buttonGroup = new ButtonGroup();
      buttonGroup.add(primaryButton);
      buttonGroup.add(secondaryButton);

      JPanel buttonGroupPanel = new JPanel(new GridLayout(3, 1));
      buttonGroupPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
      buttonGroupPanel.setOpaque(true);
      buttonGroupPanel.setBackground(Color.darkGray);
      buttonGroupPanel.setForeground(Color.white);
      buttonGroupPanel.add(primaryButton);
      buttonGroupPanel.add(secondaryButton);

      selectionPanel = new JPanel(new GridLayout(1, 2));
      selectionPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
      selectionPanel.setBackground(Color.darkGray);
      selectionPanel.add(buttonGroupPanel);
   }

   private void createNodeSelectionArea() {

      String[] data1 = {"one", "two", "three", "4", "5", "6"};
      String[] data2 = {"four", "five", "six", "seven", "eight"};

      ComboBoxListener comboBoxListener = new ComboBoxListener();

      comboBox = new JComboBox(data1);
      comboBox.setBorder(BorderFactory.createLineBorder(Color.white));
      comboBox.setPreferredSize(new Dimension(150, 20));;
      comboBox.setBackground(Color.white);
      comboBox.setForeground(Color.black);
      comboBox.addActionListener(comboBoxListener);

      JPanel comboBoxPanel = new JPanel();
      comboBoxPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
      comboBoxPanel.setBackground(Color.darkGray);
      comboBoxPanel.add(comboBox, BorderLayout.CENTER);

      ListBoxListener listBoxListener = new ListBoxListener();

      aList = new JList(data2);
      aList.setBackground(Color.black);
      aList.setForeground(Color.white);
      aList.addListSelectionListener(listBoxListener);

      JScrollPane scrollPane = new JScrollPane(aList);
      scrollPane.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
      scrollPane.setBackground(Color.darkGray);

      JPanel listBoxPanel = new JPanel(new GridLayout(1,1));
      TitledBorder border = BorderFactory.createTitledBorder("A Selection");
      border.setTitleColor(Color.white);
      border.setBorder(BorderFactory.createLineBorder(Color.white));

      listBoxPanel.setBorder(border);
      listBoxPanel.setBackground(Color.darkGray);
      listBoxPanel.setForeground(Color.white);
      listBoxPanel.add(scrollPane);

      selectionPanel.add(comboBoxPanel);
      selectionPanel.add(listBoxPanel);
   }

   private void createStatusArea() {

      activityTextArea = new JTextArea();
      activityTextArea.setEditable(false);
      activityTextArea.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
      activityTextArea.setBackground(Color.black);
      activityTextArea.setForeground(Color.white);

      JScrollPane scrollPane = new JScrollPane(activityTextArea);
      scrollPane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
      scrollPane.setBackground(Color.darkGray);

      TitledBorder activityTitle = BorderFactory.createTitledBorder("Status");
      activityTitle.setTitleColor(Color.white);
      activityTitle.setBorder(BorderFactory.createLineBorder(Color.white));
      activityTitle.setTitlePosition(TitledBorder.CENTER);

      activityPanel = new JPanel(new GridLayout(1, 1));
      activityPanel.setBackground(Color.darkGray);
      activityPanel.setBorder(activityTitle);
      activityPanel.add(scrollPane);
   }

   public void addActivity(String activity) {

      activityTextArea.append(activity + "\n");
      activityTextArea.setCaretPosition(activityTextArea.getDocument().getLength());
   }

   public void createExecuteArea() {

      ButtonListener buttonListener = new ButtonListener();

      connectButton = new JButton("Connect");
      connectButton.setPreferredSize(new Dimension(115, 30));
      connectButton.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createRaisedBevelBorder(), BorderFactory.createLineBorder(Color.lightGray)));
      connectButton.setBackground(Color.white);
      connectButton.addActionListener(buttonListener);

      disconnectButton = new JButton("Disconnect");
      disconnectButton.setPreferredSize(new Dimension(115, 30));
      disconnectButton.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createRaisedBevelBorder(), BorderFactory.createLineBorder(Color.lightGray)));
      disconnectButton.setBackground(Color.white);
      disconnectButton.addActionListener(buttonListener);

      abortButton = new JButton("Abort");
      abortButton.setPreferredSize(new Dimension(115, 30));
      abortButton.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createRaisedBevelBorder(), BorderFactory.createLineBorder(Color.lightGray)));
      abortButton.setBackground(Color.white);
      abortButton.addActionListener(buttonListener);

      executePanel = new JPanel(new GridBagLayout());
      executePanel.setBackground(Color.darkGray);
      GridBagConstraints c = new GridBagConstraints();

      JPanel buttonPanel = new JPanel();
      buttonPanel.setBackground(Color.darkGray);

      buttonPanel.add(connectButton);
      buttonPanel.add(disconnectButton);
      buttonPanel.add(abortButton);

      executePanel.add(buttonPanel, c);
   }

   private class ButtonListener implements ActionListener {

      @Override
      public void actionPerformed(ActionEvent e) {

         if(e.getSource().equals(connectButton)) { 

            System.out.println("Connect Button"); 
         }

         if(e.getSource().equals(disconnectButton)) { 

            System.out.println("Disconnect Button"); 
         }

         if(e.getSource().equals(abortButton)) { 

            System.out.println("Abort Button"); 
         }
      }
   }

   private class RadioButtonListener implements ActionListener {

      @Override
      public void actionPerformed(ActionEvent e) {

         if(e.getSource().equals(primaryButton)) {

            System.out.println("Primary Selected");
         }

         if(e.getSource().equals(secondaryButton)) {

            System.out.println("Secondary Selected");
         }
      }
   }

   private class ComboBoxListener implements ActionListener {

      @Override
      public void actionPerformed(ActionEvent e) {

         if(e.getSource().equals(comboBox)) {

            System.out.println(comboBox.getSelectedItem());
            DataClass dataClass = new DataClass(MyGui.this, otherStuff);
            dataClass.doStuff();  // This class was calling the addActivity() method.
         }
      }
   }

   private class ListBoxListener implements ListSelectionListener {

      @Override
      public void valueChanged(ListSelectionEvent e) {

         if(e.getSource().equals(aList)) {

            System.out.println(aList.getSelectedValue());
         }
      }
   }

}

因此,我将(假设类名为 MyGui)MyGui.this 传递给有问题的 DataClass,然后使用 addActivity("status update") ;

因此,我没有执行上述操作,而是创建了这个界面:

public interface GuiUpdater {

   void update(MyGui MyGui, String update);
}

并修改了上面的MyGui类来实现该接口(interface)并这样调用:

   @Override
   public void update(MyGui myGui, String update) {
      // TODO Auto-generated method stub
      myGui.addActivity(update);
   }

所以我可以从其他类中更新它,我也实现了这个接口(interface)。所以我将 MyGui 的实例从 main 传递给其他类。

我认为这和我之前做的事情是一样的(只是不同)。

这是使用界面的正确方法吗?如果不是,那么在不传递 GUI 实例的情况下从不同类更新 GUI 的正确方法是什么?

最佳答案

接口(interface)用于定义对象可以支持的方法,而不需要接口(interface)的使用者了解有关该对象的太多信息或它希望如何实现该接口(interface)。在您的情况下,您希望为 MyGui 提供一个更新方法,该方法不需要 MyGui 类与其他代码之间的紧密耦合。如果您这样定义界面,那么您可以编写可能需要更新 GUI 的所有代码,以仅与 GuiUpdater 类型的对象交互:

public interface GuiUpdater {

   void update(String update);
}

然后,您将修改 MyGui 类声明来实现此接口(interface):

public class MyGui extends JFrame implements GuiUpdater {

您还必须在 MyGui 中实现此方法:

@Override
public void update(String update) {
     this.addActivity(update);
}

这与您在问题中的内容类似,但有一个重要的区别。因为它是作为 MyGui 内部的方法实现的,所以您可以访问 MyGui 实例的所有内部状态(例如 this)。换句话说,您不需要将 MyGui 实例作为参数传递,因为此方法位于 MyGui 内部。

现在,我们可以假设您的 MyGui 实例(名为 myGui)具有可能想要更新 GUI 的函数,例如:

public void foo(GuiUpdater updater) {
    updater.update("Interfaces are great");
}

您可以像 foo(myGui) 一样调用此函数,因为 MyGui 满足该接口(interface)。这将 foo 的实现与 MyGui 的实现解耦,并且意味着任何一方都不会受到对另一方实现的更改的影响。

无论您如何构建软件(MVC、MVP 等),对接口(interface)进行编码都是一个值得养成的好习惯。它隐藏了实现细节,因此减少了更改这些细节的影响。

关于java - 使用界面更新 GUI,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24836365/

相关文章:

Java接口(interface)和抽象中的返回类型

java - 在 Unity 中使用 Google Api Java 类?

java - 了解打印某些内容的字节码

javascript - 使用 JQuery UI 选项卡添加新选项卡

java - 为什么 List 是一个接口(interface)而不是一个类

java - 巨大的远程接口(interface) -> 最佳实践?

java - Hibernate 4 按属性查找记录

java - ShutdownHook何时被调用?

python - 用于 map 和 GPS 的跨平台、基于 Python 的丰富图形应用程序 : GTK or wxWidgets?

html - 将小图像放在背景颜色 html 上?