Swingworker замораживает диалоги, не обновляя

Я надеюсь, что задаю здесь правильные вопросы, но не стесняйтесь спрашивать меня о любой дополнительной информации. Я пытаюсь написать программу на Java, которая будет обрабатывать фрагмент кода из текстовой области. программа делает именно то, что я от нее ожидаю, но может занять некоторое время, поэтому я хочу поместить JProgressBar в диалоговое окно, которое будет обновляться. Я просмотрел образцы оракула на индикаторах выполнения и пытаюсь сделать что-то вроде примера в http://docs.oracle.com/javase/tutorial/uiswing/components/progress.html

Это использует достаточно простой пример, где...

  • общий класс JFrame имеет подкласс Task, который расширяет Swingworker. Класс Swingworker (Task) выполняет задачу в фоновом режиме, используя метод doinBackground().
  • Прогресс обновляется методом setProgress().
  • Основная задача JFrame реализует propertychangelistener

я так понимаю, когда ProgressBarDemo вызывает Task, он связывает свой собственный propertychangelistener с задачей, а когда Task вызывает setprogress(), изменение данных транслируется в метод ProgressBarDemos propertyChange(evt).

И это отлично работает как пример.

public class ProgressBarDemo extends JPanel
    implements ActionListener,
    PropertyChangeListener {

private JProgressBar progressBar;
private JButton startButton;
private JTextArea taskOutput;
private Task task;

class Task extends SwingWorker<Void, Void> {
    /*
     * Main task. Executed in background thread.
     */

    @Override
    public Void doInBackground() {
        Random random = new Random();
        int progress = 0;
        //Initialize progress property.
        setProgress(0);
        while (progress < 100) {
            //Sleep for up to one second.
            try {
                Thread.sleep(random.nextInt(1000));
            } catch (InterruptedException ignore) {
            }
            //Make random progress.
            progress += random.nextInt(10);
            setProgress(Math.min(progress, 100));
        }
        return null;
    }

    /*
     * Executed in event dispatching thread
     */
    @Override
    public void done() {
        Toolkit.getDefaultToolkit().beep();
        startButton.setEnabled(true);
        setCursor(null); //turn off the wait cursor
        taskOutput.append("Done!\n");
    }
}

public ProgressBarDemo() {
    super(new BorderLayout());

    //Create the demo's UI.
    startButton = new JButton("Start");
    startButton.setActionCommand("start");
    startButton.addActionListener(this);

    progressBar = new JProgressBar(0, 100);
    progressBar.setValue(0);
    progressBar.setStringPainted(true);

    taskOutput = new JTextArea(5, 20);
    taskOutput.setMargin(new Insets(5, 5, 5, 5));
    taskOutput.setEditable(false);

    JPanel panel = new JPanel();
    panel.add(startButton);
    panel.add(progressBar);

    add(panel, BorderLayout.PAGE_START);
    add(new JScrollPane(taskOutput), BorderLayout.CENTER);
    setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));

}

/**
 * Invoked when the user presses the start button.
 */
public void actionPerformed(ActionEvent evt) {
    startButton.setEnabled(false);
    setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
    //Instances of javax.swing.SwingWorker are not reusuable, so
    //we create new instances as needed.
    task = new Task();
    task.addPropertyChangeListener(this);
    task.execute();
}

/**
 * Invoked when task's progress property changes.
 */
public void propertyChange(PropertyChangeEvent evt) {
    if ("progress" == evt.getPropertyName()) {
        int progress = (Integer) evt.getNewValue();
        progressBar.setValue(progress);
        taskOutput.append(String.format(
                "Completed %d%% of task.\n", task.getProgress()));
    }
}

/**
 * Create the GUI and show it. As with all GUI code, this must run on the
 * event-dispatching thread.
 */
private static void createAndShowGUI() {
    //Create and set up the window.
    JFrame frame = new JFrame("ProgressBarDemo");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    //Create and set up the content pane.
    JComponent newContentPane = new ProgressBarDemo();
    newContentPane.setOpaque(true); //content panes must be opaque
    frame.setContentPane(newContentPane);

    //Display the window.
    frame.pack();
    frame.setVisible(true);
}

public static void main(String[] args) {
    //Schedule a job for the event-dispatching thread:
    //creating and showing this application's GUI.
    javax.swing.SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            createAndShowGUI();
        }
    });
}
}

как видно из примера, нет экземпляров revalidate() invalidate() repaint() и т.д. и все работает как надо, однако я попытался воссоздать этот подход для своего изменения и графика просто не будет обновляться .

Я также печатаю на консоль, и этот вывод соответствует ожидаемому, но что бы я ни делал, я не могу обновить JProgressBar. Если я включу кнопку для увеличения JProgressbar, она будет работать, и панель JProgress будет обновляться, однако после запуска SwingWorker JProgressbar больше не отвечает графически, даже если я включу revalidate() и т. д.

Я также включил в методы проверку до и после для значений в JProgressbar, и каждый раз он содержит правильные значения... Он просто не будет обновлять диалоговое окно!!!

Любая помощь... Пожалуйста!!!

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package db_udt_searchandreplacetest;

import Model.VariableListProcessor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

/**
 *
 * @author Alan Curley
 */
public class Dialog1 extends javax.swing.JFrame 
        implements ActionListener,
        PropertyChangeListener  {

    /**
     * Creates new form Dialog1
     */
    public Dialog1() {
        initComponents();
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
    private void initComponents() {

        jSeparator1 = new javax.swing.JSeparator();
        jScrollPane1 = new javax.swing.JScrollPane();
        SourceCode = new javax.swing.JTextArea();
        goButton = new javax.swing.JButton();
        jProgressBar1 = new javax.swing.JProgressBar();
        updateTheFlippingProgressBar = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        SourceCode.setColumns(20);
        SourceCode.setFont(new java.awt.Font("Corbel", 0, 13)); // NOI18N
        SourceCode.setRows(5);
        SourceCode.setText("Paste Source code here.");
        jScrollPane1.setViewportView(SourceCode);

        goButton.setText("GO");
        goButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                goButtonActionPerformed(evt);
            }
        });

        jProgressBar1.setStringPainted(true);

        updateTheFlippingProgressBar.setText("UTFPB");
        updateTheFlippingProgressBar.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                updateTheFlippingProgressBarActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jSeparator1)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 380, Short.MAX_VALUE)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(goButton)
                        .addGap(18, 18, 18)
                        .addComponent(jProgressBar1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(updateTheFlippingProgressBar)
                        .addGap(0, 0, Short.MAX_VALUE)))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 205, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(jSeparator1, javax.swing.GroupLayout.PREFERRED_SIZE, 10, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                    .addComponent(goButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(jProgressBar1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(updateTheFlippingProgressBar)
                .addGap(5, 5, 5))
        );

        pack();
    }// </editor-fold>                        

    /**
     * This is the function called when the user presses the "GO" Button.
     * @param evt 
     */
    private void goButtonActionPerformed(java.awt.event.ActionEvent evt) {                                         
        // Update the Progressbar to include a new Maximum count.   
        jProgressBar1.setMaximum(SourceCode.getLineCount());
        VariableListProcessor VPL = new VariableListProcessor(SourceCode);
        VPL.addPropertyChangeListener(this); // Sdet this class (Dialog1) as the propertychange listener.
        //java.awt.EventQueue.invokeLater(VPL);
        VPL.execute();
        System.out.println("GO Pressed: "+String.valueOf(jProgressBar1.getValue()));
    }                                        

    private void updateTheFlippingProgressBarActionPerformed(java.awt.event.ActionEvent evt) {                                                             
        // TODO add your handling code here:
        jProgressBar1.setValue(jProgressBar1.getValue()+1);
        if(jProgressBar1.getValue()>99)
            jProgressBar1.setValue(0);
        this.validate();
        this.repaint();
        System.out.println("UTFPB Pressed: "+String.valueOf(jProgressBar1.getValue()));
    }                                                            

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        /* Set the Nimbus look and feel */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
         * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(Dialog1.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(Dialog1.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(Dialog1.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(Dialog1.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        /* Create and display the form */
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new Dialog1().setVisible(true);
            }
        });
    }
    // Variables declaration - do not modify                     
    private javax.swing.JTextArea SourceCode;
    private javax.swing.JButton goButton;
    private javax.swing.JProgressBar jProgressBar1;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JSeparator jSeparator1;
    private javax.swing.JButton updateTheFlippingProgressBar;
    // End of variables declaration                   

    // called when an action is triggered.
    @Override
    public void actionPerformed(ActionEvent e) {
        throw new UnsupportedOperationException("<<<< actionPerformed(): Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

    // called when a property change being listened for is detected.
    @Override
    public void propertyChange(PropertyChangeEvent evt) {
        //throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
        if ("progress" == evt.getPropertyName()) {
            int progress = (Integer) evt.getNewValue();            
            jProgressBar1.setValue(progress);                                
            System.out.println("P:"+String.valueOf(jProgressBar1.getValue()));
            jProgressBar1.repaint();
        }
    }
}

Этот класс находится в другом файле.

package Model;


import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.swing.*;

/**
 * This is the swingworker class that will take the string object that contains
 * the source code and builds the VariableList object from the Data.
 * @author Alan Curley
 */
public class VariableListProcessor extends SwingWorker<Void,Integer> {
    JTextArea source;
    Integer i = 0;

    public VariableListProcessor(JTextArea source){
        this.source = source;
        i = 0;
    }

    public void setSource(JTextArea source){
        this.source = source;
    }    

    // This is the method that will be called in the background to allow the thread to run.
    // We can update the progress property of the class to report back how it is working.
    // Called when the "Execute" command is given???
    @Override
    protected Void doInBackground() throws InterruptedException{        
        // it is here we set up the Loop to go through Source, line by line and translate the variables into something
        // more meaningful.
        // Clear the progress settings.

        Integer percProgress;    
        i = 0;
        //setProgress(0);

        // build an Arraylist of Strings that represent each line in the source code.
        ArrayList<String> sourceCodeList;
        sourceCodeList = new ArrayList();
        sourceCodeList.addAll(Arrays.asList(source.getText().split("\\n")));

        for (String S:sourceCodeList){
            if(S.matches("TYPE\\W*UDT\\W+\\d+.*"))
                System.out.println(S);
            percProgress = ((++i)*100/source.getLineCount());
            publish(percProgress);
            /*if(!(oldPercProgress.equals(percProgress)))
            {
                try{ ///
                Thread.sleep(100);
                /*
                }catch(InterruptedException ignore){}
                oldPercProgress = percProgress;                
            } */               
//            if(i.equals(269))
//                System.out.println(String.valueOf(i)+"\t"+S);
        }
        return null;
        //throw new UnsupportedOperationException("<<<< VPL-doInBackground(): Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

    @Override
    protected void done(){
        System.out.println("Complete. :-)");
        JOptionPane.showMessageDialog(null, "Complete", "Complete", JOptionPane.INFORMATION_MESSAGE);
        //throw new UnsupportedOperationException("<<<< VPL-done(): Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

    @Override
        // Can safely update the GUI from this method.
        protected void process(List<Integer> chunks) {
        // Here we receive the values that we publish().
        // They may come grouped in chunks.
        int mostRecentValue = chunks.get(chunks.size()-1);         
        setProgress(mostRecentValue);
    }


}

person deadlyBuzz    schedule 16.04.2014    source источник
comment
Я думаю, что, возможно, нашел это... Строка jProgressBar1.setMaximum(SourceCode.getLineCount()); в методе goButtonActionPerformed() изначально использовалась, так как я хотел, чтобы это подсчитывалось до максимума, а не в процентах от подсчета строк. После того, как я установил для progress() значение 100, метод Done вызывал и выдавал ошибку. Я изменил это обратно на процент, но оставил строку выше по ошибке. Когда я удалил это, теперь он работает нормально. Урок усвоен, а?   -  person deadlyBuzz    schedule 18.04.2014


Ответы (1)


Я думаю, что, возможно, нашел это... Строка jProgressBar1.setMaximum(SourceCode.getLineCount()); в методе «goButtonActionPerformed()» изначально использовалась, так как я хотел, чтобы это считалось до максимума, а не в процентах от подсчета строк. После того, как я установил «progress ()» на 100, метод «Готово» вызывал и завершал процедуру. Я изменил это обратно на процент, но оставил строку выше по ошибке. Когда я удалил это, теперь он работает нормально. Урок усвоен, а?

person deadlyBuzz    schedule 18.04.2014