【问题标题】:JTextArea/JTextComponent setText causes crashJTextArea/JTextComponent setText 导致崩溃
【发布时间】:2012-07-13 12:47:29
【问题描述】:

我是 Java 新手,尤其是 Swing 库。当我尝试使用记事本演示(来自 JDK 的标准演示)时,尝试更改编辑器窗口中的文本时发生了崩溃。我的示例代码:

void Filter(Component f){
  if (f instanceof JTextComponent){
    JTextComponent textComponent = (JTextComponent) f;
    textComponent.setVisible(false); //Works
    textComponent.setVisible(true); //Works
    textComponent.getText(); //Works
    textComponent.updateUI(); //Works
    textComponent.setText("Hello world!"); //Crashes
  }else{
    RecursiveGet(f);
  }
}
void RecursiveGet(Component c){
  for (Component f : ((JComponent) c).getComponents()) {
    if (f instanceof JComponent) {
      Filter(f);
    }
  }
}

我搜索了例如 JTextComponent,直到找到它,然后测试了一些方法。我想我遗漏了一些东西,一些细节。我的环境 JDK 1.7、JRE 7.0、Win7 x64。我很乐意得到任何帮助。谢谢。

更新 我添加异常处理程序

void Filter(Component f){
        if (f instanceof JTextComponent){
            JTextComponent textComponent = (JTextComponent) f;
            textComponent.setVisible(false);  //Work
            textComponent.setVisible(true);  //Work
            textComponent.getText();  //Work
            textComponent.updateUI(); //Work
            try {
            textComponent.setText("Hello world!"); //Crash
            } catch (Exception e) {
                e.printStackTrace();
            }
        }else{
            RecursiveGet(f);
        }
    }

然后得到这个..

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
        at javax.swing.plaf.synth.SynthContext.getPainter(Unknown Source)
        at javax.swing.plaf.synth.SynthTextAreaUI.update(Unknown Source)
        at javax.swing.JComponent.paintComponent(Unknown Source)
        at javax.swing.JComponent.paint(Unknown Source)
        at javax.swing.JComponent.paintChildren(Unknown Source)
        at javax.swing.JComponent.paint(Unknown Source)
        at javax.swing.JViewport.paint(Unknown Source)
        at javax.swing.JComponent.paintChildren(Unknown Source)
        at javax.swing.JComponent.paint(Unknown Source)
        at javax.swing.JComponent.paintChildren(Unknown Source)
        at javax.swing.JComponent.paint(Unknown Source)
        at javax.swing.JComponent.paintToOffscreen(Unknown Source)
        at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(Unknown S
ource)
        at javax.swing.RepaintManager$PaintManager.paint(Unknown Source)
        at javax.swing.RepaintManager.paint(Unknown Source)
        at javax.swing.JComponent._paintImmediately(Unknown Source)
        at javax.swing.JComponent.paintImmediately(Unknown Source)
        at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
        at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
        at javax.swing.RepaintManager.prePaintDirtyRegions(Unknown Source)
        at javax.swing.RepaintManager.access$700(Unknown Source)
        at javax.swing.RepaintManager$ProcessingRunnable.run(Unknown Source)
        at java.awt.event.InvocationEvent.dispatch(Unknown Source)
        at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
        at java.awt.EventQueue.access$000(Unknown Source)
        at java.awt.EventQueue$3.run(Unknown Source)
        at java.awt.EventQueue$3.run(Unknown Source)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Sour
ce)
        at java.awt.EventQueue.dispatchEvent(Unknown Source)
        at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
        at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
        at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
        at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
        at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
        at java.awt.EventDispatchThread.run(Unknown Source)

更新 2 setText 方法在添加异常处理程序块后起作用。但我想念什么?

【问题讨论】:

  • 有报错吗?
  • crash 是什么意思?它会抛出异常吗?如果是,是什么?
  • 我的意思是记事本应用程序被冻结并且不会响应我的操作。
  • 如果您从命令行运行程序,请查看输出。如果您在 IDE 中运行,请查看您的输出选项卡。如果没有,请在系统设置中启用 Java 控制台。
  • 您的代码是否在事件调度线程上运行?

标签: java swing settext


【解决方案1】:

这不是一个答案,而是一个代码帖子,显示您的方法或其变体,一种允许编码人员更改要发布的文本的方法:

import java.awt.*;
import java.awt.event.ActionEvent;
import javax.swing.*;
import javax.swing.text.*;

@SuppressWarnings("serial")
public class TestFilter extends JPanel {
   public TestFilter() {
      JPanel textFieldPanel = new JPanel(new GridLayout(0, 3));
      for (int i = 0; i < 15; i++) {
         textFieldPanel.add(new JTextField(10));
      }

      JPanel buttonPanel = new JPanel();
      buttonPanel.add(new JButton(new FilterAction("Show Text", "Hello World")));
      buttonPanel.add(new JButton(new FilterAction("Clear Text", "")));

      setLayout(new BorderLayout());
      add(textFieldPanel, BorderLayout.NORTH);
      add(new JScrollPane(new JTextArea(10, 15)));
      add(buttonPanel, BorderLayout.SOUTH);
   }

   private class FilterAction extends AbstractAction {
      private String text;

      public FilterAction(String name, String text) {
         super(name);
         this.text = text;
      }

      @Override
      public void actionPerformed(ActionEvent e) {
         filter(TestFilter.this, text);
      }
   }

   void filter(Component f, String text) {
      if (f instanceof JTextComponent) {
         JTextComponent textComponent = (JTextComponent) f;
         textComponent.setVisible(false); // Works
         textComponent.setVisible(true); // Works
         textComponent.getText(); // Works
         textComponent.updateUI(); // Works
         textComponent.setText(text); // Crashes
      } else {
         RecursiveGet(f, text);
      }
   }

   void RecursiveGet(Component c, String text) {
      for (Component f : ((JComponent) c).getComponents()) {
         if (f instanceof JComponent) {
            filter(f, text);
         }
      }
   }

   private static void createAndShowGui() {
      JFrame frame = new JFrame("TestFilter");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(new TestFilter());
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

因此,问题可能在于您如何调用您的方法,而您尚未向我们展示。

【讨论】:

  • 好的,我尝试显示所有代码,但不要怪我)正如我所说的实验。
  • +1 用于发布可运行代码,并显示 setText 确实有效 :-) @Darius 不,不显示所有代码。发布 SSCCE 来证明您的问题。
【解决方案2】:

根据您原始问题的cmets,

“[...]它在另一个线程中工作[s],但是[原始]线程在所有对象创建后开始[s]..”

所有修改 Swing 组件的代码都必须在事件调度线程中运行。等到所有东西都创建好是不够的。

java.awt.EventQueue.invokeLater(new Runnable() {
    public void run() {
        // modify swing components
    }
});

您可能想阅读以下内容:Java Event-Dispatching Thread explanation

...还有这个:Java: Swing Libraries & Thread Safety

【讨论】:

  • 根据堆栈跟踪,此异常来自事件调度线程。
  • 在原始问题的 cmets 中,他写道:“它在另一个线程中工作,但线程在所有对象创建后启动..”
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-17
  • 2018-01-23
  • 2020-12-02
  • 2013-11-11
相关资源
最近更新 更多