Java JTextArea尝试打开新的JDialog并刷新时未显示 [英] Java JTextArea Not showing up when trying to open new JDialog and refresh
问题描述
当创建一个包含文本区域的新对话框,然后运行输出到文本区域的代码时,直到代码执行完成,文本区域才会显示出来.我希望在执行代码时刷新文本区域.这是一些示例代码,演示了此问题.
When creating a new dialog containing a text area and then running code that outputs to the text area, the text area is not showing up until the code execution finishes. I would like the text area to refresh while the code is executing. Here is some sample code that demonstrates the problem.
package textareatester;
import java.io.PrintStream;
import javax.swing.JOptionPane;
public class NewJFrame extends javax.swing.JFrame
{
/**
* Creates new form NewJFrame
*/
public NewJFrame()
{
initComponents();
}
@SuppressWarnings("unchecked")
private void initComponents()
{
jButton1 = new javax.swing.JButton();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
jButton1.setText("Test Me");
jButton1.addActionListener(new java.awt.event.ActionListener()
{
public void actionPerformed(java.awt.event.ActionEvent evt)
{
jButton1ActionPerformed(evt);
}
});
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addContainerGap(175, Short.MAX_VALUE)
.addComponent(jButton1)
.addGap(154, 154, 154))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(113, 113, 113)
.addComponent(jButton1)
.addContainerGap(164, Short.MAX_VALUE))
);
pack();
}
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt)
{
NewJDialog dialog = new NewJDialog(this, "Output", false );
dialog.setVisible(true);
PrintStream ps = System.out;
System.setOut(new PrintStream(new StreamCapturer("STDOUT", dialog, ps)));
OutputMaker oMaker = new OutputMaker();
oMaker.makeOutput();
JOptionPane.showMessageDialog(this,"OUtput ran successfully!", "Success!", JOptionPane.INFORMATION_MESSAGE);
}
/**
* @param args the command line arguments
*/
public static void main(String args[])
{
try
{
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels())
{
if ("Nimbus".equals(info.getName()))
{
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException ex)
{
java.util.logging.Logger.getLogger(NewJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (InstantiationException ex)
{
java.util.logging.Logger.getLogger(NewJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (IllegalAccessException ex)
{
java.util.logging.Logger.getLogger(NewJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (javax.swing.UnsupportedLookAndFeelException ex)
{
java.util.logging.Logger.getLogger(NewJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable()
{
public void run()
{
new NewJFrame().setVisible(true);
}
});
}
private javax.swing.JButton jButton1;
}
package textareatester;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
public class StreamCapturer extends OutputStream
{
private StringBuilder buffer;
private String prefix;
private NewJDialog consumer;
private PrintStream old;
public StreamCapturer(String prefix, NewJDialog consumer, PrintStream old)
{
this.prefix = prefix;
buffer = new StringBuilder(128);
buffer.append("[").append(prefix).append("] ");
this.old = old;
this.consumer = consumer;
}
@Override
public void write(int b) throws IOException
{
char c = (char) b;
String value = Character.toString(c);
buffer.append(value);
if (value.equals("\n"))
{
consumer.appendText(buffer.toString());
buffer.delete(0, buffer.length());
buffer.append("[").append(prefix).append("] ");
}
old.print(c);
}
}
package textareatester;
import java.util.logging.Level;
import java.util.logging.Logger;
public class OutputMaker
{
public void makeOutput()
{
try
{
System.out.println("Output for line 1.");
Thread.sleep(2000);
System.out.println("Output for line 2.");
Thread.sleep(2000);
System.out.println("Output for line 3.");
Thread.sleep(2000);
System.out.println("Output for line 4.");
Thread.sleep(2000);
System.out.println("Output for line 5.");
} catch (InterruptedException ex)
{
Logger.getLogger(OutputMaker.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
package textareatester;
import java.awt.EventQueue;
public class NewJDialog extends javax.swing.JDialog
{
/**
* Creates new form NewJDialog
*/
public NewJDialog(java.awt.Frame parent, boolean modal)
{
this(parent, "", modal);
}
public NewJDialog(java.awt.Frame parent, String title, boolean modal)
{
super(parent, title, modal);
initComponents();
}
@SuppressWarnings("unchecked")
private void initComponents()
{
jScrollPane2 = new javax.swing.JScrollPane();
jTextArea1 = new javax.swing.JTextArea();
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
jTextArea1.setColumns(20);
jTextArea1.setRows(5);
jScrollPane2.setViewportView(jTextArea1);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 410, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 300, Short.MAX_VALUE)
);
pack();
}
public void appendText(final String text)
{
if (EventQueue.isDispatchThread())
{
jTextArea1.append(text);
jTextArea1.setCaretPosition(jTextArea1.getText().length());
} else
{
EventQueue.invokeLater(new Runnable()
{
@Override
public void run()
{
appendText(text);
}
});
}
}
private javax.swing.JScrollPane jScrollPane2;
private javax.swing.JTextArea jTextArea1;
}
推荐答案
From what I can tell, you code is based on my previous answer
问题是,您是在事件调度线程的上下文中使用Thread.sleep
的,这将阻止它在jButton1ActionPerformed
返回之前处理任何新事件(包括重绘事件).
The problem is, you're using Thread.sleep
from within the context of the Event Dispatching Thread, which is prevent it from processing any new events (including repaint events) until after the jButton1ActionPerformed
returns.
例如,您需要使用一个单独的线程,例如SwingWorker
或仅使用一个普通的旧线程(如append
方法将同步更新同步到UI本身),例如
Instead, you need to be using a separate thread, like SwingWorker
or just a plain old thread (seen as the append
method synchronises updates to the UI by itself), for example
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class TestRedirect {
public static void main(String[] args) {
new TestRedirect();
}
public TestRedirect() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException ex) {
} catch (InstantiationException ex) {
} catch (IllegalAccessException ex) {
} catch (UnsupportedLookAndFeelException ex) {
}
CapturePane capturePane = new CapturePane();
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(capturePane);
frame.setSize(200, 200);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
PrintStream ps = System.out;
System.setOut(new PrintStream(new StreamCapturer("STDOUT", capturePane, ps)));
}
});
}
public class CapturePane extends JPanel implements Consumer {
private JTextArea output;
public CapturePane() {
setLayout(new BorderLayout());
output = new JTextArea();
add(new JScrollPane(output));
JButton test = new JButton("Test");
test.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
SwingWorker worker = new SwingWorker() {
@Override
protected Object doInBackground() throws Exception {
System.out.println("Hello world");
Thread.sleep(1000);
System.out.println("I'm calling you from another thread");
Thread.sleep(1000);
System.out.println("But you can still see the updates as they occur");
return null;
}
@Override
protected void done() {
test.setEnabled(true);
}
};
test.setEnabled(false);
worker.execute();
}
});
add(test, BorderLayout.SOUTH);
}
@Override
public void appendText(final String text) {
if (EventQueue.isDispatchThread()) {
output.append(text);
output.setCaretPosition(output.getText().length());
} else {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
appendText(text);
}
});
}
}
}
public interface Consumer {
public void appendText(String text);
}
public class StreamCapturer extends OutputStream {
private StringBuilder buffer;
private String prefix;
private Consumer consumer;
private PrintStream old;
public StreamCapturer(String prefix, Consumer consumer, PrintStream old) {
this.prefix = prefix;
buffer = new StringBuilder(128);
buffer.append("[").append(prefix).append("] ");
this.old = old;
this.consumer = consumer;
}
@Override
public void write(int b) throws IOException {
char c = (char) b;
String value = Character.toString(c);
buffer.append(value);
if (value.equals("\n")) {
consumer.appendText(buffer.toString());
buffer.delete(0, buffer.length());
buffer.append("[").append(prefix).append("] ");
}
old.print(c);
}
}
}