2012-07-25 2 views
-1

Моя проблема решена. Вот код:Использование jProgressBar с SaxParser

SwingWorker класс:

package ths.turnier; 

import javax.swing.SwingUtilities; 

/** 
* This is the 3rd version of SwingWorker (also known as 
* SwingWorker 3), an abstract class that you subclass to 
* perform GUI-related work in a dedicated thread. For 
* instructions on using this class, see: 
* 
* http://java.sun.com/docs/books/tutorial/uiswing/misc/threads.html 
* 
* Note that the API changed slightly in the 3rd version: 
* You must now invoke start() on the SwingWorker after 
* creating it. 
*/ 
public abstract class SwingWorker { 
private Object value; // see getValue(), setValue() 
private Thread thread; 

/** 
* Class to maintain reference to current worker thread 
* under separate synchronization control. 
*/ 
private static class ThreadVar { 
    private Thread thread; 
    ThreadVar(Thread t) { thread = t; } 
    synchronized Thread get() { return thread; } 
    synchronized void clear() { thread = null; } 
} 

private ThreadVar threadVar; 

/** 
* Get the value produced by the worker thread, or null if it 
* hasn't been constructed yet. 
*/ 
protected synchronized Object getValue() { 
    return value; 
} 

/** 
* Set the value produced by worker thread 
*/ 
private synchronized void setValue(Object x) { 
    value = x; 
} 

/** 
* Compute the value to be returned by the <code>get</code> method. 
*/ 
public abstract Object construct(); 

/** 
*   public void run() { finished(); } Called on the event dispatching thread (not on the worker thread) 
* after the <code>construct</code> method has returned. 
*/ 
public void finished() { 
} 

/** 
* A new method that interrupts the worker thread. Call this method 
* to force the worker to stop what it's doing. 
*/ 
public void interrupt() { 
    Thread t = threadVar.get(); 
    if (t != null) { 
     t.interrupt(); 
    } 
    threadVar.clear(); 
} 

/** 
* Return the value created by the <code>construct</code> method. 
* Returns null if either the constructing thread or the current 
* thread was interrupted before a value was produced. 
* 
* @return the value created by the <code>construct</code> method 
*/ 
public Object get() { 
    while (true) { 
     Thread t = threadVar.get(); 
     if (t == null) { 
      return getValue(); 
     } 
     try { 
      t.join(); 
     } 
     catch (InterruptedException e) { 
      Thread.currentThread().interrupt(); // propagate 
      return null; 
     } 
    } 
} 


/** 
* Start a thread that will call the <code>construct</code> method 
* and then exit. 
*/ 
public SwingWorker() { 
    final Runnable doFinished = new Runnable() { 
     public void run() { finished(); } 
    }; 

    Runnable doConstruct = new Runnable() { 
     public void run() { 
      try { 
       setValue(construct()); 
      } 
      finally { 
       threadVar.clear(); 
      } 

      SwingUtilities.invokeLater(doFinished); 
     } 
    }; 

    Thread t = new Thread(doConstruct); 
    threadVar = new ThreadVar(t); 
} 

/** 
* Start the worker thread. 
*/ 
public void start() { 
    Thread t = threadVar.get(); 
    if (t != null) { 
     t.start(); 
    } 
} 
} 

MonitoredInputStream:

/** 
* A class that monitors the read progress of an input stream. 
* 
* @author Hermia Yeung "Sheepy" 
* @since 2012-04-05 18:42 
*/ 
public class MonitoredInputStream extends FilterInputStream { 
private volatile long mark = 0; 
private volatile long lastTriggeredLocation = 0; 
private volatile long location = 0; 
private final int threshold; 
private final List<ChangeListener> listeners = new ArrayList<ChangeListener>(4); 

/** 
* Creates a MonitoredInputStream over an underlying input stream. 
* @param in Underlying input stream, should be non-null because of no public setter 
* @param threshold Min. position change (in byte) to trigger change event. 
*/ 
public MonitoredInputStream(InputStream in, int threshold) { 
    super(in); 
    this.threshold = threshold; 
} 

/** 
* Creates a MonitoredInputStream over an underlying input stream. 
* Default threshold is 16KB, small threshold may impact performance impact on larger streams. 
* @param in Underlying input stream, should be non-null because of no public setter 
*/ 
public MonitoredInputStream(InputStream in) { 
    super(in); 
    this.threshold = 1024*16; 
} 

public void addChangeListener(ChangeListener l) { if (!listeners.contains(l)) listeners.add(l); } 
public void removeChangeListener(ChangeListener l) { listeners.remove(l); } 
public long getProgress() { return location; } 

protected void triggerChanged(final long location) { 
    if (threshold > 0 && Math.abs(location-lastTriggeredLocation) < threshold) return; 
    lastTriggeredLocation = location; 
    if (listeners.size() <= 0) return; 
    try { 
    final ChangeEvent evt = new ChangeEvent(this); 
    for (ChangeListener l : listeners) l.stateChanged(evt); 
    } catch (ConcurrentModificationException e) { 
    triggerChanged(location); // List changed? Let's re-try. 
    } 
} 


@Override public int read() throws IOException { 
    final int i = super.read(); 
    if (i != -1) triggerChanged(location++); 
    return i; 
} 

@Override public int read(byte[] b, int off, int len) throws IOException { 
    final int i = super.read(b, off, len); 
    if (i > 0) triggerChanged(location += i); 
    return i; 
} 

@Override public long skip(long n) throws IOException { 
    final long i = super.skip(n); 
    if (i > 0) triggerChanged(location += i); 
    return i; 
} 

@Override public void mark(int readlimit) { 
    super.mark(readlimit); 
    mark = location; 
} 

@Override public void reset() throws IOException { 
    super.reset(); 
    if (location != mark) triggerChanged(location = mark); 
} 
} 

Как использовать это:

void updateProgressWknAdd(final int i) 
{ 
Runnable doSetProgress = new Runnable() { 
public void run() { 
progressWknAdd.setValue(i); 
} 
}; 
SwingUtilities.invokeLater(doSetProgress); 
} 

    Object doWorkWkn(String pfad) { 
// Code which reads file + setting the max of jprogressbar to file size. and: 
final MonitoredInputStream mis = new MonitoredInputStream(fis); 
     mis.addChangeListener(new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { 
     updateProgressWknRead((int) mis.getProgress()); 
     }}); 
} 

Как использовать работника:

SwingWorker worker = new SwingWorker() { 
      public Object construct() { 
       return doWorkWkn(pfad_zur_datei); 
      } 

      public void finished() { 
       frame_progressbar.setVisible(false); 
      } 
     }; 
     worker.start(); 

SwingWorker запускает doWorkWkn, пока не закончен. После этого jFrame устанавливается невидимым. doWorkWkn() считывает файл и добавляет changeListener, который обновляет панель прогресса при каждом изменении.

ответ

1

Свинг НЕ нить безопасный.

Пользовательский интерфейс не обновляется, поскольку вы блокируете EventDispatchingThread с чтением файла. Это предотвращает обновление индикатора выполнения на экране.

Как предложил @LanguagesNamedAfterCofee, вы должны использовать SwingWorker для выполнения фактического чтения файла и позволяют это методы обновления (publish и setProgress) для обновления пользовательского интерфейса.

+0

Спасибо! Оно работает! Я отправлю решение вечером. – poldi

0

В коде, которую вы используете, используется diamond operator, то есть <>. Вам необходимо решить эту проблему с помощью соответствующего родового.

Как превратить List<String> foo = new ArrayList<>(); в List<String> foo = new ArrayList<String>();

Просто поиск <> возникновения и устранить ее.

+0

Спасибо за помощь! Выше я добавил еще несколько кодов. JProgressBar не обновляется и остается на 0% до завершения задачи. После этого он показывает 100%. Знаете ли вы, почему? Я не могу понять, почему ... – poldi

+2

@ user1552265 Использование SwingWorker – LanguagesNamedAfterCofee