1 簡(jiǎn)單入門(mén)例子
入門(mén)例子是從參考文獻(xiàn)2與3中粘過(guò)來(lái)的內(nèi)容棘催。
在Swing中,如果需要重定向System.err和System.out到一個(gè)JTextPane或一個(gè)JTextArea,你僅需要覆寫(xiě)OutputStream類(lèi)的write()方法能真,以追加文本到文本組件。下面給一個(gè)關(guān)于JTextArea的例子。
private JTextArea textArea = new JTextArea(4, 25);
// 本質(zhì)上相當(dāng)于多線程的更新JTextArea內(nèi)容
private void updateTextArea(final String text) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
textArea.append(text);
}
});
}
private void redirectSystemStreams() {
OutputStream out = new OutputStream() {
@Override
public void write(int b) throws IOException {
updateTextArea(String.valueOf((char) b));
}
@Override
public void write(byte[] b, int off, int len) throws IOException {
updateTextArea(new String(b, off, len));
}
@Override
public void write(byte[] b) throws IOException {
write(b, 0, b.length);
}
};
System.setOut(new PrintStream(out, true));
System.setErr(new PrintStream(out, true));
}
@Test
public void run() {
// 使用粉铐,調(diào)用redirectSystemStreams()即可疼约。
redirectSystemStreams();
// 下面這句話會(huì)轉(zhuǎn)向textArea中輸出
System.out.println("hello, world");
}
2 實(shí)時(shí)輸出問(wèn)題
redirectSystemStreams方法,本質(zhì)上是多線程的更新JTextArea內(nèi)容蝙泼。在處理Swing上的點(diǎn)擊事件時(shí)程剥,事件處理返回之前,其他事件是不能觸發(fā)的汤踏,界面類(lèi)似于卡住的狀況织鲸。
因此,在Swing點(diǎn)擊事件結(jié)束后溪胶,更新JTextArea內(nèi)容的線程才能運(yùn)行搂擦,這樣的效果是內(nèi)容輸出是非實(shí)時(shí)的。
怎樣解決這個(gè)問(wèn)題呢哗脖?在事件處理函數(shù)里面瀑踢,重開(kāi)一個(gè)線程,在這個(gè)新開(kāi)的線程里面才避,執(zhí)行比較耗時(shí)的計(jì)算與相應(yīng)的打印內(nèi)容橱夭。這樣的話,事件處理函數(shù)所在的線程會(huì)快速的線束桑逝,其它更新Swing的JTextArea內(nèi)容的線程才能被執(zhí)行徘钥。
下面以偽代碼的形式,給出一個(gè)例子肢娘,說(shuō)明事件處理函數(shù)的寫(xiě)法呈础。
public class InstallBtnListener implements ActionListener {
// 日志頁(yè)面類(lèi),該類(lèi)有一個(gè)JTextArea屬性橱健,是打印內(nèi)容目標(biāo)輸出位置;
private LogFrame logFrame = new LogFrame();
public InstallBtnListener() {
super();
// 使輸出轉(zhuǎn)向JTextArea;
// 這里我封閉了個(gè)類(lèi)而钞,重點(diǎn)是,將JTextArea傳過(guò)去拘荡,且調(diào)用redirectSystemStreams方法
new RedirectingPrint(logFrame.getTextArea()).redirectSystemStreams();
}
@Override
public void actionPerformed(ActionEvent e) {
// 在事件處理函數(shù)里面臼节,重開(kāi)一個(gè)線程,在這個(gè)新開(kāi)的線程里面珊皿,執(zhí)行比較耗時(shí)的計(jì)算與相應(yīng)的打印內(nèi)容
new Thread(new Runnable() {
@Override
public void run() {
// 比較耗時(shí)的計(jì)算與相應(yīng)的打印內(nèi)容代碼寫(xiě)在這里
}
}).start();
}
}
// JButton點(diǎn)擊事件
jbutton.addActionListener(new InstallBtnListener());
3 總結(jié)
以上网缝,就解決了輸出實(shí)時(shí)性的問(wèn)題。
下面有一段話蟋定,從參考文獻(xiàn)1中粘過(guò)來(lái)的粉臊,用它來(lái)總結(jié)下這個(gè)問(wèn)題。
一般說(shuō)來(lái)驶兜,耗時(shí)的操作不應(yīng)該在事件處理方法中執(zhí)行扼仲,因?yàn)槭录幚矸祷刂霸洞纾渌录遣荒苡|發(fā)的,界面類(lèi)似于卡住的狀況屠凶,所以在獨(dú)立的線程上執(zhí)行比較耗時(shí)的操作可能更好驰后,這會(huì)立即更新用戶界面和釋放事件派發(fā)線程去派發(fā)其他的事件。
4 參考文獻(xiàn)
[1] https://blog.csdn.net/yiziweiyang/article/details/52325308 (java基礎(chǔ)學(xué)習(xí)總結(jié)——java.awt.EventQueue.invokeLater干什么用的)
[2] https://billwaa.wordpress.com/2011/11/14/java-gui-console-output/#comment-100 ([Java] GUI Console Output)
[3] http://unserializableone.blogspot.com/2009/01/redirecting-systemout-and-systemerr-to.html (Redirecting System.out and System.err to JTextPane or JTextArea)
[4] https://stackoverrun.com/cn/q/86020 (如何在eclipse中打印到textArea而不是控制臺(tái)矗愧?)
[5] https://stackoverflow.com/questions/564759/how-to-redirect-all-console-output-to-a-gui-textbox