将文件从操作系统拖放到Java应用程序(Swing)

首先我要说的是,我一直在阅读拖拽教程和类似的问题,但不幸的是,我对这件事情感到更加困惑。 我想要实现的是相对简单的,所以我很惊讶它已经让我陷入了这么多麻烦。 我正在编写一个小实用程序应用程序,它将一堆结果文件(自定义xml类型)合并到一个大的制表符分隔文本文件中。 大多数function已经编码,但我想为它制作一个不错的GUI。

我想要的是能够以漂亮和亲切的方式将文件拖放到组件(例如JTextArea )中(读取:不是完整路径,而是一个小图标和名称)。 我希望能够提供一个JFileChooser来浏览文件。 然后我将按顺序解析文件以生成我想要的矩阵。

到目前为止我所学到的是框架已经存在,但是需要定制任何其他function。 我在Netbeans中创建了一个测试GUI,并尝试将一堆文件拖到JTextArea ,但它们显示为文件路径,并且不可否认它看起来非常难看。

我非常感谢有关如何以一种简洁的方式解决(或澄清)这个问题的任何提示和指导。 请注意,我打算在多个不同的操作系统(Mac,Win和Linux)上使用该软件。

编辑:我到目前为止的代码基于Sun教程中的一个示例,如下所示

 import java.awt.datatransfer.*; import java.awt.event.*; import java.awt.*; import java.io.*; import javax.swing.*; import javax.swing.UIManager.LookAndFeelInfo; import javax.swing.border.TitledBorder; import javax.swing.filechooser.FileNameExtensionFilter; import javax.swing.text.*; public class ConsolidatorDemo extends JPanel implements ActionListener { private static final long serialVersionUID = -4487732343062917781L; JFileChooser fc; JButton clear; JTextArea dropZone, console; JSplitPane childSplitPane, parentSplitPane; PrintStream ps; public ConsolidatorDemo() { super(new BorderLayout()); fc = new JFileChooser();; fc.setMultiSelectionEnabled(true); fc.setDragEnabled(true); fc.setControlButtonsAreShown(false); fc.setFileSelectionMode(JFileChooser.FILES_ONLY); JPanel fcPanel = new JPanel(new BorderLayout()); fcPanel.add(fc, BorderLayout.CENTER); clear = new JButton("Clear All"); clear.addActionListener(this); JPanel buttonPanel = new JPanel(new BorderLayout()); buttonPanel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); buttonPanel.add(clear, BorderLayout.LINE_END); JPanel leftUpperPanel = new JPanel(new BorderLayout()); leftUpperPanel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); leftUpperPanel.add(fcPanel, BorderLayout.CENTER); leftUpperPanel.add(buttonPanel, BorderLayout.PAGE_END); JScrollPane leftLowerPanel = new javax.swing.JScrollPane(); leftLowerPanel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); dropZone = new JTextArea(); dropZone.setColumns(20); dropZone.setLineWrap(true); dropZone.setRows(5); dropZone.setDragEnabled(true); dropZone.setDropMode(javax.swing.DropMode.INSERT); dropZone.setBorder(new TitledBorder("Selected files/folders")); leftLowerPanel.setViewportView(dropZone); childSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, leftUpperPanel, leftLowerPanel); childSplitPane.setDividerLocation(400); childSplitPane.setPreferredSize(new Dimension(480, 650)); console = new JTextArea(); console.setColumns(40); console.setLineWrap(true); console.setBorder(new TitledBorder("Console")); parentSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, childSplitPane, console); parentSplitPane.setDividerLocation(480); parentSplitPane.setPreferredSize(new Dimension(800, 650)); add(parentSplitPane, BorderLayout.CENTER); } public void setDefaultButton() { getRootPane().setDefaultButton(clear); } public void actionPerformed(ActionEvent e) { if (e.getSource() == clear) { dropZone.setText(""); } } /** * Create the GUI and show it. For thread safety, * this method should be invoked from the * event-dispatching thread. */ private static void createAndShowGUI() { //Make sure we have nice window decorations. JFrame.setDefaultLookAndFeelDecorated(true); try { //UIManager.setLookAndFeel("de.javasoft.plaf.synthetica.SyntheticaBlackStarLookAndFeel"); for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) { if ("Nimbus".equals(info.getName())) { UIManager.setLookAndFeel(info.getClassName()); break; } } }catch (Exception e){ e.printStackTrace(); } //Create and set up the window. JFrame frame = new JFrame("Consolidator!"); frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); //Create and set up the menu bar and content pane. ConsolidatorDemo demo = new ConsolidatorDemo(); demo.setOpaque(true); //content panes must be opaque frame.setContentPane(demo); //Display the window. frame.pack(); frame.setVisible(true); demo.setDefaultButton(); } 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(); } }); } 

这是一个快速片段,用于将实际文件导入JList(而不是将其String表示forms导入文本组件),并使用自定义渲染器很好地呈现它。 它改编自BasicDnD(在教程中):

  fileDropper = new JList(new DefaultListModel()); fileDropper.setDragEnabled(true); leftLowerPanel.setViewportView(fileDropper); TransferHandler handler = new TransferHandler() { @Override public boolean canImport(TransferHandler.TransferSupport info) { // we only import FileList if (!info.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) { return false; } return true; } @Override public boolean importData(TransferHandler.TransferSupport info) { if (!info.isDrop()) { return false; } // Check for FileList flavor if (!info.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) { displayDropLocation("List doesn't accept a drop of this type."); return false; } // Get the fileList that is being dropped. Transferable t = info.getTransferable(); List data; try { data = (List)t.getTransferData(DataFlavor.javaFileListFlavor); } catch (Exception e) { return false; } DefaultListModel model = (DefaultListModel) fileDropper.getModel(); for (File file : data) { model.addElement(file); } return true; } private void displayDropLocation(String string) { System.out.println(string); } }; fileDropper.setTransferHandler(handler); fileDropper.setCellRenderer(new DefaultListRenderer( StringValues.FILE_NAME, IconValues.FILE_ICON)); 

无法抗拒显示SwingX渲染器配置:-)在核心java中,你会手动完成,类似于

  class MyRenderer extends DefaultListCellRenderer { @Override public Component getListCellRendererComponent(...) { super.getList... if (value instanceof File) { setText(FileSystemView.getFileSystemView().getDisplayName(value); setIcon(FileSystemView.getFileSystemView().getSystemIcon(value); } return this; } } 

这实际上是kleopatra的答案1 (带有一些微不足道的变化,不一定是更好的),用截图!

ConsolidatorDemo

 import java.awt.datatransfer.*; import java.awt.event.*; import java.awt.BorderLayout; import java.awt.Component; import java.awt.Dimension; import java.io.*; import javax.swing.*; import javax.swing.UIManager.LookAndFeelInfo; import javax.swing.border.TitledBorder; import javax.swing.filechooser.FileNameExtensionFilter; import javax.swing.filechooser.FileSystemView; import javax.swing.text.*; import java.util.List; public class ConsolidatorDemo extends JPanel implements ActionListener { private static final long serialVersionUID = -4487732343062917781L; JFileChooser fc; JButton clear; JTextArea console; JList dropZone; DefaultListModel listModel; JSplitPane childSplitPane, parentSplitPane; PrintStream ps; public ConsolidatorDemo() { super(new BorderLayout()); fc = new JFileChooser();; fc.setMultiSelectionEnabled(true); fc.setDragEnabled(true); fc.setControlButtonsAreShown(false); fc.setFileSelectionMode(JFileChooser.FILES_ONLY); JPanel fcPanel = new JPanel(new BorderLayout()); fcPanel.add(fc, BorderLayout.CENTER); clear = new JButton("Clear All"); clear.addActionListener(this); JPanel buttonPanel = new JPanel(new BorderLayout()); buttonPanel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); buttonPanel.add(clear, BorderLayout.LINE_END); JPanel leftUpperPanel = new JPanel(new BorderLayout()); leftUpperPanel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); leftUpperPanel.add(fcPanel, BorderLayout.CENTER); leftUpperPanel.add(buttonPanel, BorderLayout.PAGE_END); JScrollPane leftLowerPanel = new javax.swing.JScrollPane(); leftLowerPanel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); listModel = new DefaultListModel(); dropZone = new JList(listModel); dropZone.setCellRenderer(new FileCellRenderer()); dropZone.setTransferHandler(new ListTransferHandler(dropZone)); dropZone.setDragEnabled(true); dropZone.setDropMode(javax.swing.DropMode.INSERT); dropZone.setBorder(new TitledBorder("Selected files/folders")); leftLowerPanel.setViewportView(new JScrollPane(dropZone)); childSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, leftUpperPanel, leftLowerPanel); childSplitPane.setDividerLocation(400); childSplitPane.setPreferredSize(new Dimension(480, 650)); console = new JTextArea(); console.setColumns(40); console.setLineWrap(true); console.setBorder(new TitledBorder("Console")); parentSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, childSplitPane, console); parentSplitPane.setDividerLocation(480); parentSplitPane.setPreferredSize(new Dimension(800, 650)); add(parentSplitPane, BorderLayout.CENTER); } public void setDefaultButton() { getRootPane().setDefaultButton(clear); } public void actionPerformed(ActionEvent e) { if (e.getSource() == clear) { listModel.clear(); } } /** * Create the GUI and show it. For thread safety, * this method should be invoked from the * event-dispatching thread. */ private static void createAndShowGUI() { //Make sure we have nice window decorations. JFrame.setDefaultLookAndFeelDecorated(true); try { //UIManager.setLookAndFeel("de.javasoft.plaf.synthetica.SyntheticaBlackStarLookAndFeel"); for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) { if ("Nimbus".equals(info.getName())) { UIManager.setLookAndFeel(info.getClassName()); break; } } }catch (Exception e){ e.printStackTrace(); } //Create and set up the window. JFrame frame = new JFrame("Consolidator!"); frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); //Create and set up the menu bar and content pane. ConsolidatorDemo demo = new ConsolidatorDemo(); demo.setOpaque(true); //content panes must be opaque frame.setContentPane(demo); //Display the window. frame.pack(); frame.setVisible(true); demo.setDefaultButton(); } 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(); } }); } } class FileCellRenderer extends DefaultListCellRenderer { public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { Component c = super.getListCellRendererComponent( list,value,index,isSelected,cellHasFocus); if (c instanceof JLabel && value instanceof File) { JLabel l = (JLabel)c; File f = (File)value; l.setIcon(FileSystemView.getFileSystemView().getSystemIcon(f)); l.setText(f.getName()); l.setToolTipText(f.getAbsolutePath()); } return c; } } class ListTransferHandler extends TransferHandler { private JList list; ListTransferHandler(JList list) { this.list = list; } @Override public boolean canImport(TransferHandler.TransferSupport info) { // we only import FileList if (!info.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) { return false; } return true; } @Override public boolean importData(TransferHandler.TransferSupport info) { if (!info.isDrop()) { return false; } // Check for FileList flavor if (!info.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) { displayDropLocation("List doesn't accept a drop of this type."); return false; } // Get the fileList that is being dropped. Transferable t = info.getTransferable(); List data; try { data = (List)t.getTransferData(DataFlavor.javaFileListFlavor); } catch (Exception e) { return false; } DefaultListModel model = (DefaultListModel) list.getModel(); for (Object file : data) { model.addElement((File)file); } return true; } private void displayDropLocation(String string) { System.out.println(string); } } 
  1. 当我注意到她已经发布了答案时,我正忙着写答案。 由于我的TransferHandler非常破碎,我使用了她的。 虽然我使用了我的列表单元格渲染器版本,但它似乎并没有捕捉到她所暗示的微妙之处。 我在提到List时也遇到了编译错误(鉴于编译器假设我的意思是AWT列表。我只是意识到在我将几个List类型语句改为非generics之后发生了什么 – 我认为他们中的大多数现在已经改变了。

这是没有控制台和额外按钮的代码

 import java.awt.BorderLayout; import java.awt.Component; import java.awt.Dimension; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.File; import java.io.PrintStream; import java.util.List; import javax.swing.BorderFactory; import javax.swing.DefaultListCellRenderer; import javax.swing.DefaultListModel; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JSplitPane; import javax.swing.JTextArea; import javax.swing.TransferHandler; import javax.swing.UIManager; import javax.swing.UIManager.LookAndFeelInfo; import javax.swing.border.TitledBorder; import javax.swing.filechooser.FileSystemView; public class ConsolidatorDemo extends JPanel implements ActionListener { private static final long serialVersionUID = -4487732343062917781L; // JFileChooser fc; JButton clear,compare; JTextArea fc; JList dropZone; DefaultListModel listModel; JSplitPane childSplitPane, parentSplitPane; PrintStream ps; public ConsolidatorDemo() { super(new BorderLayout()); /* fc = new JFileChooser();; fc.setMultiSelectionEnabled(true); fc.setDragEnabled(true); fc.setControlButtonsAreShown(false); fc.setFileSelectionMode(JFileChooser.FILES_ONLY);*/ fc= new JTextArea(); fc.setText("Rules:\n1. drop old html first.\n2. drop new html.\n3. drop output folder.\n4. click compare button.\n5. Check output in the output.txt file.\nEnd"); fc.setEditable(false); JPanel fcPanel = new JPanel(new BorderLayout()); fcPanel.add(fc, BorderLayout.CENTER); compare = new JButton("Compare"); compare.addActionListener(this); JPanel buttonPanel1 = new JPanel(new BorderLayout()); buttonPanel1.setBorder(BorderFactory.createEmptyBorder(1,1,1,1)); buttonPanel1.add(compare, BorderLayout.LINE_END); clear = new JButton("Clear All"); clear.addActionListener(this); JPanel buttonPanel = new JPanel(new BorderLayout()); buttonPanel.setBorder(BorderFactory.createEmptyBorder(1,1,1,1)); buttonPanel.add(clear, BorderLayout.LINE_END); JPanel leftUpperPanel = new JPanel(new BorderLayout()); leftUpperPanel.setBorder(BorderFactory.createEmptyBorder(3,3,3,3)); leftUpperPanel.add(fcPanel, BorderLayout.CENTER); leftUpperPanel.add(buttonPanel1, BorderLayout.LINE_END); leftUpperPanel.add(buttonPanel, BorderLayout.PAGE_END); JScrollPane leftLowerPanel = new javax.swing.JScrollPane(); leftLowerPanel.setBorder(BorderFactory.createEmptyBorder(3,3,3,3)); listModel = new DefaultListModel(); dropZone = new JList(listModel); dropZone.setCellRenderer(new FileCellRenderer()); dropZone.setTransferHandler(new ListTransferHandler(dropZone)); dropZone.setDragEnabled(true); dropZone.setDropMode(javax.swing.DropMode.INSERT); dropZone.setBorder(new TitledBorder("Drag and drop files here")); leftLowerPanel.setViewportView(new JScrollPane(dropZone)); childSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, leftLowerPanel,leftUpperPanel); childSplitPane.setDividerLocation(200);//400 childSplitPane.setPreferredSize(new Dimension(300, 400));//480, 650 /*console = new JTextArea(); console.setColumns(40); console.setLineWrap(true); console.setBorder(new TitledBorder("Console")); parentSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, childSplitPane, console); parentSplitPane.setDividerLocation(480); parentSplitPane.setPreferredSize(new Dimension(800, 650));*/ add(childSplitPane, BorderLayout.CENTER); } public void setDefaultButton() { getRootPane().setDefaultButton(clear); } public void actionPerformed(ActionEvent e) { if (e.getSource() == clear) { listModel.clear(); }else if (e.getSource() == compare) { //our function } } /** * Create the GUI and show it. For thread safety, * this method should be invoked from the * event-dispatching thread. */ private static void createAndShowGUI() { //Make sure we have nice window decorations. JFrame.setDefaultLookAndFeelDecorated(true); try { //UIManager.setLookAndFeel("de.javasoft.plaf.synthetica.SyntheticaBlackStarLookAndFeel"); for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) { if ("Nimbus".equals(info.getName())) { UIManager.setLookAndFeel(info.getClassName()); break; } } }catch (Exception e){ e.printStackTrace(); } //Create and set up the window. JFrame frame = new JFrame("Bill of materials Comparer"); frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); //Create and set up the menu bar and content pane. ConsolidatorDemo demo = new ConsolidatorDemo(); demo.setOpaque(true); //content panes must be opaque frame.setContentPane(demo); //Display the window. frame.pack(); frame.setVisible(true); demo.setDefaultButton(); } 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(); } }); } } class FileCellRenderer extends DefaultListCellRenderer { public Component getListCellRendererComponent(JList list,Object value,int index,boolean isSelected,boolean cellHasFocus) { Component c = super.getListCellRendererComponent(list,value,index,isSelected,cellHasFocus); if (c instanceof JLabel && value instanceof File) { JLabel l = (JLabel)c; File f = (File)value; l.setIcon(FileSystemView.getFileSystemView().getSystemIcon(f)); l.setText(f.getName()); //l.setText(f.getAbsolutePath()); l.setToolTipText(f.getAbsolutePath()); } return c; } } class ListTransferHandler extends TransferHandler { private JList list; ListTransferHandler(JList list) { this.list = list; } @Override public boolean canImport(TransferHandler.TransferSupport info) { // we only import FileList if (!info.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) { return false; } return true; } @Override public boolean importData(TransferHandler.TransferSupport info) { if (!info.isDrop()) { return false; } // Check for FileList flavor if (!info.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) { displayDropLocation("List doesn't accept a drop of this type."); return false; } // Get the fileList that is being dropped. Transferable t = info.getTransferable(); List data; try { data = (List)t.getTransferData(DataFlavor.javaFileListFlavor); } catch (Exception e) { return false; } DefaultListModel model = (DefaultListModel) list.getModel(); for (Object file : data) { model.addElement((File)file); } return true; } private void displayDropLocation(String string) { System.out.println(string); } }