Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
461 views
in Technique[技术] by (71.8m points)

swing - Java loading gif freeze while processing data?

I call a method which lists all the files in a directory, and adds them to a JTable:

    addFilesWithSubsButton.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            reverseLoadingVisibility(loaderLabel); //set Visible
            addFilesWithSubs2(chooser, loaderLabel);
        }
    });

public void addFilesWithSubs2(JFileChooser chooser, JLabel loaderLabel) {
    //loading all files ....

    //when every file is listed:
    //Set invisible
    reverseLoadingVisibility(loaderLabel);
}

The another method change reverse the visibility of the JLabel in which the loading .gif is.

public void reverseLoadingVisibility(JLabel loaderLabel) {
    loaderLabel.setVisible(!loaderLabel.isVisible());
}

The problem is: the gif doesn't play, freezes while the files are added to the JTable.

UPDATE: Still have problem the loading gif freezes

addFilesButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                reverseLoadingVisibility(loaderLabel);
                try {
                    new AddFiles().doInBackground(
                            chooser, CHOOSERTITLE, 
                            lastDictionary,
                            sdf,
                            filesTable,
                            model,
                            columnNames,
                            loaderLabel);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });

public class AddFiles extends SwingWorker{

@Override
protected Void doInBackground() throws Exception {
    return null;
}

protected void doInBackground(JFileChooser chooser, String CHOOSERTITLE, 
        String lastDictionary,
        SimpleDateFormat sdf,
        JTable filesTable,
        DefaultTableModel model,
        String[] columnNames,
        JLabel loaderLabel) throws Exception {
    //Set visible
    reverseLoadingVisibility(loaderLabel);


    chooser.setDialogTitle(CHOOSERTITLE);
    chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
    //
    chooser.setAcceptAllFileFilterUsed(true);
    //TODO: this changed to chooser    
    if (chooser.showOpenDialog(chooser) == JFileChooser.APPROVE_OPTION) { 

      // create a file that is really a directory
      File aDirectory = new File(chooser.getSelectedFile().toString());
      lastDictionary = chooser.getSelectedFile().toString();

      // get a listing of all files in the directory
      String[] filesInDir = aDirectory.list();
      // TODO
      System.out.println("Number of files: " + filesInDir.length);

      // have everything i need, just print it now


      for ( int i=0; i<filesInDir.length; i++ )
          {
            File currentFile = new File(aDirectory + "" + filesInDir[i]);

            System.out.println(filesInDir[i] );
            System.out.println(aDirectory );
            System.out.println(currentFile.length()/1024 + " KB");



            System.out.println(sdf.format((currentFile).lastModified()));

            // Avoid duplicates
            int row = 0;
            boolean duplicate = false;
            for (; row < filesTable.getRowCount(); row++) {
                if (model.getValueAt(row, 1).equals(filesInDir[i]) &&
                    model.getValueAt(row, 3).equals(aDirectory)
                ) {
                    duplicate = true;
                    break;
                }
                System.out.println("model.getValueAt(row, 1) " + model.getValueAt(row, 1));
                System.out.println(filesInDir[i]);
                System.out.println("model.getValueAt(row, 3) " + model.getValueAt(row, 3));
                System.out.println(aDirectory);
            }

            if (!duplicate && currentFile.isFile()) {
                model.addRow(new Object[]{
                        filesTable.getRowCount()+1, 
                        filesInDir[i],
                        null,
                        aDirectory,
                        currentFile.length()/1024 + " KB",
                        sdf.format((currentFile).lastModified())
                });


            }


          }
      }
    else {
      System.out.println("No Selection ");
    }

    // Readjust columns
    adjustTableColumns(filesTable, columnNames);

    //Set unvisible
    reverseLoadingVisibility(loaderLabel);
}

...

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

That's why because all files are loaded in the EDT (Event Dispatch Thread) (hopefully you launch your application using SwingUtilities.invokerLater() method) which cause all swing components to freeze. For more details read this java document by oracle: Initial Threads.

In order to solve your problem, you have to use a SwingWorker. A class responsible for heavy background tasks in Swing applications. With a simple google search, you can take an idea from here: How do I use SwingWorker in Java?

UPDATE in order to answer OP's comment.

The truth is that your code is a little bit big, and the most important, it is not an SSCCE.

In order to give you one more hand to find the solution you are looking for, i have created an SSCCE, using a SwingWorker that does something "heavy". In our case, the something heavy, is to write 1000 lines in a .txt file, but each line, thread (our worker) will sleep for 10ms.

Take it a look, run it if you want (i recommend it). Some extra comments inside the code, do not forget to check them.

package test;

import java.awt.BorderLayout;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.util.List;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;

public class SwingWorkerExample extends JFrame {
    /*
     * Worker has Void doInBackground a.k.a, doInBackground method needs to return nothing.
     * Worker needs to process-publish Integers.
     */
    private SwingWorker<Void, Integer> writeToFileWorker = null;
    private JLabel gifLabel;
    private JButton doSomethingHeavy;

    public SwingWorkerExample() {
        super("Just a test.");
        createWorker();
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        getContentPane().setLayout(new BorderLayout());
        gifLabel = new JLabel();
        ImageIcon gif = new ImageIcon("C:/Users/George/Desktop/giphy.gif");
        gifLabel.setIcon(gif);
        gifLabel.setVisible(false); //Initialy non visible
        gifLabel.setHorizontalTextPosition(JLabel.CENTER);
        gifLabel.setVerticalTextPosition(JLabel.BOTTOM);
        gifLabel.setHorizontalAlignment(JLabel.CENTER);
        getContentPane().add(gifLabel, BorderLayout.CENTER);

        doSomethingHeavy = new JButton("Do something heavy in another thread and start dancing...");
        doSomethingHeavy.addActionListener(e -> {
            //Before start the worker, show gif and disable the button
            doSomethingHeavy.setEnabled(false);
            gifLabel.setVisible(true);
            writeToFileWorker.execute();
        });
        getContentPane().add(doSomethingHeavy, BorderLayout.PAGE_END);
        setSize(500, 300);
        setLocationRelativeTo(null);
    }

    private void createWorker() {
        writeToFileWorker = new SwingWorker<Void, Integer>() {
            @Override
            protected Void doInBackground() throws Exception {
                File fileToWrite = new File(System.getProperty("user.home") + File.separator + "Desktop" + File.separator + "hello_worlds.txt");
                try (BufferedWriter writer = new BufferedWriter(new FileWriter(fileToWrite));) {
                    for (int line = 0; line < 1000; line++) {
                        writer.append("Hello World! My name is Swing Worker.");
                        writer.append(System.lineSeparator());
                        Thread.sleep(10);
                        publish(line);
                    }
                }
                return null;
            }

            /*
             * Runs in Event Dispatch Thread (EDT)
             */
            @Override
            protected void process(List<Integer> chunks) {
                int line = chunks.get(0);//First parameter is the line
                gifLabel.setText("Written " + line + " lines in the txt.");
                super.process(chunks);
            }

            /*
             * Runs in Event Dispatch Thread (EDT)
             */
            @Override
            protected void done() {
                //When swing worker is finished, a.k.a the heavy work, stop the gif and enable the button
                gifLabel.setVisible(false);
                doSomethingHeavy.setEnabled(true);
                super.done();
            }
        };

    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            SwingWorkerExample swe = new SwingWorkerExample();
            swe.setVisible(true);
        });
    }
}

Small preview:

Preview


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...