在SwingWorker中实现JScrollPane / JTextArea

DerStrom8

使用SwingWorker时,我的JScrollPane / JTextArea遇到了一些麻烦。这是我目前拥有的:

JTextArea txtDirs;
Task task;

//EDT
public void createGUI(){
    txtDirs = new JTextArea();
    txtDirs.setBounds(10, 56, 414, 125);
    txtDirs.setEditable(false);
    contentPane.add(new JScrollPane(txtDirs));

    task = new Task();
    task.execute();
}

class Task extends SwingWorker<Void, Void>{
    @Override
    public void doInBackground(){
        for(file : files){
            txtDirs.append(file.getAbsolutePath);
        }
    }

    @Override
    public void done(){
        closeWindow();
    }
}

这不是确切的代码,但是它应该为您提供要点。无论如何,问题在于尽管doInBackground()方法中的代码确实运行了,但JScrollPane却根本没有出现。我希望它与txtDirs.append(file.getAbsolutePath())在后台任务中进行更新()有关。但是,我不确定在这种情况下如何使其工作。该框架出现按预期的方式,但它完全是空白。类中应该有一个“过程”方法Task吗?那个txtDirs.append(file.getAbsolutePath())应该放在”的地方吗?恐怕我对SwingWorkers的使用还很陌生,因此任何帮助将不胜感激。

编辑:

经过一番困惑后,我决定只发布完整的代码。我知道问题出在哪里,我可能误解了评论中提到的一些内容,因此我希望发布此内容可以使某人指出我犯的任何明显错误。

完整代码:

import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JButton;
import javax.swing.JProgressBar;
import javax.swing.JLabel;
import javax.swing.SwingWorker;

import org.apache.commons.io.FileUtils;

@SuppressWarnings("serial")
public class BasicCopy extends JFrame {

    private JPanel contentPane;
    private JTextArea txtCopiedDirs;
    private JButton btnCancel;
    private JProgressBar progressBar;
    private JLabel lblCopying;
    private String mainDrive;
    private String backupDrive;
    private String username;
    private String backupDir;
    long totalSize = 0L;        //total size of directories/files
    long currentSize = 0L;      //current size of files counting up to ONE_PERCENT
    long currentPercent = 0L;   //current progress in %
    long ONE_PERCENT;       //totalSize / 100
    Task task;

    public BasicCopy() {
    }

    public BasicCopy(String inDrive, String outDrive, String username, long space){
        mainDrive = inDrive;
        backupDrive = outDrive;
        this.username = username;
        totalSize = space*1048576;
        ONE_PERCENT = totalSize/100;
        createGUI();
    }

    public void createGUI(){
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setTitle("Backup Progress");
        setBounds(100, 100, 450, 300);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        setContentPane(contentPane);
        contentPane.setLayout(null);

        txtCopiedDirs = new JTextArea(10, 50);
        txtCopiedDirs.setEditable(false);
        contentPane.add(new JScrollPane(txtCopiedDirs));

        btnCancel = new JButton("Cancel");
        btnCancel.setBounds(169, 227, 89, 23);
        btnCancel.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                closeWindow();
            }
        });
        contentPane.add(btnCancel);

        progressBar = new JProgressBar(0, 100);
        progressBar.setBounds(10, 192, 414, 24);
        progressBar.setValue(0);
        contentPane.add(progressBar);

        lblCopying = new JLabel("Now backing up your files....");
        lblCopying.setBounds(10, 11, 157, 34);
        contentPane.add(lblCopying);

        setVisible(true);
        task = new Task();
        task.execute();
    }


    /**
     * Swing Worker class
     */
    class Task extends SwingWorker<Void, String>{
        @Override
        public Void doInBackground(){
            setProgress(0);

            //Create Backup Directory
            Date date = new Date();
            SimpleDateFormat sdf = new SimpleDateFormat("MM-dd-yyyy_HMMSS");
            String timestamp = sdf.format(date);
            backupDir = backupDrive + ":\\" + "Backup_" + timestamp;
            File backupDirectory = new File(backupDir);
            backupDirectory.mkdir();

            //Copy Files
            //Main directories
            String pics = mainDrive + ":\\Users\\" + username + "\\Pictures\\";
            String docs = mainDrive + ":\\Users\\" + username + "\\Documents\\";
            String vids = mainDrive + ":\\Users\\" + username + "\\Videos\\";
            String musc = mainDrive + ":\\Users\\" + username + "\\Music\\";
            //Backup directories
            String bkPics = backupDir + "\\Pictures\\";
            String bkDocs = backupDir + "\\Documents\\";
            String bkVids = backupDir + "\\Documents\\";
            String bkMusc = backupDir + "\\Pictures\\";

            String[] directories = {pics, docs, vids, musc};
            String[] bkDirectories = {bkPics, bkDocs, bkVids, bkMusc};

            //Loop through directories and copy files
            for (int i = 0; i < directories.length; i++){
                File dir = new File(directories[i]);
                File dest = new File(bkDirectories[i]);
                for(File file: dir.listFiles()){
                    try{
                        if(file.isFile()){
                            FileUtils.copyFileToDirectory(file, dest);
                            publish(file.getAbsolutePath() + "\n");
                        } else if (file.isDirectory()){
                            FileUtils.copyDirectoryToDirectory(file, dest);
                            publish(file.getAbsolutePath() + "\n");
                        }
                        if(getDirSize(file) >= ONE_PERCENT){
                            currentPercent = getDirSize(file)/ONE_PERCENT;
                            progressBar.setValue((int)currentPercent);
                            currentSize = 0;
                        } else {
                            currentSize = currentSize + getDirSize(file);
                            if(currentSize >= ONE_PERCENT){
                                currentPercent = currentSize/ONE_PERCENT;
                                currentPercent++;
                                progressBar.setValue((int)currentPercent);
                                currentSize = 0;
                            }
                        }
                    } catch (IOException e){
                        e.printStackTrace();
                    }
                }
            }
            return null;
        }

        @Override
        public void process(List<String> chunks){
            for(String path : chunks){
                txtCopiedDirs.append(path);
            }
        }

        @Override
        public void done(){
            closeWindow();
        }
    }

    public static Long getDirSize(File file) {
        long size = 0L;

        if (file.isFile() && file != null){       
            size += file.isDirectory() ? getDirSize(file) : file.length();
        } else if (file.isDirectory()){
            for (File f : file.listFiles()) {
            size += f.isDirectory() ? getDirSize(f) : file.length();
        }
        }
        return size;
    }

    /* Close current window */
    public void closeWindow() {
        WindowEvent close = new WindowEvent(this, WindowEvent.WINDOW_CLOSING);
        Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(close);
        System.exit(0);
    }
}

编辑#2:

我对createGUI()方法进行了一些更改,以避免contentPane具有空布局:

public void createGUI(){
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setTitle("Backup Progress");
    setBounds(100, 100, 450, 300);
    contentPane = new JPanel(new BorderLayout());
    contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
    setContentPane(contentPane);
    contentPane.setLayout(null);

    txtCopiedDirs = new JTextArea(10, 50);
    txtCopiedDirs.setEditable(false);
    scrollPane = new JScrollPane(txtCopiedDirs);
    contentPane.add(scrollPane, BorderLayout.CENTER);

    btnCancel = new JButton("Cancel");
    btnCancel.setBounds(169, 227, 89, 23);
    btnCancel.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            closeWindow();
        }
    });
    contentPane.add(btnCancel);

    progressBar = new JProgressBar(0, 100);
    progressBar.setBounds(10, 192, 414, 24);
    progressBar.setValue(0);
    contentPane.add(progressBar);

    lblCopying = new JLabel("Now backing up your files....");
    lblCopying.setBounds(10, 11, 157, 34);
    contentPane.add(lblCopying);

    setVisible(true);
    task = new Task();
    task.execute();
}
疯狂程序员
  • 不要使用setBounds,而是使用JTextArea(rows, cols)
  • 不要从EDT外部修改任何UI组件,而要使用publish和重写processprocess在EDT的内容内被称为

查看Swing中的并发以了解更多详细信息

您的问题的可能原因包括...

  • 在使用的同时向框架中添加其他组件BorderLayout,而不指定位置约束(除外BorderLayout.CENTER
  • 在添加组件之前调用可见

更新

主要问题是,contentPane正在使用null布局,并且滚动窗格的默认边界是0x00x0宽度和高度的位置

最好的选择是不使用WinodwBuilder,并学习如何使用布局管理器

更新示例

这是一个使用两个布局管理器BorderLayout作为基本布局的示例,GridBagLayout为额外的组件提供了一些额外的支持。

基本经验法则。如果它是一个UI组件,尤其是它在屏幕上(或者您不知道它是否在屏幕上),则只能从EDT上下文进行更新。

这意味着progressBar.setValue从中进行调用doInBackground违反了Swing的单线程规则。SwingWorker通过其PropertyChange支持提供进度更新

import java.awt.BorderLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingWorker;
import javax.swing.border.EmptyBorder;

public class BasicCopy extends JFrame {

    private JPanel contentPane;
    private JTextArea txtCopiedDirs;
    private JButton btnCancel;
    private JProgressBar progressBar;
    private JLabel lblCopying;
    private String mainDrive;
    private String backupDrive;
    private String username;
    private String backupDir;
    long totalSize = 0L;        //total size of directories/files
    long currentSize = 0L;      //current size of files counting up to ONE_PERCENT
    long currentPercent = 0L;   //current progress in %
    long ONE_PERCENT;       //totalSize / 100
    Task task;

    public BasicCopy() {
    }

    public BasicCopy(String inDrive, String outDrive, String username, long space) {
        mainDrive = inDrive;
        backupDrive = outDrive;
        this.username = username;
        totalSize = space * 1048576;
        ONE_PERCENT = totalSize / 100;
        createGUI();
    }

    public void createGUI() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setTitle("Backup Progress");
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        setContentPane(contentPane);
        contentPane.setLayout(new BorderLayout());

        txtCopiedDirs = new JTextArea(10, 50);
        txtCopiedDirs.setEditable(false);
        contentPane.add(new JScrollPane(txtCopiedDirs));

        JPanel controls = new JPanel(new GridBagLayout());
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.insets = new Insets(4, 4, 4, 4);

        lblCopying = new JLabel("Now backing up your files....");
        contentPane.add(lblCopying, gbc);

        gbc.gridy++;

        progressBar = new JProgressBar(0, 100);
        progressBar.setValue(0);
        contentPane.add(progressBar, gbc);

        gbc.gridy++;

        btnCancel = new JButton("Cancel");
        btnCancel.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                closeWindow();
            }
        });
        controls.add(btnCancel, gbc);
        contentPane.add(controls, BorderLayout.SOUTH);

        setLocationRelativeTo(null);
        pack();
        setVisible(true);
        task = new Task();
        task.addPropertyChangeListener(new PropertyChangeListener() {
            @Override
            public void propertyChange(PropertyChangeEvent evt) {
                if ("progress".equalsIgnoreCase(evt.getPropertyName())) {
                    progressBar.setValue((int) evt.getNewValue());
                }
            }
        });
        task.execute();
    }

    /**
     * Swing Worker class
     */
    class Task extends SwingWorker<Void, String> {

        @Override
        public Void doInBackground() throws Exception {
            setProgress(0);

            //Create Backup Directory
            Date date = new Date();
            SimpleDateFormat sdf = new SimpleDateFormat("MM-dd-yyyy_HMMSS");
            String timestamp = sdf.format(date);
            backupDir = backupDrive + ":\\" + "Backup_" + timestamp;
            File backupDirectory = new File(backupDir);
            backupDirectory.mkdir();

            //Copy Files
            //Main directories
            String pics = mainDrive + ":\\Users\\" + username + "\\Pictures\\";
            String docs = mainDrive + ":\\Users\\" + username + "\\Documents\\";
            String vids = mainDrive + ":\\Users\\" + username + "\\Videos\\";
            String musc = mainDrive + ":\\Users\\" + username + "\\Music\\";
            //Backup directories
            String bkPics = backupDir + "\\Pictures\\";
            String bkDocs = backupDir + "\\Documents\\";
            String bkVids = backupDir + "\\Documents\\";
            String bkMusc = backupDir + "\\Pictures\\";

            String[] directories = {pics, docs, vids, musc};
            String[] bkDirectories = {bkPics, bkDocs, bkVids, bkMusc};

            //Loop through directories and copy files
            for (int i = 0; i < directories.length; i++) {
                File dir = new File(directories[i]);
                File dest = new File(bkDirectories[i]);
                for (File file : dir.listFiles()) {
                    try{
                    if (file.isFile()) {
                        FileUtils.copyFileToDirectory(file, dest);
                        publish(file.getAbsolutePath() + "\n");
                    } else if (file.isDirectory()) {
                        FileUtils.copyDirectoryToDirectory(file, dest);
                        Thread.sleep(1000);
                        publish(file.getAbsolutePath() + "\n");
                    }
                    if (getDirSize(file) >= ONE_PERCENT) {
                        currentPercent = getDirSize(file) / ONE_PERCENT;
                        setProgress((int) currentPercent);
                        currentSize = 0;
                    } else {
                        currentSize = currentSize + getDirSize(file);
                        if (currentSize >= ONE_PERCENT) {
                            currentPercent = currentSize / ONE_PERCENT;
                            currentPercent++;
                            setProgress((int) currentPercent);
                            currentSize = 0;
                        }
                    }
                    } catch (IOException e){
                        e.printStackTrace();
                    }
                }
            }
            return null;
        }

        @Override
        public void process(List<String> chunks) {
            for (String path : chunks) {
                txtCopiedDirs.append(path);
            }
        }

        @Override
        public void done() {
            closeWindow();
        }
    }

    public static Long getDirSize(File file) {
        long size = 0L;

        if (file.isFile() && file != null) {
            size += file.isDirectory() ? getDirSize(file) : file.length();
        } else if (file.isDirectory()) {
            for (File f : file.listFiles()) {
                size += f.isDirectory() ? getDirSize(f) : file.length();
            }
        }
        return size;
    }

    /* Close current window */
    public void closeWindow() {
        WindowEvent close = new WindowEvent(this, WindowEvent.WINDOW_CLOSING);
        Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(close);
        System.exit(0);
    }
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

JScrollPane 不在 JTextArea 中滚动

来自分类Dev

JScrollPane多行内的JTextArea

来自分类Dev

JScrollPane中的JTextArea将不会显示

来自分类Dev

JScrollPane将不会显示在JTextArea中

来自分类Dev

JScrollPane中的JTextArea将不会显示

来自分类Dev

JScrollPane,JTextArea和JPanel的问题

来自分类Dev

添加JScrollPane时JTextArea消失

来自分类Dev

JScrollPane未显示在JTextArea上

来自分类Dev

在SwingWorker中打印时JTextArea不会自动滚动

来自分类Dev

JTextArea中的setText()机制?

来自分类Dev

JTextArea中的计算

来自分类Dev

JTable中Jtextarea的用法

来自分类Dev

JTextArea中的新行?

来自分类Dev

在 jTextArea 中迭代 jTable

来自分类Dev

JScrollPane 中的动态 JTextArea 最终位于滚动条下方

来自分类Dev

如何与JTextArea一起使用JScrollPane?

来自分类Dev

JScrollPane无法在我的JTextArea上运行吗?

来自分类Dev

如何在JTextArea上添加JScrollPane?

来自分类Dev

如何在JTextArea上添加JScrollPane?

来自分类Dev

无法将JScrollPane添加到JTextArea

来自分类Dev

如何为我的 JTextArea 添加 JScrollPane?

来自分类Dev

在JTextArea中显示ArrayList <String>

来自分类Dev

JTextArea中整数的增量值

来自分类Dev

清除 JTextArea 中的附加文本

来自分类Dev

如何从不包含JTextArea的方法中追加JTextArea?

来自分类Dev

如何从不包含JTextArea的方法中追加JTextArea?

来自分类Dev

使用Timer实现JTextArea中的打字机效果?

来自分类Dev

使用Timer实现JTextArea中的打字机效果?

来自分类Dev

具有空布局的Frame中具有JScrollPAne的JTextArea