添加翻转到 JTree 句柄

2023-12-24

我正在尝试对Collapsed Icon https://docs.oracle.com/javase/8/docs/api/javax/swing/plaf/basic/BasicTreeUI.html#collapsedIcon对于 JTree。但是,我不确定如何定位单个句柄而不是所有句柄。

如果运行下面的代码,您将看到当您将鼠标悬停在 JTree 的任何句柄、节点或叶子上时,所有折叠的句柄都将变为翻转状态。这是不希望的。那么,当我将鼠标悬停在该句柄上时(最好不要将鼠标悬停在其旁边的节点上时)如何更改该句柄?

import java.awt.*;
import java.awt.event.*;

import javax.swing.*;
import javax.swing.tree.*;
import javax.swing.plaf.basic.*;

@SuppressWarnings("serial")
public class DirectoryExplorer extends JFrame {
    private DirectoryExplorer() {
        super("Directory Explorer");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLayout(new GridLayout(1, 1));
        createPanel();
        setSize(800,600);
        setVisible(true);
    }

    private void createPanel() {
        JPanel panel = new JPanel(new GridLayout(1, 1));

        DefaultMutableTreeNode root = new DefaultMutableTreeNode("Hello");
        root.add(new DefaultMutableTreeNode("1"));
        root.add(new DefaultMutableTreeNode("2"));
        root.add(new DefaultMutableTreeNode("3"));

        JTree tree = new JTree();
        BasicTreeUI tUI = (BasicTreeUI) tree.getUI();
        tUI.setCollapsedIcon(new ImageIcon("resources/closed.png"));
        tUI.setExpandedIcon(new ImageIcon("resources/open.png"));
        tree.setShowsRootHandles(true);
        tree.addMouseMotionListener(new MouseHandler(tree));

        panel.add(new JScrollPane(tree));
        getContentPane().add(panel);
    }

    public static void main(String[] args) {
        new DirectoryExplorer();
    }

    private class MouseHandler implements MouseMotionListener {
        JTree t = null;
        BasicTreeUI tUI = null;

        public MouseHandler(JTree tree) {
            t = tree;
            tUI = (BasicTreeUI) tree.getUI();
        }

        @Override
        public void mouseDragged(MouseEvent e) {

        }

        @Override
        public void mouseMoved(MouseEvent e) {
            TreePath selPath = t.getPathForLocation(e.getX(), e.getY());
            if(selPath != null) 
                tUI.setCollapsedIcon(new ImageIcon("resources/rollover.png"));
            else
                tUI.setCollapsedIcon(new ImageIcon("resources/closed.png"));
            t.repaint();
        }
    }
}

为了达到想要的结果,你需要覆盖BasicTreeUI.paintExpandControl() and BasicTreeUI.MouseHandler.mouseMoved()。您还需要创建一些方法,例如setRolloverIcon().

一个工作示例可能如下所示

import java.awt.Component;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.net.MalformedURLException;
import java.net.URL;

import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.plaf.basic.BasicTreeUI;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreePath;

@SuppressWarnings("serial")
public class DirectoryExplorer extends JFrame {
    private DirectoryExplorer() {
        super("Directory Explorer");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLayout(new GridLayout(1, 1));
        createPanel();
        setSize(800,600);
        setVisible(true);
    }

    private void createPanel() {
        JPanel panel = new JPanel(new GridLayout(1, 1));

        DefaultMutableTreeNode root = new DefaultMutableTreeNode("Hello");
        root.add(new DefaultMutableTreeNode("1"));
        root.add(new DefaultMutableTreeNode("2"));
        root.add(new DefaultMutableTreeNode("3"));

        JTree tree = new JTree();

        //UI Stuff//
        TreeHandleUI tUI = new TreeHandleUI(tree);
        tree.setUI(tUI);
        try {
            tUI.setCollapsedIcon(new ImageIcon(new URL("https://i.stack.imgur.com/nKJFv.png")));
            tUI.setExpandedIcon(new ImageIcon(new URL("https://i.stack.imgur.com/NJvcp.png")));
            tUI.setRolloverIcon(new ImageIcon(new URL("https://i.stack.imgur.com/jN6uX.png")));
        } catch(MalformedURLException e) {
            System.out.println("Bad URL / URLs");
        }
        ////////////

        tree.setShowsRootHandles(true);

        panel.add(new JScrollPane(tree));
        getContentPane().add(panel);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(() -> new DirectoryExplorer());
    }

    private class TreeHandleUI extends BasicTreeUI {
        ///Variables
        private JTree t = null;
        private Icon rolloverIcon = null;
        private boolean rolloverEnabled = false;
        private UpdateHandler uH = null;

        private boolean isLeftToRight( Component c ) {
            return c.getComponentOrientation().isLeftToRight();
        }

        public TreeHandleUI(JTree tree) {
            t = tree;
            uH = new UpdateHandler(t);
            t.addMouseMotionListener(uH);
        }

        public void setRolloverIcon(Icon rolloverG) {
            Icon oldValue = rolloverIcon;
            rolloverIcon = rolloverG;
            setRolloverEnabled(true);
            if (rolloverIcon != oldValue) {
                t.repaint();
            }
        }

        private void setRolloverEnabled(boolean handleRolloverEnabled) {
            boolean oldValue = rolloverEnabled;
            rolloverEnabled = handleRolloverEnabled;
            if (handleRolloverEnabled != oldValue) {
                t.repaint();
            }
        }

        @Override
        protected void paintExpandControl(Graphics g,
                                          Rectangle clipBounds, Insets insets,
                                          Rectangle bounds, TreePath path,
                                          int row, boolean isExpanded,
                                          boolean hasBeenExpanded,
                                          boolean isLeaf) {
            Object value = path.getLastPathComponent();

            if (!isLeaf && (!hasBeenExpanded || treeModel.getChildCount(value) > 0)) {
                int middleXOfKnob;
                if (isLeftToRight(t)) {
                    middleXOfKnob = bounds.x - getRightChildIndent() + 1;
                } else {
                    middleXOfKnob = bounds.x + bounds.width + getRightChildIndent() - 1;
                }
                int middleYOfKnob = bounds.y + (bounds.height / 2);

                if (isExpanded) {
                    Icon expandedIcon = getExpandedIcon();
                    if(expandedIcon != null)
                      drawCentered(tree, g, expandedIcon, middleXOfKnob, middleYOfKnob );
                } else if(isLocationInExpandControl(path, uH.getXPos(), uH.getYPos()) && !isExpanded && rolloverEnabled) {
                    if(row == uH.getRow()) {
                        if(rolloverIcon != null)
                            drawCentered(tree, g, rolloverIcon, middleXOfKnob, middleYOfKnob);
                    } else {
                        Icon collapsedIcon = getCollapsedIcon();
                        if(collapsedIcon != null)
                          drawCentered(tree, g, collapsedIcon, middleXOfKnob, middleYOfKnob);
                    }
                } else {
                    Icon collapsedIcon = getCollapsedIcon();
                    if(collapsedIcon != null)
                      drawCentered(tree, g, collapsedIcon, middleXOfKnob, middleYOfKnob);
                }
            }
        }

        private class UpdateHandler extends BasicTreeUI.MouseHandler {
            private JTree t = null;
            private int xPos = 0;
            private int yPos = 0;

            private boolean leftToRight(Component c) {
                return c.getComponentOrientation().isLeftToRight();
            }

            public UpdateHandler(JTree tree) {
                t = tree;
            }

            @Override
            public void mouseMoved(MouseEvent e) {
                xPos = e.getX();
                yPos = e.getY();
                t.repaint();
            }

            public int getXPos() {
                return xPos;
            }

            public int getYPos() {
                return yPos;
            }

            public int getRow() {
                return getRowForPath(t, getClosestPathForLocation(t, xPos, yPos));
            }
        }
    }
}

代码将在不下载图像的情况下运行,但它们在下面可用

closed.png
enter image description here

open.png
enter image description here

rollover.png
enter image description here

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

添加翻转到 JTree 句柄 的相关文章

  • 在 Java 中连接和使用 Cassandra

    我已经阅读了一些关于 Cassandra 是什么以及它可以做什么的教程 但我的问题是如何在 Java 中与 Cassandra 交互 教程会很好 如果可能的话 有人可以告诉我是否应该使用 Thrift 还是 Hector 哪一个更好以及为什
  • Java new Date() 打印

    刚刚学习 Java 我知道这可能听起来很愚蠢 但我不得不问 System out print new Date 我知道参数中的任何内容都会转换为字符串 最终值是 new Date 返回对 Date 对象的引用 那么它是如何打印这个的呢 Mo
  • 为什么 i++ 不是原子的?

    Why is i Java 中不是原子的 为了更深入地了解 Java 我尝试计算线程中循环的执行频率 所以我用了一个 private static int total 0 在主课中 我有两个线程 主题 1 打印System out prin
  • 给定两个 SSH2 密钥,我如何检查它们是否属于 Java 中的同一密钥对?

    我正在尝试找到一种方法来验证两个 SSH2 密钥 一个私有密钥和一个公共密钥 是否属于同一密钥对 我用过JSch http www jcraft com jsch 用于加载和解析私钥 更新 可以显示如何从私钥 SSH2 RSA 重新生成公钥
  • JAXb、Hibernate 和 beans

    目前我正在开发一个使用 Spring Web 服务 hibernate 和 JAXb 的项目 1 我已经使用IDE hibernate代码生成 生成了hibernate bean 2 另外 我已经使用maven编译器生成了jaxb bean
  • 反射找不到对象子类型

    我试图通过使用反射来获取包中的所有类 当我使用具体类的代码 本例中为 A 时 它可以工作并打印子类信息 B 扩展 A 因此它打印 B 信息 但是当我将它与对象类一起使用时 它不起作用 我该如何修复它 这段代码的工作原理 Reflection
  • 操作错误不会显示在 JSP 上

    我尝试在 Action 类中添加操作错误并将其打印在 JSP 页面上 当发生异常时 它将进入 catch 块并在控制台中打印 插入异常时出错 请联系管理员 在 catch 块中 我添加了它addActionError 我尝试在jsp页面中打
  • 斯坦福 NLP - 处理文件列表时 OpenIE 内存不足

    我正在尝试使用斯坦福 CoreNLP 中的 OpenIE 工具从多个文件中提取信息 当多个文件 而不是一个 传递到输入时 它会给出内存不足错误 All files have been queued awaiting termination
  • 十进制到八进制的转换[重复]

    这个问题在这里已经有答案了 可能的重复 十进制转换错误 https stackoverflow com questions 13142977 decimal conversion error 我正在为一个类编写一个程序 并且在计算如何将八进
  • 在两个活动之间传输数据[重复]

    这个问题在这里已经有答案了 我正在尝试在两个不同的活动之间发送和接收数据 我在这个网站上看到了一些其他问题 但没有任何问题涉及保留头等舱的状态 例如 如果我想从 A 类发送一个整数 X 到 B 类 然后对整数 X 进行一些操作 然后将其发送
  • 为什么HashMap不能保证map的顺序随着时间的推移保持不变

    我在这里阅读有关 Hashmap 和 Hashtable 之间的区别 http javarevisited blogspot sg 2010 10 difference Between hashmap and html http javar
  • Java Integer CompareTo() - 为什么使用比较与减法?

    我发现java lang Integer实施compareTo方法如下 public int compareTo Integer anotherInteger int thisVal this value int anotherVal an
  • 如何从终端运行处理应用程序

    我目前正在使用加工 http processing org对于一个小项目 但是我不喜欢它附带的文本编辑器 我使用 vim 编写所有代码 我找到了 pde 文件的位置 并且我一直在从 vim 中编辑它们 然后重新打开它们并运行它们 重新加载脚
  • 在mockito中使用when进行模拟ContextLoader.getCurrentWebApplicationContext()调用。我该怎么做?

    我试图在使用 mockito 时模拟 ContextLoader getCurrentWebApplicationContext 调用 但它无法模拟 here is my source code Mock org springframewo
  • 如何在桌面浏览器上使用 webdriver 移动网络

    我正在使用 selenium webdriver 进行 AUT 被测应用程序 的功能测试自动化 AUT 是响应式网络 我几乎完成了桌面浏览器的不同测试用例 现在 相同的测试用例也适用于移动浏览器 因为可以从移动浏览器访问 AUT 由于它是响
  • simpleframework,将空元素反序列化为空字符串而不是 null

    我使用简单框架 http simple sourceforge net http simple sourceforge net 在一个项目中满足我的序列化 反序列化需求 但在处理空 空字符串值时它不能按预期工作 好吧 至少不是我所期望的 如
  • 获取 JVM 上所有引导类的列表?

    有一种方法叫做findBootstrapClass对于一个类加载器 如果它是引导的 则返回一个类 有没有办法找到类已经加载了 您可以尝试首先通过例如获取引导类加载器呼叫 ClassLoader bootstrapLoader ClassLo
  • 静态变量的线程安全

    class ABC implements Runnable private static int a private static int b public void run 我有一个如上所述的 Java 类 我有这个类的多个线程 在里面r
  • 如何实现仅当可用内存较低时才将数据交换到磁盘的写缓存

    我想将应用程序生成的数据缓存在内存中 但如果内存变得稀缺 我想将数据交换到磁盘 理想情况下 我希望虚拟机通知它需要内存并将我的数据写入磁盘并以这种方式释放一些内存 但我没有看到任何方法以通知我的方式将自己挂接到虚拟机中before an O
  • 使用 xpath 和 vtd-xml 以字符串形式获取元素的子节点和文本

    这是我的 XML 的一部分

随机推荐

  • 将所有函数保存在txt文件中

    我通常会运行大量模拟R 在模拟之间 R 的某些部分 代码会改变 通常情况下 我会站在旁边 模拟结果包含以下内容的 txt 文件 其中使用的每个函数的定义 模拟 为了制作该 txt 文件 我只需 运行这一行 for j in 1 length
  • 开始学习 JavaFX 之前需要了解什么? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我读到了 JavaFX 相对于 Swing 的优势 这不是讨论的重点 我想学习 JavaFX 但后来我对 JavaFX 脚本和 XML
  • Android Square Picasso 无法加载土耳其字符图像 url

    我尝试使用 square picasso 一个网络应用程序 但是如果我的图片网址包含土耳其字符 毕加索未加载 该网址正在运行 http www bulenttiras com wp content uploads 2014 02 kokhu
  • 虚拟类中的抽象方法

    我有一个 C 类 它有很多虚拟方法 其中一些方法本质上是抽象的 它们在子类中完全实现 基类是空的 为了让它编译 我在基类中抛出一个 InvalidOperationException 并注释应该做什么 这只是感觉很脏 有更好的方法来设计我的
  • Android,日文字符文件名比较问题

    我正在尝试将搜索字符串与文件名与 Android 上的递归目录搜索相匹配 问题是字符是日语 在某些情况下不匹配 例如 我尝试匹配文件名开头的搜索字符串是 呼 当我从 file getName 打印文件名时 这会准确反映 例如打印到控制台的文
  • Oracle中如何进行条件插入?

    我读了here http psoug org snippet INSERT WHEN 588 htm语法如下所示 INSERT WHEN Condition THEN INTO TableName ColumnName VALUES VAL
  • 使用 Polly 断路器处理多种服务的正确方法

    我有一个应用程序 我们可以在其中与数百个 HTTP 端点进行通信 该应用程序是某种代理 在使用 polly 进行测试时 我注意到如果一个端点 比如说api endpoint1 com失败 调用api endpoint2 com and ap
  • 如何使用SQL查询来定义dbtable中的表?

    In JDBC 到其他数据库 http spark apache org docs latest sql programming guide html jdbc to other databases我找到了以下解释dbtable范围 应读取
  • 当单元格内容被截断时,将 VB.Net DataGridView 中的三个点(省略号)(...) 更改为自定义字符

    我正在 VB Net 中开发一个项目 并且使用古吉拉特语字体 非 Unicode 我放置了一个 DaraGridView DGV 并在 DGV 中显示数据库中存储的数据 在 DGV 中 如果单元格的内容被截断 则 DGV 显示椭圆 三个点
  • iPhone 应用程序和 Web 应用程序之间的双向同步

    我有一个依赖于 MySQL 数据库的 Web 应用程序 我正在考虑为其构建一个 iPhone 应用程序 该应用程序将允许用户在网络应用程序上浏览 插入 更新 删除其帐户的数据 最简单的方法是将 iPhone 应用程序简单地构建为 Web 应
  • java.lang.IllegalStateException:凭证加密存储中的 SharedPreferences 在用户解锁之前不可用

    Google Pixel 设备 OS 9 0 pie 上的 cashlytics 中不会记录崩溃 Playstore 将 ANR Crashes 报告为 java lang IllegalStateException 凭证加密存储中的 Sh
  • C# catch(FileNotFoundException) 和 CA1031

    所以这段代码会触发CA1031 try logic catch FileNotFoundException exception type handle error 虽然这个没有 try logic catch FileNotFoundExc
  • 密码确认验证 CakePHP

    我进行了广泛的搜索 尝试了书中的每一个技巧 但我仍然无法让我的 CakePHP 应用程序执行简单的密码确认验证 我尝试创建一个自定义验证规则 如下所示 passwordequal gt array rule gt checkpassword
  • 无法让此正则表达式适用于 Snakemake 中的 wildcard_constraints

    我有一个用 Snakemake 编写的工作流程 用于分析生物测序数据 工作流程期望对所有数据文件进行组织 以便每个原始读取文件都以检测类型 RNASeq DNaseSeq 等 开头 并且在工作流程生成的所有文件中都保持此文件名约定 我有一个
  • Chrome中如何区分浏览器关闭和刷新事件?

    如何使用 JavaScript for CHROME 区分浏览器关闭和刷新事件 我尝试过下面的 JavaScript 代码 但它不适用于 Chrome window onbeforeunload function e var e e win
  • 如何打印问题中的变量值?

    我做一点补充 sumbit CIN A B CO R sumbit 0 1 1 CO R write CIN nl write A nl write nl write B nl write nl write CO write R nl 我想
  • Kotlin Gson 反序列化

    我收到一个带有地图包装器的 JSON 数据模型Table 我试图使用泛型来传递超出包装器的类型 但它在运行时翻译得不好 这是我的 JSON 文件的示例 Table paymentmethod id 1 paymentmethod descr
  • 合并两个纠缠的凸包

    如何合并两个纠缠的凸包 例如this https i stack imgur com ALM4G jpg 使用格雷厄姆扫描或任何其他算法在线性时间内形成凸包 基本上 你使用安德鲁的修改 https en wikibooks org wiki
  • 本机查询支持 SQL Server 的 Spring data jpa 流

    我们需要使用 Spring data jpa 从 SQL Server 检索数据 由于我们有数百万条记录 因此我们无法一次请求加载所有数据 是否可以使用本机查询进行流式传输 是的 您可以让您的查询方法在 Spring Data JPA 中返
  • 添加翻转到 JTree 句柄

    我正在尝试对Collapsed Icon https docs oracle com javase 8 docs api javax swing plaf basic BasicTreeUI html collapsedIcon对于 JTr