0

我有一个像这样初始化的 Java-Gnome GUI:

public static void main(String[] args) {
    Gtk.init(args);
    new GTK();
    Gtk.main();
}

public GTK() {
    initUI(this);
    //Exit GUI cleanly if close pressed
    connect(this);
    showAll();
}

public void initUI(final GTK gtk) {
    //Add various panes, boxes, buttons etc...
    //All my UI updates made at runtime here work correctly

    start.connect(new Button.Clicked(){

    @Override
    public void onClicked(Button start){
    worker = new worker(fileList, gtk);
    Thread workerThread = new Thread(worker);
    workerThread.start();

    Glib.idleAdd(new Handler(){
    public boolean run(){

    progress = worker.getProgress();

    if(progress != 1){
        progressBar.setFraction(progress);
        return true;
    }
    else{
          progressBar.setFraction(progress);
          return false;
                }
             }
         });
            }
    });
}

其中progressBar 是我的GUI 中的一个组件(org.gnome.gtk.ProgressBar),但progressBar 直到一切都完成运行后才会更新,它似乎被放在队列的后面并且只是在最后执行而不是立即如我所愿。

http://java-gnome.sourceforge.net/NEWS.html

http://java-gnome.sourceforge.net/doc/api/4.1/org/gnome/glib/Glib.html#idleAdd(org.gnome.glib.Handler)

编辑。

我的工作线程首先跨越两个类:

public class auCDtect implements Runnable { 

private String processingLog;
private String output;
private String summary;
private Collection<String> fileList;
private double progress = 0.0;
private GTK gtk;

auCDtect(Collection<String> fileList, GTK gtk){this.fileList = fileList; this.gtk = gtk;}

public void run () {

    List<String> command = new ArrayList<String>();
    command.add("./auCDtect");
    command.add("-d");
    command.add("-m10");

    //Add each song passed to this class to the auCDtect command
    for(String file:fileList){

        command.add(file);
    }
    ProcessBuilder processBuilder = new ProcessBuilder(command);

        Process process = null;
        try {
            process = processBuilder.start();
        } catch (IOException e) {
            e.printStackTrace();
        }

        //Set up error stream thread 
        StreamGobbler errorGobbler = new StreamGobbler(process.getErrorStream(), "ERROR", this); 

        //Set up output stream thread
        StreamGobbler outputGobbler = new StreamGobbler(process.getInputStream(), "OUTPUT", this); 

        // Start error and input stream threads
        new Thread(errorGobbler).start(); 
        new Thread(outputGobbler).start(); 
  }

public void update(double progress, String processingLog, String output, String summary){

    this.processingLog = processingLog;
    this.output = output;
    this.summary = summary;
    this.progress = progress/(fileList.size());
    gtk.setOutputUpdated(true);
    try {
        Thread.sleep(100);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

public double getProgress(){

    return progress;
}

public String getProcessingLog(){

    return processingLog;
}

public String getOutput(){

    return output;
}

public String getSummary(){

    return summary;
}

}

第二个由第一个产生:

public class StreamGobbler implements Runnable { 

InputStream inputStream; 
String type;
private String processingLog = null;
private String output = null;
private String summary = null;
protected boolean finished = false;
private auCDtect auCDtect;
private int progress = 0;

StreamGobbler(InputStream inputStream, String type, auCDtect auCDtect){this.inputStream = inputStream; this.type = type; this.auCDtect = auCDtect;} 

public void run(){ 

    Scanner scanner = new Scanner(inputStream);

    while (((scanner.hasNextLine())&&(type == "OUTPUT"))){

        String line = scanner.nextLine();

        if(line.contains("Processing file:")){
            processingLog = line.substring(line.indexOf("P"), (line.indexOf("]")+1));
        }
        if(line.contains("This track looks like")){
            output = line.substring(line.indexOf("This track"), (line.indexOf("%")+1));
            progress = progress + 1;
        }
        if(line.contains("These")){
            summary = line.substring(line.indexOf("These tracks"));
        }

        if((type == "OUTPUT")&&(progress > 0)){

            auCDtect.update(progress, processingLog, output, summary);
            processingLog = null;
            output = null;
            summary = null;
        }
    }

}
}
4

1 回答 1

1

不确定这适用于java版本,我更习惯C版本,但无论如何......

尝试更新主线程的不应该是工作线程,而是相反。从处理clicked信号的回调中,您应该调用idleAdd,并创建和运行您的工作线程。在工作线程中,您更新主线程可以访问的变量,以及您将放置进度值的位置。然后,主循环将偶尔运行一次空闲处理程序,并读取该值。然后它会更新进度条,但重要的是这个调用是从主线程完成的。

GTK 不是线程安全的,因为大多数工具包(java 版本可能接近于线程安全,但我不是 100% 确定,并且在 GTK 中所做的后续更改可能会在将来破坏这一点,所以我不会依赖它)。因此,您的工作线程不应与用户界面组件混淆。

对此持保留态度,我知道 C 中的一些 GTK,而不是 java-gnome,所以我可能完全错了,idleAdd无论如何文档似乎都证实了这一点。

于 2013-01-22T12:42:14.460 回答