美文网首页
swing JTree踩坑自定义TreeCellRenderer

swing JTree踩坑自定义TreeCellRenderer

作者: 魂狩 | 来源:发表于2023-01-02 15:51 被阅读0次

近来在写idea插件,需要用到界面,只能使用swing。于是开始踩坑……

需求

解析依赖文件,展示依赖的版本信息和更新时间,用户发现依赖有问题可以自己更新。由于一个JLabel不够用,默认的DefaultTreeCellRenderer就不够用了,需要开始研究。

第一个坑

DefaultTreeCellRenderer是继承的JLabelTreeCellRenderer,那么我新写一个继承JComponentTreeCellRenderer的类不就可以了?但是事实是不行,或者说很麻烦。UI相关的资源和配置需要使用sun.swing.DefaultLookup这个类进行获取,DefaultTreeCellRendererjavax.swing.tree包下,可以访问,但是我们不行,sun.swing.DefaultLookup这个类并没有公开。直接引用会出现Symbol is declared in module 'java.desktop' which does not export package 'sun.swing'错误。所以,我们必须使用原来的DefaultTreeCellRenderer类。

第二个坑

JTree本质是调用TreeCellRenderergetTreeCellRendererComponent方法,然后一行行画出来的,所以只需要构造一个TreeCellRenderer类就够了。每一条数据都会执行一遍,然后画到JTree控件里面去,事件处理也需要注册在JTree上面。也因此,在自定义TreeCellRenderer里面添加交互控件,比如按钮,是无效的。如果需要进行交互,最好用右键菜单(有个editorCellRenderer不确定行不行,没试过,待尝试)。

第三个坑

getTreeCellRendererComponent方法的value是包装后的MutableTreeNode,不是userObject。需要进行转换才能拿到传进去的数据。

示例

package me.small.vision.window

import me.small.vision.data.InfoPO
import java.awt.BorderLayout
import java.awt.Component
import javax.swing.ImageIcon
import javax.swing.JComponent
import javax.swing.JLabel
import javax.swing.JTree
import javax.swing.tree.DefaultMutableTreeNode
import javax.swing.tree.DefaultTreeCellRenderer
import javax.swing.tree.TreeCellRenderer

class MyTreeCellRenderer : JComponent(), TreeCellRenderer {
    private var father: DefaultTreeCellRenderer = DefaultTreeCellRenderer()

    init {
        father.leafIcon = ImageIcon(this.javaClass.classLoader.getResource("leaf.png"))
        layout = BorderLayout()
        add(JLabel("time"), BorderLayout.EAST)
        add(JLabel("info"), BorderLayout.WEST)
    }

    override fun getTreeCellRendererComponent(
        tree: JTree,
        value: Any,
        selected: Boolean,
        expanded: Boolean,
        leaf: Boolean,
        row: Int,
        hasFocus: Boolean
    ): Component {
        value as DefaultMutableTreeNode
        remove(1)
        if (value.userObject is InfoPO) {
            val data = value.userObject!! as InfoPO
            (components[0] as JLabel).text = data.time
            add(
                father.getTreeCellRendererComponent(
                    tree,
                    data.name,
                    selected,
                    expanded,
                    leaf,
                    row,
                    hasFocus
                ), BorderLayout.WEST
            )
        } else {
            (components[0] as JLabel).text = ""
            add(
                father.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus),
                BorderLayout.WEST
            )
        }
        return this
    }
}

这里有个小坑,components是私有属性component的引用,直接修改components[1]是不行的,必须删了然后添加。这样渲染出来的效果,就是左边是依赖名称,右边是更新时间,清晰明了。

相关文章

网友评论

      本文标题:swing JTree踩坑自定义TreeCellRenderer

      本文链接:https://www.haomeiwen.com/subject/aquccdtx.html