-1

私の問題は解決しました。コードは次のとおりです。

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を追加します。これにより、変更のたびにプログレスバーが更新されます。

4

2 に答える 2

1

スイングはスレッドセーフではありません。

ファイルの読み取りでEventDispatchingThreadをブロックしているため、UIは更新されません。これにより、画面上のプログレスバーが更新されなくなります。

@LanguagesNamedAfterCofeeが提案したように、SwingWorkerを使用してファイルの実際の読み取りを実行し、その更新メソッド(publishおよびsetProgress)がUIを更新できるようにする必要があります。

于 2012-07-26T03:02:17.957 に答える
0

使用しているコードのどこかで、これを一致するジェネリックに解決する必要がありますdiamond operator<>

に変換List<String> foo = new ArrayList<>();するようにList<String> foo = new ArrayList<String>();

<>オカレンスを検索して解決するだけです。

于 2012-07-25T22:15:22.873 に答える