各位大佬,小弟遇到一個問題,好幾天解決不掉,特來尋找大佬的幫助。
實作需求:只要產生新的String就到實時列印到JTextArea(JTextArea添加到JScrollPane),并且需要實時顯示滾動條。
我的實作:,每次產生新的String就要啟動一個新的執行緒(Thread_update)進行列印,部分代碼如下。
問題:JScrollPane的滾動條只有在結束完成才會一次顯示,中間String都超過JScrollPane的可視域了但是進度條都沒有顯示。
求大佬們幫助。
//初始化JTextArea()和JScrollPane()
return_text = new JTextArea();
//return全域輸出編輯框不可編輯
return_text.setEditable(false);
//設定自動換行
return_text.setLineWrap(true);
// 設定斷行不斷字
return_text.setWrapStyleWord(true);
//return輸出界面(帶進度條)初始化
return_scrollpane = new JScrollPane();
return_scrollpane.setViewportView(return_text);
return_scrollpane.setAutoscrolls(true);
return_scrollpane.setBounds(10, 40, 570, 408);
container.add(return_scrollpane);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//每次產生新的sth就要啟動一個執行緒進行列印
updateThread(sth);
//啟動列印執行緒
private void updateThread(String sth) {
Thread_update thread_update = new Thread_update(sth);
thread_update.start();
try {
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
}
//子執行緒的實作
private class Thread_update extends Thread {
private String sth;
public Thread_update(String sth) {
this.sth = sth;
}
@Override
public void run() {
return_text.setText(return_text.getText() + sth);
return_text.paintImmediately(return_text.getBounds());
return_text.setCaretPosition(return_text.getDocument().getLength());
return_scrollpane.revalidate();
try {
Thread.sleep(100);
} catch (Exception e) {
e.printStackTrace();
}
}
}
uj5u.com熱心網友回復:
把你的執行緒改成這樣試試:
//子執行緒的實作
private static class Thread_update extends Thread {
private String sth;
public Thread_update(String sth) {
this.sth = sth;
}
@Override
public void run() {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
return_text.append(sth);
}
});
try {
Thread.sleep(100);
} catch (Exception e) {
e.printStackTrace();
}
}
}
uj5u.com熱心網友回復:
@Overridepublic void run() {
// return_text.setText(return_text.getText() + sth);
// return_text.paintImmediately(return_text.getBounds());
// return_text.setCaretPosition(return_text.getDocument().getLength());
// return_scrollpane.revalidate();
// try {
// Thread.sleep(100);
// } catch (Exception e) {
// e.printStackTrace();
// }
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
return_text.append(sth);
}
});
try {
Thread.sleep(100);
} catch (Exception e) {
e.printStackTrace();
}
}
}
大佬,run()實作復制你的現在JTextArea都不會實時顯示了
uj5u.com熱心網友回復:
uj5u.com熱心網友回復:
無法實時顯示應該和你的 updateThread 方法中 sleep 有關這個方法你應該是在某個 Listener 中呼叫的,
Swing 所有控制元件的 listener 都是在 EDT 中執行的
而 EDT 負責 UI 繪制
你把 sleep 在 EDT 中執行,會阻礙界面的正常重繪
uj5u.com熱心網友回復:
嗯,是的,這個update_Thread我是放在ActionEvent的監聽器中,然后使用按鈕添加了這個監聽器。大佬的意思是我使這個監聽器所在執行緒睡眠了,影響了UI的繪制?uj5u.com熱心網友回復:
嗯,是這意思。
你之前能讓文字重繪,是因為你強制呼叫了文本控制元件的 paintImmediately ,但是這樣做并不合適
uj5u.com熱心網友回復:
嗯,試了下把listener里邊的sleep全部去掉是可以能正常列印的,滾動條也可以實時顯示,但是因為listener里邊涉及到網路資料的讀取,也不知道可以讀取的位元組數,我現在實作是設計等待時間去讀取,如果不使用sleep可以使用什么去做這個延時又不會影響到UI的繪制?大佬。uj5u.com熱心網友回復:
嗯,試了下把listener里邊的sleep全部去掉是可以能正常列印的,滾動條也可以實時顯示,但是因為listener里邊涉及到網路資料的讀取,也不知道可以讀取的位元組數,我現在實作是設計等待時間去讀取,如果不使用sleep可以使用什么去做這個延時又不會影響到UI的繪制?大佬。
你這樣的需求,應該在你的那個 Thread_update 執行緒中做類似于網路資料讀取的耗時任務
然后再任務做完之后,根據結果再去重繪界面
注意 SwingUtilities.invokeLater 中的任務會在EDT中執行,所以這個里面只能執行UI重繪的代碼
所有耗時代碼也不能放到 SwingUtilities.invokeLater 里做
uj5u.com熱心網友回復:
嗯,試了下把listener里邊的sleep全部去掉是可以能正常列印的,滾動條也可以實時顯示,但是因為listener里邊涉及到網路資料的讀取,也不知道可以讀取的位元組數,我現在實作是設計等待時間去讀取,如果不使用sleep可以使用什么去做這個延時又不會影響到UI的繪制?大佬。
你這樣的需求,應該在你的那個 Thread_update 執行緒中做類似于網路資料讀取的耗時任務
然后再任務做完之后,根據結果再去重繪界面
注意 SwingUtilities.invokeLater 中的任務會在EDT中執行,所以這個里面只能執行UI重繪的代碼
所有耗時代碼也不能放到 SwingUtilities.invokeLater 里做
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/17712.html
標籤:Java SE
上一篇:求解
