【问题标题】:Java JTree node is a clickable URL linkJava JTree 节点是一个可点击的 URL 链接
【发布时间】:2017-05-30 16:51:17
【问题描述】:

我正在尝试使节点成为可点击的 URL,但我似乎无法弄清楚如何。

我搜索了高低,似乎找不到解决方案。

这是我的代码:

public class NyttigeLinks {

    private static JFrame nyttigeLinks;

    public static void main(String[] args) {

                    initialize();
            }

    public NyttigeLinks() {

    }

    private static void initialize() {
        nyttigeLinks = new JFrame();
        nyttigeLinks.setBounds(new Rectangle(0, 0, 350, 650));
        nyttigeLinks.getContentPane().setBounds(new Rectangle(0, 0, 350, 650));
        nyttigeLinks.getContentPane().setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
        nyttigeLinks.getContentPane().setLayout(null);

        JLabel logoLabel = new JLabel("");
        logoLabel.setIcon(new ImageIcon(NyttigeLinks.class.getResource("/images/ssiLogo.jpg")));
        logoLabel.setBounds(0, 0, 350, 60);

        JTree tree = new JTree();

        nyttigeLinks.getContentPane().add(logoLabel);

        JScrollPane scrollPane = new JScrollPane(tree);
        scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
        scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
        scrollPane.setBounds(10, 71, 324, 508);
        nyttigeLinks.getContentPane().add(scrollPane);

        tree.setModel(new DefaultTreeModel(
            new DefaultMutableTreeNode("Nyttige Links\t") {
                {
                    DefaultMutableTreeNode node_1;
                    node_1 = new DefaultMutableTreeNode("Projekt Wiki");
                        node_1.add(new DefaultMutableTreeNode("AO"));
                        node_1.add(new DefaultMutableTreeNode("Attends"));
                        node_1.add(new DefaultMutableTreeNode("Carlsberg"));
                        node_1.add(new DefaultMutableTreeNode("COOP"));
                        node_1.add(new DefaultMutableTreeNode("Dafgaard"));
                        node_1.add(new DefaultMutableTreeNode("Jysk DK"));
                        node_1.add(new DefaultMutableTreeNode("Jysk SE"));
                        node_1.add(new DefaultMutableTreeNode("Kvadrat"));
                        node_1.add(new DefaultMutableTreeNode("Solar"));
                        node_1.add(new DefaultMutableTreeNode("Stockmann"));
                        node_1.add(new DefaultMutableTreeNode("Tine"));
                        node_1.add(new DefaultMutableTreeNode("Unicef"));
                        node_1.add(new DefaultMutableTreeNode("Vectura"));
                    add(node_1);
                    node_1 = new DefaultMutableTreeNode("Helpdesk Norcic");
                        node_1.add(new DefaultMutableTreeNode("Test"));
                    add(node_1);
                    node_1 = new DefaultMutableTreeNode("Test");
                        node_1.add(new DefaultMutableTreeNode("AO"));
                        node_1.add(new DefaultMutableTreeNode("Attends"));
                        node_1.add(new DefaultMutableTreeNode("Carlsberg"));
                        node_1.add(new DefaultMutableTreeNode("COOP"));
                        node_1.add(new DefaultMutableTreeNode("Dafgaard"));
                        node_1.add(new DefaultMutableTreeNode("Jysk DK"));
                        node_1.add(new DefaultMutableTreeNode("Jysk SE"));
                        node_1.add(new DefaultMutableTreeNode("Kvadrat"));
                        node_1.add(new DefaultMutableTreeNode("Solar"));
                        node_1.add(new DefaultMutableTreeNode("Stockmann"));
                        node_1.add(new DefaultMutableTreeNode("Tine"));
                        node_1.add(new DefaultMutableTreeNode("Unicef"));
                        node_1.add(new DefaultMutableTreeNode("VecturaAO"));
                        node_1.add(new DefaultMutableTreeNode("Attends"));
                        node_1.add(new DefaultMutableTreeNode("Carlsberg"));
                        node_1.add(new DefaultMutableTreeNode("COOP"));
                        node_1.add(new DefaultMutableTreeNode("Dafgaard"));
                        node_1.add(new DefaultMutableTreeNode("Jysk DK"));
                        node_1.add(new DefaultMutableTreeNode("Jysk SE"));
                        node_1.add(new DefaultMutableTreeNode("Kvadrat"));
                        node_1.add(new DefaultMutableTreeNode("Solar"));
                        node_1.add(new DefaultMutableTreeNode("Stockmann"));
                        node_1.add(new DefaultMutableTreeNode("Tine"));
                        node_1.add(new DefaultMutableTreeNode("Unicef"));
                        node_1.add(new DefaultMutableTreeNode("VecturaAO"));
                        node_1.add(new DefaultMutableTreeNode("Attends"));
                        node_1.add(new DefaultMutableTreeNode("Carlsberg"));
                        node_1.add(new DefaultMutableTreeNode("COOP"));
                        node_1.add(new DefaultMutableTreeNode("Dafgaard"));
                        node_1.add(new DefaultMutableTreeNode("Jysk DK"));
                        node_1.add(new DefaultMutableTreeNode("Jysk SE"));
                        node_1.add(new DefaultMutableTreeNode("Kvadrat"));
                        node_1.add(new DefaultMutableTreeNode("Solar"));
                        node_1.add(new DefaultMutableTreeNode("Stockmann"));
                        node_1.add(new DefaultMutableTreeNode("Tine"));
                        node_1.add(new DefaultMutableTreeNode("Unicef"));
                        node_1.add(new DefaultMutableTreeNode("Vectura"));
                    add(node_1);
                }
            }
        ));
        tree.setBounds(10, 71, 324, 540);
        tree.setRootVisible(false);

        JLabel bottomLabelTop = new JLabel("                   Nyttige Links Version 1.0");
        bottomLabelTop.setBounds(0, 590, 230, 14);
        nyttigeLinks.getContentPane().add(bottomLabelTop);

        JLabel bottomLabelBot = new JLabel("                              Made by xxx");
        bottomLabelBot.setBounds(0, 605, 230, 15);
        nyttigeLinks.getContentPane().add(bottomLabelBot);

        JButton btnNewButton = new JButton("Admin");
        btnNewButton.setIcon(new ImageIcon(NyttigeLinks.class.getResource("/images/appIcon.ico")));
        btnNewButton.setBounds(240, 590, 80, 20);
        nyttigeLinks.getContentPane().add(btnNewButton);
        nyttigeLinks.setPreferredSize(new Dimension(350, 650));
        nyttigeLinks.setSize(new Dimension(350, 650));
        nyttigeLinks.setResizable(false);
        nyttigeLinks.setTitle("Nyttige Links");
        nyttigeLinks.setIconImage(Toolkit.getDefaultToolkit().getImage(NyttigeLinks.class.getResource("/images/appIcon.ico")));
        nyttigeLinks.setBackground(Color.YELLOW);
        nyttigeLinks.setBounds(100, 100, 350, 650);
        nyttigeLinks.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        nyttigeLinks.setVisible(true);
    }
}

我很抱歉有点菜鸟,但你总得从某个地方开始吧?

如果有人能指出我正确的方向,我将不胜感激!祝大家晚安!

【问题讨论】:

    标签: java jtree


    【解决方案1】:

    我不相信有办法让节点本身成为 URL。但是,您可以通过在单击节点时使用侦听器打开浏览器来完成相同的操作。要打开浏览器,可以使用Desktop#browse(URI) 方法。

    关于单击的主题,我建议在单击节点时不要打开 URL。对于非常烦人的用户(IMO)。相反,我建议使用双击。 This answer提供了很好的区分单击和双击的方法,以及如何将其添加到Tree


    [...] 但你必须从某个地方开始,对吧?

    没错!请允许我在这里提供更多详细信息,希望对更多学习有所帮助。

    您将面临的一个挑战是如何知道要为给定节点打开哪个 URL。目前您只知道显示的String,我认为您不希望显示每个节点的完整 URL 是一个安全的假设。我建议不要使用String 参数创建DefaultMutableTreeNode 对象,而是创建一个传递给DefaultMutableTreeNode 构造函数的对象。该对象还可以具有URI 属性,因此它知道要打开哪个 URL。

    例如:

    public class LeafNodeObject {
        private final URI uri;
    
        public LeafNodeObject(final String display, final URI uri) {
            this.display = display;
            this.uri = uri;
        }
    
        /**
         * Override so that we control what is display on the Node
         */
        @Override
        public String toString() {
            return display;
        }
    
        public void onDoubleClick() {
            try {
                Desktop.getDesktop().browse(uri);
            } catch (final IOException e) {
                e.printStackTrace();
            }
        }
    
    }
    

    可以像这样添加节点:

    node_1.add(new DefaultMutableTreeNode(new LeafNodeObject("Test", new URI("www.eclipse.org"))));
    

    在我们的监听器中(根据上面的链接稍作修改):

    final MouseListener ml = new MouseAdapter() {
        public void mousePressed(final MouseEvent e) {
            final int selRow = tree.getRowForLocation(e.getX(), e.getY());
            final TreePath selPath = tree.getPathForLocation(e.getX(), e.getY());
            if (selRow != -1) {
                final DefaultMutableTreeNode node = (DefaultMutableTreeNode) selPath.getLastPathComponent();
                if (e.getClickCount() == 1) {
                    // Single click
                } else if (e.getClickCount() == 2) {
                    // Double click
                    ((LeafNodeObject) node.getUserObject()).onDoubleClick();
                }
            }
        }
    };
    

    现在当有双击事件时,我们在我们创建的LeafNodeObject 上调用onDoubleClick() 方法。

    这看起来很棒,除了我们会遇到非叶节点的类转换问题!为了解决这个问题,我们可以为这些节点创建一个类似的类(例如ParentNodeObject)。为了良好的 OOP,我们应该认识到这两个类的共同行为(onDoubleClick(),还有一个onSingleClick()),并为共享能力创建一个接口。

    例如:

    public interface NodeObject {
        public void onSingleClick();
        public void onDoubleClick();
    }
    

    现在我们可以让我们的两个类实现这个接口:

    public class ParentNodeObject implements NodeObject {
        private final String display;
    
        public ParentNodeObject(final String display) {
            this.display = display;
        }
    
        /**
         * Override so that we control what is display on the Node
         */
        @Override
        public String toString() {
            return display;
        }
    
        @Override
        public void onSingleClick() {
            // Do nothing
        }
    
        @Override
        public void onDoubleClick() {
            // Do nothing
        }
    }
    
    public class LeafNodeObject implements NodeObject {
        private final URI uri;
    
        public LeafNodeObject(final String display, final URI uri) {
            this.display = display;
            this.uri = uri;
        }
    
        /**
         * Override so that we control what is display on the Node
         */
        @Override
        public String toString() {
            return display;
        }
    
        @Override
        public void onSingleClick() {
            // Do nothing
        }
    
        @Override
        public void onDoubleClick() {
            try {
                Desktop.getDesktop().browse(uri);
            } catch (final IOException e) {
                e.printStackTrace();
            }
        }
    
    }
    

    因此,在我们的监听器中,我们不再需要知道(也不再关心)该节点是父节点还是叶节点。我们可以简单地调用onSingleClick()onDoubleClick(),其余的由实现来处理!

    if (e.getClickCount() == 1) {
        // Single click
        ((NodeObject) node.getUserObject()).onSingleClick();
    } else if (e.getClickCount() == 2) {
        // Double click
        ((NodeObject) node.getUserObject()).onDoubleClick();
    }
    

    回到您的代码中,可以像这样添加父节点和子节点:

    node_1 = new DefaultMutableTreeNode(new ParentNodeObject("Helpdesk Norcic"));
    node_1.add(new DefaultMutableTreeNode(new LeafNodeObject("Test", new URI("www.eclipse.org"))));
    

    现在,当您单击或双击任何节点时,onSingleClick()onDoubleClick() 方法也将被调用。在这种情况下我们只关心双击叶子节点时会发生什么,所以我们只需要填写那个方法。

    【讨论】:

    • 太棒了!非常感谢你的帮助。明天早上下班的时候我会研究一下。我今晚没有时间了。非常感谢,我一定会更新这个帖子的进展情况。
    • @TheGreyNight 不客气!如果有任何不完全合理或可以使用更好的解释的地方,请告诉我。
    【解决方案2】:

    虽然我还没有检查上面提到的代码,但我在等待对该线程的回复时是这样解决这个问题的:

    class SelectionListener implements TreeSelectionListener {
    
        public void valueChanged(TreeSelectionEvent se) {
            JTree tree = (JTree) se.getSource();
            DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent();
            String selectedNodeName = selectedNode.toString();
            if (selectedNode.isLeaf()) {
                if (selectedNodeName == "Unicef") {
                    try {
                        java.awt.Desktop.getDesktop().browse(java.net.URI.create("http://www.eb.dk"));
                    } catch (IOException e1) {
                        // make a error pop up appear here
                        JOptionPane.showMessageDialog(null, "Something went wrong, please report this to the developer!", "Something went wrong", 0);
                        e1.printStackTrace();
    
                    }
                }
    
                if (selectedNodeName == "Vectura") {
                    try {
                        java.awt.Desktop.getDesktop().browse(java.net.URI.create("http://www.google.com"));
                    } catch (IOException e1) {
                        // make a error pop up appear here
                        JOptionPane.showMessageDialog(null, "Something went wrong, please report this to the developer!", "Something went wrong", 0);
                        e1.printStackTrace();
    
                    }
                }
    
            }
    
        }
    }
    

    这绝对不是一个好方法,因为它会导致很多 if 语句,但它很简单,我自己可以理解。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-05
      • 1970-01-01
      • 2018-03-20
      • 2010-12-26
      相关资源
      最近更新 更多