Top-Level Drop

到目前为止,我们主要致力于将TransferHandler附加到JComponent子类之一。但是,您也可以直接在顶级容器(例如JFrameJDialog)上设置TransferHandler

这对于导入文件的应用程序特别有用,例如编辑器,IDE,图像处理程序,CD 刻录程序。这样的应用程序通常包括菜单,工具栏,用于编辑文档的区域以及可能在打开的文档之间进行切换的列表或机制。

我们有一个示例,但是由于此演示读取文件,因此我们不提供 Java Web Start 版本-您必须自己下载并编译该演示。

从下面的屏幕快照中可以看到,TopLevelTransferHandlerDemo有一个菜单(Demo 子菜单除外,为空),一个(非功能性)工具栏,一个显示打开文档列表的区域(左侧)和一个区域(在右侧)显示每个打开的文档的内容。在启动时,蓝色文档区域已分配了一个支持文件导入的传输处理程序-因此是唯一可以接受放置的位置。

TopLevelTransferHandlerDemo 演示的快照。

Try this:

  • 编译并运行TopLevelTransferHandlerDemo示例,如果要下载为 NetBeans 构建的 zip 文件,请查阅example index

  • 从本地桌面或文件系统中拖动文件,然后将其放在右侧的蓝色文档区域中。该文件将打开,并显示一个填充了其内容的框架。文档区域JDesktopPane包含一个支持导入javaFileListFlavor的传输处理程序。

  • 拖动另一个文件,然后try将其放在文档区域上。您会发现您无法将其放在显示最后一个文件的框架的顶部。您也不能将其放在列表,菜单或工具栏上。唯一可以放置的地方是文档区域的蓝色部分或先前打开的框架的菜单栏上的蓝色部分。在每个内容框架内都有一个文本组件的传输处理程序,该处理程序不了解文件的放置-您可以将文本放置到该区域中,而不是文件中。

  • 从菜单中,选择“演示”->“使用顶级 TransferHandler”将传输处理程序安装在顶级容器JFrame上。

  • try再次拖动演示。接受墨滴的区域数量增加了。现在,您可以将应用程序中的大部分内容拖放到任何地方,包括菜单栏,工具栏,框架的标题栏,但列表(位于左侧)或先前打开的文件的内容区域除外。 JList和文本区域的传输处理程序都不知道如何导入文件。

  • 通过从菜单中选择“演示”->“从列表中删除 TransferHandler”和“从文本中删除”,在其余组件上禁用传输处理程序。

  • 再次拖动演示。现在,您可以在应用程序的任何位置拖放文件!

  • 从菜单中,选择“演示”->“使用复制动作”。

  • 再次拖动演示。请注意,鼠标光标现在显示 COPY 光标-这将提供更准确的反馈,因为成功的拖放操作不会从源中删除文件。如选择放下动作所述,可以对目标进行编程以从可用的放置动作中进行选择。

请注意禁用文本组件上的默认传输处理程序的一个不良副作用:您不再可以在编辑区域内拖放(或剪切/复制/粘贴)文本。要解决此问题,您将需要为文本组件实现一个自定义的传输处理程序,该处理程序可以接受文件删除并重新实现对文本传输所缺少的支持。您可能希望观看RFE 4830695,这将允许在现有TransferHandler的顶部添加数据导入。

这是TopLevelTransferHandlerDemo.java的源代码:

/**
 * Demonstration of the top-level {@code TransferHandler}
 * support on {@code JFrame}.
 */
public class TopLevelTransferHandlerDemo extends JFrame {
    
    private static boolean DEMO = false;

    private JDesktopPane dp = new JDesktopPane();
    private DefaultListModel listModel = new DefaultListModel();
    private JList list = new JList(listModel);
    private static int left;
    private static int top;
    private JCheckBoxMenuItem copyItem;
    private JCheckBoxMenuItem nullItem;
    private JCheckBoxMenuItem thItem;

    private class Doc extends InternalFrameAdapter implements ActionListener {
        String name;
        JInternalFrame frame;
        TransferHandler th;
        JTextArea area;

        public Doc(File file) {
            this.name = file.getName();
            try {
                init(file.toURI().toURL());
            } catch (MalformedURLException e) {
                e.printStackTrace();
            }
        }
        
        public Doc(String name) {
            this.name = name;
            init(getClass().getResource(name));
        }
        
        private void init(URL url) {
            frame = new JInternalFrame(name);
            frame.addInternalFrameListener(this);
            listModel.add(listModel.size(), this);

            area = new JTextArea();
            area.setMargin(new Insets(5, 5, 5, 5));

            try {
                BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream()));
                String in;
                while ((in = reader.readLine()) != null) {
                    area.append(in);
                    area.append("\n");
                }
                reader.close();
            } catch (Exception e) {
                e.printStackTrace();
                return;
            }

            th = area.getTransferHandler();
            area.setFont(new Font("monospaced", Font.PLAIN, 12));
            area.setCaretPosition(0);
            area.setDragEnabled(true);
            area.setDropMode(DropMode.INSERT);
            frame.getContentPane().add(new JScrollPane(area));
            dp.add(frame);
            frame.show();
            if (DEMO) {
                frame.setSize(300, 200);
            } else {
                frame.setSize(400, 300);
            }
            frame.setResizable(true);
            frame.setClosable(true);
            frame.setIconifiable(true);
            frame.setMaximizable(true);
            frame.setLocation(left, top);
            incr();
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    select();
                }
            });
            nullItem.addActionListener(this);
            setNullTH();
        }

        public void internalFrameClosing(InternalFrameEvent event) {
            listModel.removeElement(this);
            nullItem.removeActionListener(this);
        }

        public void internalFrameOpened(InternalFrameEvent event) {
            int index = listModel.indexOf(this);
            list.getSelectionModel().setSelectionInterval(index, index);
        }

        public void internalFrameActivated(InternalFrameEvent event) {
            int index = listModel.indexOf(this);
            list.getSelectionModel().setSelectionInterval(index, index);
        }

        public String toString() {
            return name;
        }
        
        public void select() {
            try {
                frame.toFront();
                frame.setSelected(true);
            } catch (java.beans.PropertyVetoException e) {}
        }
        
        public void actionPerformed(ActionEvent ae) {
            setNullTH();
        }
        
        public void setNullTH() {
            if (nullItem.isSelected()) {
                area.setTransferHandler(null);
            } else {
                area.setTransferHandler(th);
            }
        }
    }

    private TransferHandler handler = new TransferHandler() {
        public boolean canImport(TransferHandler.TransferSupport support) {
            if (!support.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
                return false;
            }

            if (copyItem.isSelected()) {
                boolean copySupported = (COPY & support.getSourceDropActions()) == COPY;

                if (!copySupported) {
                    return false;
                }

                support.setDropAction(COPY);
            }

            return true;
        }

        public boolean importData(TransferHandler.TransferSupport support) {
            if (!canImport(support)) {
                return false;
            }
            
            Transferable t = support.getTransferable();

            try {
                java.util.List<File> l =
                    (java.util.List<File>)t.getTransferData(DataFlavor.javaFileListFlavor);

                for (File f : l) {
                    new Doc(f);
                }
            } catch (UnsupportedFlavorException e) {
                return false;
            } catch (IOException e) {
                return false;
            }

            return true;
        }
    };

    private static void incr() {
        left += 30;
        top += 30;
        if (top == 150) {
            top = 0;
        }
    }

    public TopLevelTransferHandlerDemo() {
        super("TopLevelTransferHandlerDemo");
        setJMenuBar(createDummyMenuBar());
        getContentPane().add(createDummyToolBar(), BorderLayout.NORTH);

        JSplitPane sp = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, list, dp);
        sp.setDividerLocation(120);
        getContentPane().add(sp);
        //new Doc("sample.txt");
        //new Doc("sample.txt");
        //new Doc("sample.txt");

        list.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);

        list.addListSelectionListener(new ListSelectionListener() {
            public void valueChanged(ListSelectionEvent e) {
                if (e.getValueIsAdjusting()) {
                    return;
                }
                
                Doc val = (Doc)list.getSelectedValue();
                if (val != null) {
                    val.select();
                }
             }
        });
        
        final TransferHandler th = list.getTransferHandler();

        nullItem.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent ae) {
                if (nullItem.isSelected()) {
                    list.setTransferHandler(null);
                } else {
                    list.setTransferHandler(th);
                }
            }
        });
        thItem.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent ae) {
                if (thItem.isSelected()) {
                    setTransferHandler(handler);
                } else {
                    setTransferHandler(null);
                }
            }
        });
        dp.setTransferHandler(handler);
    }

    private static void createAndShowGUI(String[] args) {
        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (Exception e) {
        }

        TopLevelTransferHandlerDemo test = new TopLevelTransferHandlerDemo();
        test.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        if (DEMO) {
            test.setSize(493, 307);
        } else {
            test.setSize(800, 600);
        }
        test.setLocationRelativeTo(null);
        test.setVisible(true);
        test.list.requestFocus();
    }
    
    public static void main(final String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                //Turn off metal's use of bold fonts
                UIManager.put("swing.boldMetal", Boolean.FALSE);
                createAndShowGUI(args);
            }
        });
    }
    
    private JToolBar createDummyToolBar() {
        JToolBar tb = new JToolBar();
        JButton b;
        b = new JButton("New");
        b.setRequestFocusEnabled(false);
        tb.add(b);
        b = new JButton("Open");
        b.setRequestFocusEnabled(false);
        tb.add(b);
        b = new JButton("Save");
        b.setRequestFocusEnabled(false);
        tb.add(b);
        b = new JButton("Print");
        b.setRequestFocusEnabled(false);
        tb.add(b);
        b = new JButton("Preview");
        b.setRequestFocusEnabled(false);
        tb.add(b);
        tb.setFloatable(false);
        return tb;
    }
    
    private JMenuBar createDummyMenuBar() {
        JMenuBar mb = new JMenuBar();
        mb.add(createDummyMenu("File"));
        mb.add(createDummyMenu("Edit"));
        mb.add(createDummyMenu("Search"));
        mb.add(createDummyMenu("View"));
        mb.add(createDummyMenu("Tools"));
        mb.add(createDummyMenu("Help"));
        
        JMenu demo = new JMenu("Demo");
        demo.setMnemonic(KeyEvent.VK_D);
        mb.add(demo);

        thItem = new JCheckBoxMenuItem("Use Top-Level TransferHandler");
        thItem.setMnemonic(KeyEvent.VK_T);
        demo.add(thItem);

        nullItem = new JCheckBoxMenuItem("Remove TransferHandler from List and Text");
        nullItem.setMnemonic(KeyEvent.VK_R);
        demo.add(nullItem);

        copyItem = new JCheckBoxMenuItem("Use COPY Action");
        copyItem.setMnemonic(KeyEvent.VK_C);
        demo.add(copyItem);

        return mb;
    }
    
    private JMenu createDummyMenu(String str) {
        JMenu menu = new JMenu(str);
        JMenuItem item = new JMenuItem("[Empty]");
        item.setEnabled(false);
        menu.add(item);
        return menu;
    }
}