【问题标题】:showOpenDialog() of JFileChooser doesn't open dialog box for opening filesJFileChooser 的 showOpenDialog() 不打开打开文件的对话框
【发布时间】:2020-04-07 02:21:27
【问题描述】:

我正在编写一个用于合并 pdf 文件的 GUI 实用程序,但 JFileChooser 的 showOpenDialog() 方法没有打开用于打开文件的对话框。单击“文件”菜单中的“打开”项时没有响应。为方便起见,Apache pdfbox 库的下载链接为: https://pdfbox.apache.org/download.cgi

我尝试将 openFiles() 方法的胆量移动到 actionPerformed() 方法中的相应位置,但还是不行。但是,在另一个人用于不同目的的代码中,showOpenDialog() 方法在从 actionPerformed 方法中调用的方法中工作。代码如下:

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import javax.swing.*;
import javax.swing.filechooser.FileFilter;
import org.apache.pdfbox.multipdf.PDFMergerUtility;

public class PDFMerger extends JFrame implements ActionListener {
    private static final int DEFAULT_WIDTH = 500;
    private static final int DEFAULT_HEIGHT = 500;
    private JMenuItem openItem;
    private JMenuItem saveItem;
    private JMenuItem exitItem;
    private JTextArea textArea;
    private JTextField textField;
    private JButton bindButton;
    private File[] files;
    private File mergedFile;

    public static void main(String[] args) {
        PDFMerger pdfMerger = new PDFMerger();
        pdfMerger.setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
        pdfMerger.setDefaultCloseOperation(EXIT_ON_CLOSE);
        pdfMerger.setVisible(true);
    }

    public PDFMerger () {
        JMenu menu = new JMenu("File");
        JMenuItem openItem = new JMenuItem("Open");
        openItem.addActionListener(this);
        saveItem = new JMenuItem("Save");
        saveItem.setEnabled(false);
        saveItem.addActionListener(this);
        exitItem = new JMenuItem("Exit");
        exitItem.addActionListener(this);
        menu.add(openItem);
        menu.add(saveItem);
        menu.add(exitItem);
        JMenuBar menuBar = new JMenuBar();
        menuBar.add(menu);
        setJMenuBar(menuBar);
        textArea = new JTextArea(40, 50);
        JScrollPane scrollPane = new JScrollPane(textArea);
        add(scrollPane, BorderLayout.CENTER);
        JPanel operationPanel = new JPanel();
        BoxLayout layout = new BoxLayout(operationPanel, BoxLayout.LINE_AXIS);
        operationPanel.setLayout(layout);
        JLabel label = new JLabel("Result: ");
        textField = new JTextField(30);
        textField.setEditable(false);
        bindButton = new JButton("Bind");
        bindButton.addActionListener(this);
        bindButton.setEnabled(false);
        operationPanel.add(label);
        operationPanel.add(textField);
        operationPanel.add(bindButton);
        add(operationPanel, BorderLayout.NORTH);
    }

    public void actionPerformed (ActionEvent event) {

        if (event.getSource() == exitItem) 
            System.exit(0);
        else if (event.getSource() == openItem) {
            files = openFiles();
            bindButton.setEnabled(false);
        }
        else if (event.getSource() == bindButton) {
            mergedFile = mergeFiles();
            saveItem.setEnabled(true);
        }
        else if (event.getSource() == saveItem)
            saveFile();
    }

    public File[] openFiles () {
        File[] selectedFiles = null;
        JFileChooser chooser = new JFileChooser();
        chooser.setCurrentDirectory(new File("."));
        chooser.setMultiSelectionEnabled(true);
        int option = chooser.showOpenDialog(PDFMerger.this);

        if (option == JFileChooser.APPROVE_OPTION) 
            selectedFiles = chooser.getSelectedFiles();
        return selectedFiles;
    }

    public File mergeFiles () {
        File merged = null;
        // TODO

        return merged;
    }
    public void saveFile () {
        //TODO
    }
}

感谢您的帮助。

【问题讨论】:

    标签: java swing jfilechooser


    【解决方案1】:

    我修复了您的代码并打开了 JFileChooser。

    我所做的主要更改是:

    1. 我通过调用 SwingUtilities invokeLater 方法启动了 Swing GUI。此方法可确保在 Event Dispatch Thread 上创建和执行 Swing 组件。

    2. 我使用了 JFrame。我没有扩展 JFrame。仅当您打算覆盖一个或多个类方法时才扩展 Swing 组件。

    3. 您的代码让人难以阅读。我将代码划分为逻辑方法。我留下了令人困惑的代码,但是当您创建 Swing 布局时,您确实应该按行、列顺序创建组件。您还应该将特定组件的所有方法调用组合在一起。它使发现和解决问题变得更加容易。

    4. 你不应该只有一个动作监听器来处理所有事情。您应该为每个按钮或菜单项设置单独的操作侦听器。

    无论如何,这是您的代码。一旦我在逻辑上分离了事物,就更容易找到阻止 JFileChooser 显示的错误。

    import java.awt.*;
    import java.awt.event.*;
    import java.io.*;
    import javax.swing.*;
    
    public class PDFMerger implements ActionListener {
    
        private JFrame frame;
        private JMenuItem openItem;
        private JMenuItem saveItem;
        private JMenuItem exitItem;
        private JTextArea textArea;
        private JTextField textField;
        private JButton bindButton;
        private File[] files;
        private File mergedFile;
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    new PDFMerger();
                }
            });
        }
    
        public PDFMerger() {
            frame = new JFrame("PDF Merger");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            JMenuBar menuBar = createJMenuBar();
            frame.setJMenuBar(menuBar);
    
            JPanel operationPanel = createOperationPanel();
            frame.add(operationPanel, BorderLayout.NORTH);
            JPanel textPanel = createTextPanel();
            frame.add(textPanel, BorderLayout.CENTER);
    
            frame.pack();
            frame.setLocationByPlatform(true);
            frame.setVisible(true);
        }
    
        private JPanel createOperationPanel() {
            JPanel operationPanel = new JPanel();
            BoxLayout layout = new BoxLayout(operationPanel, BoxLayout.LINE_AXIS);
            operationPanel.setLayout(layout);
            JLabel label = new JLabel("Result: ");
            textField = new JTextField(30);
            textField.setEditable(false);
            bindButton = new JButton("Bind");
            bindButton.addActionListener(this);
            bindButton.setEnabled(false);
            operationPanel.add(label);
            operationPanel.add(textField);
            operationPanel.add(bindButton);
            return operationPanel;
        }
    
        private JPanel createTextPanel() {
            JPanel panel = new JPanel();
            panel.setLayout(new BorderLayout());
    
            textArea = new JTextArea(40, 50);
            JScrollPane scrollPane = new JScrollPane(textArea);
            panel.add(scrollPane, BorderLayout.CENTER);
            return panel;
        }
    
        private JMenuBar createJMenuBar() {
            JMenu menu = new JMenu("File");
            openItem = new JMenuItem("Open");
            openItem.addActionListener(this);
            saveItem = new JMenuItem("Save");
            saveItem.setEnabled(false);
            saveItem.addActionListener(this);
            exitItem = new JMenuItem("Exit");
            exitItem.addActionListener(this);
            menu.add(openItem);
            menu.add(saveItem);
            menu.add(exitItem);
            JMenuBar menuBar = new JMenuBar();
            menuBar.add(menu);
            return menuBar;
        }
    
        @Override
        public void actionPerformed (ActionEvent event) {
            if (event.getSource() == exitItem) {
                frame.dispose();
                System.exit(0);
            } else if (event.getSource() == openItem) {
                files = openFiles();
                bindButton.setEnabled(false);
            } else if (event.getSource() == bindButton) {
                mergedFile = mergeFiles();
                saveItem.setEnabled(true);
            } else if (event.getSource() == saveItem)
                saveFile();
        }
    
        public File[] openFiles () {
            File[] selectedFiles = null;
            JFileChooser chooser = new JFileChooser();
            chooser.setCurrentDirectory(new File("."));
            chooser.setMultiSelectionEnabled(true);
            int option = chooser.showOpenDialog(frame);
    
            if (option == JFileChooser.APPROVE_OPTION) 
                selectedFiles = chooser.getSelectedFiles();
            return selectedFiles;
        }
    
        public File mergeFiles () {
            File merged = null;
            // TODO
    
            return merged;
        }
        public void saveFile () {
            //TODO
        }
    }
    

    【讨论】:

    • 谢谢你,吉尔伯特勒布朗。你说得对。我应该使用 Event Dispatch Thread 和单独的 ActionListener。与我的意大利面条代码相比,您的代码非常清晰紧凑。我想知道如何调试我自己的代码。你能推荐一些工具和技术吗?谢谢!
    • @MichaelMay:我的代码编辑器是 Eclipse。我认真对待所有编译器警告并努力消除它们。对于您的代码,一旦每个方法只有 20 行左右的代码,我就可以观察代码并将我看到的内容与我知道的正确代码进行比较。不幸的是,这种能力伴随着编码经验,尤其是创造和发现自己错误的经验。
    • @MichaelMay:在阅读代码时,谨慎地使用空行来分隔方法的各个部分会有所帮助。有时,您必须将 System.out.println 语句放在不同的地方,以确保您的代码正常运行。我使用调试器作为最后的手段,因为它可能需要一段时间来隔离问题,尤其是在像 Swing GUI 这样的事件驱动代码中。努力减少类字段。并非每个字段都必须是类字段。使您的所有字段都特定于一个方法,并且当且仅当您的类中的其他地方需要它时,才使一个字段成为类字段。
    • 感谢您的提示。我认为我需要编写更多代码来获得经验并从错误中学到更多。
    猜你喜欢
    • 2013-05-12
    • 2010-12-11
    • 1970-01-01
    • 1970-01-01
    • 2022-01-23
    • 2011-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多