Java在处理数据时加载gif冻结?

时间:2018-08-29 14:26:48

标签: java swing

我调用一个列出目录中所有文件并将其添加到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);
}

另一种方法改变了加载.gif的JLabel的可见性。

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

问题是:在将文件添加到JTable时,gif无法播放,冻结

更新:加载gif冻结仍然存在问题

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();
                }
            }
        });

公共类AddFiles扩展了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);
}

...

2 个答案:

答案 0 :(得分:2)

这就是原因,因为所有文件都已加载到EDT(事件调度线程)中(希望您使用SwingUtilities.invokerLater()方法启动应用程序),这会导致所有摆动组件冻结。有关更多详细信息,请阅读oracle的以下Java文档:Initial Threads.

为了解决您的问题,您必须使用SwingWorker。一个类,负责Swing应用程序中的繁重的后台任务。通过简单的Google搜索,您可以从这里获取一个想法:How do I use SwingWorker in Java?

更新,以回答OP的评论。

事实是,您的代码有点大,最重要的是,它不是SSCCE.

为了给您更多帮助,找到您正在寻找的解决方案,我创建了一个SSCCE,使用SwingWorker做一些“繁重的工作”。在我们的例子中,最麻烦的是在.txt文件中写入1000行,但是每行,线程(我们的工作程序)将休眠10毫秒。

看看,如果需要,可以运行它(我推荐)。代码中包含一些额外的注释,请不要忘记对其进行检查。

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);
        });
    }
}

小预览:

Preview

答案 1 :(得分:1)

我的猜测是您的addFilesWithSubs2-Method正在阻止UI线程。如果您的任务运行时间长,则必须在单独的线程中执行它们,例如SwingWorker