使用界面更新GUI

时间:2014-07-19 03:13:32

标签: 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.thisDataClass,然后使用addActivity("status update");

所以我没有做以上操作,而是创建了这个界面:

public interface GuiUpdater {

   void update(MyGui MyGui, String update);
}

并修改上面的MyGui类来实现接口并以这种方式调用它:

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

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

我认为这与我以前做过的事情完全相同(不同)。

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

1 个答案:

答案 0 :(得分:2)

接口用于定义对象可以支持的方法,而不需要接口的使用者了解对象或者希望如何实现接口。在您的情况下,您希望在MyGui上提供更新方法,该方法不需要MyGui类与您的其他代码之间的紧密耦合。如果您这样定义了接口,那么您可以编写可能需要更新GUI的所有代码,以便只与GuiUpdater类型的对象进行交互:

public interface GuiUpdater {

   void update(String update);
}

然后,您将修改MyGui类声明以实现此接口:

public class MyGui extends JFrame implements GuiUpdater {

您还必须在MyGui

中实施此方法
@Override
public void update(String update) {
     this.addActivity(update);
}

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

现在,我们可以假设一个名为MyGui的{​​{1}}实例具有可能需要更新GUI的功能,例如:

myGui

您可以像public void foo(GuiUpdater updater) { updater.update("Interfaces are great"); } 一样调用此函数,因为foo(myGui)满足该接口。这将MyGui的实现与foo的实现分离,意味着任何一方都不会对另一方的实现进行更改。

无论您如何构建软件(MVC,MVP等),编码到接口都是一个很好的习惯。它隐藏了实施细节,因此减少了更改这些细节的影响。