有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

Java中的多线程操作优先级。(在GUI更新之前,对象实例化并运行?)

我希望GUI将按钮的标题从“Go”更改为“Working…”在对象实例化并实际执行工作之前。完成后,我希望按钮的标题切换回“Go”

代码如下:

    private class convert implements ActionListener {
    public void actionPerformed(ActionEvent e) {
        JButton button = (JButton)e.getSource();

        button.setText("Working...");
        button.setEnabled(false);

        anObject name = new AnObject();
        boolean result = name.methodName(chooser.getSelectedFile(),encoding);

        // A bunch of stuff was here but irrelevant to the question,
        // so it was removed to save room.

        button.setEnabled(true);
        button.setText("Go");
    }

实践中实际发生的是name被实例化,methodName被调用,然后按钮在屏幕上得到更新,尽管我已经告诉虚拟机先更改按钮标题

我的工作原理是,考虑到我没有使这个程序线程化,这与操作优先级、JVM的内部线程化或其他有关

有什么建议吗


共 (3) 个答案

  1. # 1 楼答案

    试试SwingUtilities.invokeLater()

    private class convert implements ActionListener {
    public void actionPerformed(ActionEvent e) {
        final JButton button = (JButton)e.getSource();
    
        button.setText("Working...");
        button.setEnabled(false);
    
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                anObject name = new AnObject();
                boolean result = name.methodName(chooser.getSelectedFile(),encoding);
    
                // A bunch of stuff was here but irrelevant to the question,
                // so it was removed to save room.
    
                button.setEnabled(true);
                button.setText("Convert");
            }
        });
    }
    
  2. # 2 楼答案

    事件线程中会发生一个“ActionPerformed”回调,在返回之前,GUI上通常不会更新任何内容。如果你想更新gui,做点什么,然后再次更新,你需要更新gui,生成一个线程并返回。然后线程必须执行它的操作,然后执行SwingUtilities。调用调用器来更新gui

  3. # 3 楼答案

    我知道您已经接受了一个解决方案,但由于您遇到了“冻结gui”综合症,您肯定有线程问题,invokeLater无法解决您的问题。正如extraneon在上面提到的,你需要一个SwingWorker或者一些后台线程来解决这个问题。此外,我认为这是一个使用AbstractAction而不是ActionListener的好例子。例如:

    import java.awt.Dimension;
    import java.awt.event.*;
    import javax.swing.*;
    
    @SuppressWarnings("serial")
    public class Convert extends AbstractAction {
       private static final long SLEEP_TIME = 3000; // 3 seconds
       private String enabledText;
       private String disabledText;
    
       public Convert(String enabledText, String disabledText) {
          super(enabledText);
          this.enabledText = enabledText;
          this.disabledText = disabledText;
       }
    
       public void actionPerformed(ActionEvent e) {
          Object source = e.getSource();
          if (!(source instanceof JButton)) {
             return;
          }
          final JButton button = (JButton) source;
          setButtonEnabled(button, false);
          new SwingWorker<Void, Void>() {
             @Override
             protected Void doInBackground() throws Exception {
                // TODO: long-running code goes here. 
                // Emulated by Thread.sleep(...) 
                Thread.sleep(SLEEP_TIME);
                return null;
             }
    
             @Override
             protected void done() {
                setButtonEnabled(button, true);
             }
          }.execute();
       }
    
       public void setButtonEnabled(JButton button, boolean enabled) {
          if (enabled) {
             button.setText(enabledText);
             button.setEnabled(true);
          } else {
             button.setText(disabledText);
             button.setEnabled(false);
          }
       }
    
       private static void createAndShowUI() {
          JFrame frame = new JFrame("Convert");
          frame.getContentPane().add(new ConvertGui());
          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();
             }
          });
       }
    }
    
    @SuppressWarnings("serial")
    class ConvertGui extends JPanel {
       public ConvertGui() {
          add(new JButton(new Convert("GO", "Working...")));
       }
    
       @Override
       public Dimension getPreferredSize() {
          return new Dimension(300, 200);
       }
    }