2

我一直在尝试解决我随机按下按钮时发生的 .setText 崩溃问题num0

  • 但似乎我只能通过使用来解决它, new Thread(new Runnable() { __overwrite__swing__textfields___ });但在这种情况下我无法访问我的JTextField.

因此我写了一个RunnableOutput类来发送和申请,但也失败了。例子:

可运行输出.java

package ui;

import java.awt.ComponentOrientation;
import javax.swing.*;

/**
 * JTextField - Wrapper for thread-safe 
 * 
 * @author root
 */
public class RunnableOutput implements Runnable {
  private JTextField outputArea;
  private String messageToAppend;

  // initialze outputArea and message
  public RunnableOutput(JTextField output, String message) {
    outputArea = output;
    messageToAppend = message;
  }

  @Override
  public void run() {
    outputArea.setText(messageToAppend);
  }

}

菜单.java:

public static JTextField nameTextField0 = new JTextField(20);
public void IPpanel(JPanel configPanel) { 

  JPanel Numlock = new JPanel(new GridLayout(0,12));
  JButton num0 = new JButton("0"); 
  num0.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent ae) {

      // Fails: 
      // was expecting this should fixed it but indeed still not
      SwingUtilities.invokeLater(
        new RunnableOutput(nameTextField0, "Unit test: 0"));       

      // Fails: 
      // wont work few times works but when randomly i press the 
      // button it fails
      // Same result with: SwingUtilities.invokeAndWait();
      SwingUtilities.invokeLater(new Runnable() {
        public void run() {
          nameTextField0.setText("Unit test: 1");
        }
      });

      // Works: does not freez but does not change/apply the values
      new Thread(new Runnable() {
        Menu.nameTextField0.setText("Unit test: 2");
      });        

    }
  });
  Numlock.add(num0); 

  configPanel.setLayout(new GridLayout(0,1));
  configPanel.add(Numlock);

}

跟进:

  • 使用多态性并修复所有这些
4

1 回答 1

0

1)你必须添加代码行

revalidate()
repaint();

在您添加JComponents到已经可见的情况下Container

2)添加/删除JComponents/到已经可见的Container必须在 上完成EventDispatschTread,应该被包裹到invokeLater/invokeAndWait

3)我建议包装(事件被声明为方法Thread SafesetText(),调用 from ,或append()invokeLaterRunnable#ThreadExecutorutil.Timer

4)使用 SwingTimer(保证在 EDT 上输出)或 Runnable#Thread(必须包装到 invokeLater/invokeAndWait 中)

5)对于 Swing GUI,使用 SwingWorker 会更好,也许 Runnable#Thread with/or Executor/util.Timer 更好

6)不要阻止EDT

7) 如建议获得更好的帮助,请尽快使用SSCCE编辑您的问题

编辑

   new Thread(new Runnable() {

        public void run() {

            final RunnableOutput a = new RunnableOutput();

            if (SwingUtilities.isEventDispatchThread()) {
                SwingUtilities.invokeLater(new Runnable() {

                    @Override
                    public void run() {
                        a.setText(nameTextField0, text);
                    }
                });
            } else {
                try {
                    SwingUtilities.invokeAndWait(new Runnable() {

                        @Override
                        public void run() {
                            a.setText(nameTextField0, text);
                        }
                    });
                } catch (InterruptedException ex) {
                    Logger.getLogger(Menu.class.getName()).log(Level.SEVERE, null, ex);
                } catch (InvocationTargetException ex) {
                    Logger.getLogger(Menu.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
    }).start();
于 2012-04-13T10:29:03.087 回答