我在Swing中创建了一个用于编辑数据的对话框。它包含JTextArea
,两个JButton
个实例(OK
& Cancel
)和一个JCheckBox
(Wrap Text
)。我想要做的是在用户单击复选框时将文本区域中的文本包装起来。我最初使用setLineWrap(true)
包装文本。
我使用以下代码:
Runnable r1=new Runnable() {
@Override
public void run() {
System.out.println("True");
keyField.setLineWrap(true);
keyField.requestFocus();
}
};
Runnable r2=new Runnable() {
@Override
public void run() {
System.out.println("FALSE");
keyField.setLineWrap(false);
keyField.repaint();
keyField.requestFocus();
}
};
final Thread t1=new Thread(r1) ;
final Thread t2=new Thread(r2);
final JCheckBox chkSwing = new JCheckBox("Word Wrap",true);
chkSwing.addItemListener(
new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
//To change body of implemented methods use File | Settings | File Templates.
if (e.getStateChange() == ItemEvent.SELECTED) {
t1.start();
} else if (e.getStateChange() != ItemEvent.SELECTED){
t2.start();
}
}
});
panel.add(chkSwing);
问题是,一旦取消选中复选框,文本就会被解包,但再次检查复选框不会再次包装文本。控制台显示正在调用该线程。如何使复选框工作以设置/取消设置文本区域的自动换行行为?
答案 0 :(得分:6)
这是工作代码。 (带有一个可爱的动画屏幕截图,其中的评论突出显示了几个答案错过的内容。)
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
class TextAreaWrapChooser {
private JTextArea text = new JTextArea(8,30);
TextAreaWrapChooser() {
final JScrollPane scroll = new JScrollPane(text);
JToolBar tb = new JToolBar();
JCheckBox wrap = new JCheckBox("Line wrap", false);
tb.add(wrap);
wrap.addItemListener(new ItemListener() {
// this method is called on the EDT
public void itemStateChanged(ItemEvent ie) {
boolean doWrap = ie.getStateChange() == ItemEvent.SELECTED;
System.out.println("Wrap text: " + doWrap);
text.setLineWrap( doWrap );
}
});
// fill the text area
try {
File f = new File("TextAreaWrapChooser.java");
FileReader fr = new FileReader(f);
text.read( fr, f );
} catch(Exception weTried) {
}
JPanel gui = new JPanel(new BorderLayout(2,2));
gui.add(tb, BorderLayout.NORTH);
gui.add(scroll, BorderLayout.CENTER);
JOptionPane.showMessageDialog(null, gui);
}
public static void main(String[] args) {
// construct/start the GUI on the EDT.
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new TextAreaWrapChooser();
}
});
}
}
答案 1 :(得分:5)
没有理由开始单独的Thread
。更糟糕的是,您不应该修改非EDT上的Swing组件。请参阅Concurrency in Swing教程
chkSwing.addItemListener(
new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
keyField.setLineWrap( e.getStateChange() == ItemEvent.SELECTED );
}
} );
会这样做。
答案 2 :(得分:4)
为什么在单独的线程中调用wrap set?可以在SwingUtilities.invokeLater()
中调用它吗?
答案 3 :(得分:4)
在Swing中,您对图形组件所做的所有更改都应在EventDispatchThread中完成。
要从任何线程执行此操作,最简单的方法是使用SwingUtilities.invokeLater()
方法。
在您的情况下,您希望从Swing侦听器回调更改组件,这意味着您已经在EventDispatchThread中。因此,您可以从监听器中调用setLineWrap
方法。