[英]My JProgressBar is not Updating Until it is 100%
好的,我有以下代碼。
public class MyProgressBar extends JPanel implements MyData, Serializable {
/**
*
*/
public static final int MAX = 10000;
public static final int WIDTH = 400;
public static final int HEIGHT = 75;
private JProgressBar MyBar = new JProgressBar( SwingConstants.HORIZONTAL, 0, MAX );
private JFrame MyFrame = new JFrame();
private int MyValue = 0;
private Thread MyThread = new Thread( new ProgressThread() );
public MyProgressBar() {
add(MyBar);
int x = ( MyData.SCREEN.width / 2 ) - ( WIDTH / 2);
int y = ( MyData.SCREEN.height / 2 ) - ( HEIGHT / 2);
this.setBounds( x, y, WIDTH, HEIGHT );
MyFrame.setBounds( x, y, WIDTH, HEIGHT );
MyFrame.setUndecorated(true);
MyFrame.getContentPane().setSize( new Dimension( WIDTH, HEIGHT ) );
MyFrame.setMinimumSize( new Dimension( WIDTH, HEIGHT ) );
MyFrame.setPreferredSize( new Dimension( WIDTH, HEIGHT ) );
MyFrame.setSize( new Dimension( WIDTH, HEIGHT ) );
MyFrame.setVisible(false);
MyFrame.getContentPane().setLayout(null);
MyBar.setStringPainted( true );
MyBar.setBorderPainted( true );
MyBar.setValue( 0 );
MyBar.setBounds( 0, 0, WIDTH, HEIGHT );
MyFrame.add( MyBar );
MyFrame.pack();
MyFrame.repaint();
}
public void MyUpdateBar() {
MyBar.setValue( MyValue );
MyBar.repaint();
MyFrame.repaint();
this.repaint();
//dbug.Message( "MYPROGRESSBAR", "MyUpdateBar", "Value is %3.2f %d", MyBar.getPercentComplete(), MyValue );
}
public void MySetValue( int percent ) {
MyValue = (int)( MAX * ( (double)percent / 100.0 ) );
MyUpdateBar();
//dbug.Message( "MYPROGRESSBAR", "MySetValue", "Value is %3.2f %d percent was %d", MyBar.getPercentComplete(), MyValue, percent );
}
public void CreateAndShow () {
MyFrame.setVisible(true);
MyThread.start();
}
public void HideAndClear () {
MyThread.stop();
//frame.setVisible(false);
}
class ProgressThread implements Runnable {
public void run() {
EventQueue.invokeLater(new Runnable() {
public void run() {
while( MyValue < MyBar.getMaximum() ) {
MyBar.setValue( MyValue );
MyBar.repaint();
MyFrame.repaint();
dbug.Message( "MYPROGRESSBAR", "THREAD", "Value is %3.2f %d", MyBar.getPercentComplete(), MyValue );
}
}
});
}
}
}
如您所見,我創建了一個類來顯示進度。 發生的事情是我實例化了這個類。 加載我的 XML 文件,然后當我解析數據時,我正在調用更新 MyValue,當我讓我的 dbug 消息出來時,我會看到它。 但是,直到 100% 完成,條形圖本身才會顯示。 我已經閱讀了有關線程和遵循其他人的示例的內容,如果我將其作為他的示例,它會起作用。 如果我進行了一些調整(更改線程中的循環以填充進度條的設置值以讀取值),它甚至不會顯示到 100。
我做錯了什么?
謝謝!
您的線程執行SwingUtilities.invokeLater
。 您有效地在 Swing 的Event Dispatch Thread
上運行。 不知道你想達到什么目的。 但看起來您正在阻止EDT
並且您的while
循環未更新,因為MySetValue
未執行。
考慮使用SwingWorker
進行冗長的操作。 如何使用進度條演示了如何將SwingWorker
與JProgressBar
。
確保從Event Dispatch Thread
調用setValue
方法。 您可以為此使用SwingUtilities.invokeLater
。 閱讀有關線程和 Swing 的更多信息。
考慮這個簡化的示例:
public static void main(String[] arguments) {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
final JProgressBar bar = new JProgressBar(0, 100);
Thread t = new Thread(){
public void run(){
for(int i = 0 ; i < 100 ; i++){
final int percent = i;
SwingUtilities.invokeLater(new Runnable() {
public void run() {
bar.setValue(percent);
}
});
try {
Thread.sleep(100);
} catch (InterruptedException e) {}
}
}
};
frame.add(bar);
frame.pack();
frame.setVisible(true);
t.start();
}
問題是您在 EDT 中使用了一個循環來更新進度。 在該循環退出之前,EDT 無法調度事件(如重繪、重新驗證、invokeLater、鼠標事件、鍵事件等),阻止它刷新進度條。
您應該嘗試找到一種方法,讓 EDT 在進度條的每次更新之間調度其事件。 理想情況下,您使用SwingWorker將“工作”移到 EDT 之外,同時進度條通過 EDT 中的屬性更改偵聽器進行更新。
僅供參考,在 Java 中,方法和變量以小寫字母開頭。 您的代碼對其他人來說真的很難閱讀。
因此,我嘗試按照教程進行操作,這就是我所處的位置。
好的,我已經嘗試過遵循教程,但我一直在某個地方迷路。 我需要的是一個創建和顯示進度條 (JProgressBar) 的類,我可以在迭代從文件加載的數據並將其放入數據庫內存時設置它的值。 我的問題是,我發現的每個示例都有某種計數器,可以填充進度條並從“主”函數執行。 每次我將該教程更改為可以隨意調用並顯示欄的課程時,我都沒有顯示欄(即框架出現但欄甚至看起來都沒有添加到框架中,直到之后迭代完成)。 我曾嘗試使用 SwingUtilities.invokeLater 和 SwingWorker(在下面的課堂上的最新嘗試)都有同樣的問題。 更糟糕的是,我可以執行 dbug.myMessage(基本上發送到 System.out)並看到一條消息,該消息表明該條在內存中正在發生變化,只是沒有顯示。 我顯然錯過了一些可能很簡單的東西,但我想不出它是什么。
哦,還有一件事,如果我將教程保持原樣( http://docs.oracle.com/javase/tutorial/displayCode.html?code=http://docs.oracle.com/javase/tutorial/uiswing/ examples/components/ProgressBarDemo2Project/src/components/ProgressBarDemo2.java ) 並將 main 更改為 createAndShow 方法,它可以工作,但當然它沒有做我需要它做的事情。
我確實發布了關於此的另一個問題,但已經改變了課程,我認為最好發布一個新問題。
所以,這是我修改過的代碼,但似乎不起作用:
public class MyProgressBar extends JPanel implements PropertyChangeListener,
MyData,
Serializable {
/**
*
*/
private static final long serialVersionUID = -1632492668549544408L;
private MyDebug dbug = new MyDebug( MyData.MYDEBUGCHECK.MYPROGRESSBAR.getOn() );
public static final int MAX = 100;
public static final int WIDTH = 400;
public static final int HEIGHT = 75;
private JProgressBar myBar = new JProgressBar( SwingConstants.HORIZONTAL, 0, MAX );
private JFrame myFrame = new JFrame();
public Task task;
class Task extends SwingWorker<Void, Void> {
public int myValue = 0;
@Override
public Void doInBackground() {
//Initialize progress property.
setProgress(0);
while (myValue < 100) {
//Make random progress.
//myValue += random.nextInt(10);
setProgress( Math.min( myValue, 100 ) );
dbug.myMessage( "MYPROGRESSBAR", "doInBackground", "Value is %3.2f %d", myBar.getPercentComplete(), myValue );
myBar.repaint();
}
return null;
}
public void done() {
}
public void mySetValue( int percent ) {
myValue = (int)( MAX * ( (double)percent / 100.0 ) );
dbug.myMessage( "MYPROGRESSBAR", "mySetValue", "Value is %3.2f %d percent was %d", myBar.getPercentComplete(), myValue, percent );
}
}
public MyProgressBar() {
add(myBar);
int x = ( MyData.SCREEN.width / 2 ) - ( WIDTH / 2);
int y = ( MyData.SCREEN.height / 2 ) - ( HEIGHT / 2);
this.setBounds( x, y, WIDTH, HEIGHT );
myFrame.setBounds( x, y, WIDTH, HEIGHT );
myFrame.setUndecorated(true);
myFrame.getContentPane().setSize( new Dimension( WIDTH, HEIGHT ) );
myFrame.setMinimumSize( new Dimension( WIDTH, HEIGHT ) );
myFrame.setPreferredSize( new Dimension( WIDTH, HEIGHT ) );
myFrame.setSize( new Dimension( WIDTH, HEIGHT ) );
myFrame.setVisible(false);
myFrame.getContentPane().setLayout(null);
myFrame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
myBar.setStringPainted( true );
myBar.setBorderPainted( true );
myBar.setValue( 0 );
myBar.setBounds( 0, 0, WIDTH, HEIGHT );
myBar.addPropertyChangeListener( this );
myFrame.add( myBar );
//Create and set up the content pane.
//JComponent newContentPane = new MyProgressBar();
JComponent newContentPane = myBar;
newContentPane.setOpaque(true); //content panes must be opaque
myFrame.setContentPane(newContentPane);
myFrame.pack();
}
public void createAndShow () {
//Display the window.
myFrame.setVisible(true);
myFrame.repaint();
}
public void hideAndClear () {
//myFrame.setVisible(false);
}
@Override
public void propertyChange(PropertyChangeEvent args) {
dbug.myMessage( "MYPROGRESSBAR", "propertyChange", "Value is %s", args.getPropertyName() );
if ( "progress" == args.getPropertyName() ) {
int progress = (Integer) args.getNewValue();
//myBar.setValue(progress);
}
}
public void start () {
//Instances of javax.swing.SwingWorker are not reusuable, so
//we create new instances as needed.
task = new Task();
task.addPropertyChangeListener(this);
task.execute();
}
}
以下代碼段在進行中更新進度條
SwingUtilities.invokeLater(new Runnable() {
public void run() {
progressBar.setValue((int)percentage);
//below code to update progress bar while running on thread
progressBar.update(progressBar.getGraphics());}
});
進度條的動態進度更新是通過以下代碼實現的:
int progress = Math.round(((float)finished/(float)(total)) * 100);
uploadPrgressBar.setIndeterminate(progress == 0);
uploadPrgressBar.setValue(progress);
uploadPrgressBar.update(uploadPrgressBar.getGraphics());
在循環中調用包含上述代碼的方法(代碼邏輯),每次迭代后都會動態更新進度條
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.