`
zeyuphoenix
  • 浏览: 57883 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

树(选择框)

 
阅读更多
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <meta name="ProgId" content="Word.Document"> <meta name="Generator" content="Microsoft Word 12"> <meta name="Originator" content="Microsoft Word 12"> <link rel="File-List" href="file:///C:%5CDOCUME%7E1%5Cphoenix%5CLOCALS%7E1%5CTemp%5Cmsohtmlclip1%5C01%5Cclip_filelist.xml"> <link rel="Edit-Time-Data" href="file:///C:%5CDOCUME%7E1%5Cphoenix%5CLOCALS%7E1%5CTemp%5Cmsohtmlclip1%5C01%5Cclip_editdata.mso"> <!--[if !mso]> <style> v":* {behavior:url(#default#VML);} o":* {behavior:url(#default#VML);} w":* {behavior:url(#default#VML);} .shape {behavior:url(#default#VML);} </style> <![endif]--><link rel="themeData" href="file:///C:%5CDOCUME%7E1%5Cphoenix%5CLOCALS%7E1%5CTemp%5Cmsohtmlclip1%5C01%5Cclip_themedata.thmx"> <link rel="colorSchemeMapping" href="file:///C:%5CDOCUME%7E1%5Cphoenix%5CLOCALS%7E1%5CTemp%5Cmsohtmlclip1%5C01%5Cclip_colorschememapping.xml"> <!--[if gte mso 9]><xml> Normal 0 false 7.8 磅 0 2 false false false EN-US ZH-CN X-NONE </xml><![endif]--><!--[if gte mso 9]><![endif]--><style> <!-- /* Font Definitions */ @font-face {font-family:宋体; panose-1:2 1 6 0 3 1 1 1 1 1;} @font-face {font-family:"Cambria Math"; panose-1:2 4 5 3 5 4 6 3 2 4;} @font-face {font-family:Calibri; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-alt:"Times New Roman";} @font-face {font-family:""@宋体"; panose-1:2 1 6 0 3 1 1 1 1 1;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal { mso-style-parent:""; margin:0cm; margin-bottom:.0001pt; text-align:justify; text-justify:inter-ideograph; font-size:10.5pt; font-family:"Calibri","serif"; mso-bidi-font-family:"Times New Roman";} p.MsoListParagraph, li.MsoListParagraph, div.MsoListParagraph { margin:0cm; margin-bottom:.0001pt; text-align:justify; text-justify:inter-ideograph; text-indent:21.0pt; font-size:10.5pt; font-family:"Calibri","serif"; mso-bidi-font-family:"Times New Roman";} .MsoChpDefault { mso-bidi-font-family:"Times New Roman";} /* Page Definitions */ @page {} @page Section1 {size:595.3pt 841.9pt; margin:72.0pt 90.0pt 72.0pt 90.0pt; layout-grid:15.6pt;} div.Section1 {page:Section1;} /* List Definitions */ @list l0 {} @list l0:level1 { margin-left:18.0pt; text-indent:-18.0pt;} ol {margin-bottom:0cm;} ul {margin-bottom:0cm;} --> </style> <!--[if gte mso 10]> <style> /* Style Definitions */ table.MsoNormalTable { mso-style-parent:""; font-size:10.5pt; font-family:"Calibri","serif";} </style> <![endif]-->

先是春游然后又开始忙了,都没时间写了,不爽.

JTree的选择框其实也是Renderer的一种表现,单纯实现效果的话很简单,只需要设置Renderer就可以了,但是如果你想实现一个好的JTree选择框就比较难了,因为这里有选择问题、监听问题、选中后的父子关系等,这里主要是参考别人的实现写的.

先看一个简单的例子,从网上看到的,如图:

<!--[if gte vml 1]> <![endif]-->

它只是单纯的实现了树的选择框效果,写的很简单.

首先是TreeNode,我们扩展JavaTreeNode,添加了我们自己的选择属性:

publicclass CheckBoxTreeNode extends DefaultMutableTreeNode {

属性:

    /**

     * is node check

     */

privatebooleanisChecked = false;

然后就是Renderer,这里实现TreeCellRenderer,并继承了JCheckBox

publicclass CheckBoxTreeCellRenderer extends JCheckBox implements

       TreeCellRenderer {

然后实现接口的方法:

    @Override

   public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row,

           boolean hasFocus) {

取得TreeNode

       // get tree node

       CheckBoxTreeNode node = ((CheckBoxTreeNode) value);

       // set check box text

       setText(node.toString());

设置选择状态后返回:

       setSelected(false);

       returnthis;

然后是一个我们自己的JTree,它增加了鼠标监听,实现选择框的勾选效果:

publicclass CheckBoxTree extends JTree {

在构造函数里设置它的Renderer和监听:

    setCellRenderer(new CheckBoxTreeCellRenderer());

    addCheckingListener();

然后是处理监听:

addMouseListener(new MouseAdapter() {

    @Override

    publicvoid mousePressed(MouseEvent e) {

在监听里先取得选择的节点:

        int row = getRowForLocation(e.getX(), e.getY());

       TreePath treePath = getPathForRow(row);

       CheckBoxTreeNode node = ((CheckBoxTreeNode) treePath

           .getLastPathComponent());

然后设置选择状态:

       // if check , will uncheck.

       boolean checking = !node.isChecked();

       node.setChecked(checking);

当然这里可以做额外处理,例如选中节点时同时选择子节点或者父节点:

最后刷新:

       // repaint

       repaint();

然后就是使用了,和一般的JTree基本一致,只是节点是我们自己定义的Node.

    CheckBoxTree tree = new CheckBoxTree();

之后就和一个普通的JTree一样了.

到这里,简单的选择框树就完成了,它基本可以用,但是还是有一些问题的.

因为我们使用JCheckBox作为树的节点,导致我们只能呈现一个选择框和一个文本框的效果,其它复杂效果很难再实现了,简单说就是JCheckBox很难做效果

解决办法就是我们在做Renderer,使用JPanel继承,这样就可以实现更复杂的Node.

要通过鼠标监听和Repaint才能使树选择效果刷新.

通过解决问题一,我们可以在Renderer设置JCheckBox,这样就避免了刷新;同时我们可以额外实现一个单选效果.

选择模式简单(需要鼠标事件),验证数据单一(关联关系不好),封装性不好(使用达不到完全封闭)

这个问题就需要定义接口和数据结构了,本来想自己写呢,后来发现一个老外写了一个,很强大,比我写的好多了,就用它了.

先看我们简单解决12的例子,如图:

<!--[if gte vml 1]> <![endif]-->

TreeNode和前一个例子差不多,我们额外添加了一个选择模式的属性:

publicclass MyTreeNode extends DefaultMutableTreeNode {

两个属性,表示选择和选择模式:

    /** is select or not. */

    privatebooleanisSelected = false;

    /** select model. */

privateintselectionMode = 0;

在设置选择时,如果只允许单选的选择模式,我们设置其它不选择:

    publicvoid setSelected(boolean isSelected) {

        this.isSelected = isSelected;

        if ((selectionMode == TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION)

             && (children != null)) {

            Enumeration<?> enumTemp = children.elements();

            while (enumTemp.hasMoreElements()) {

                MyTreeNode node = (MyTreeNode) enumTemp.nextElement();

                node.setSelected(isSelected);

            }

        }

    }

然后就是Renderer,这里我们不继承JCheckBox,继承JPanel:

publicclass MyCheckRenderer extends JPanel implements TreeCellRenderer {

JPanel上我们放置了两个组件,当然也可以放置更复杂的:

    /** check box in tree node. */

    private JCheckBox checkBox = null;

    /** label text in tree node. */

    private TreeLabel labelText = null;

其中TreeLabel是我们自己写的:

privateclass TreeLabel extends JLabel {

我们为它添加了焦点状态和选择状态:

    /** is select. */

    privatebooleanisSelected = false;

    /** is have focus. */

    privatebooleanhasFocus = false;

然后复写它的方法和方法,使它的呈现和JTree一致:

    @Override

    public Dimension getPreferredSize() {

    @Override

    publicvoid paint(Graphics g) {

设置颜色和大小:

       g.setColor(UIManager

              .getColor("Tree.selectionBorderColor"));

       g.drawRect(imageOffset, 0, d.width - 1 - imageOffset,

              d.height - 1);

在类里我们实现TreeCellRenderer接口的方法:

    @Override

   public Component getTreeCellRendererComponent(JTree tree, Object value, boolean isSelected, boolean expanded, boolean leaf, int row,

           boolean hasFocus) {

设置JCheckBox的状态:

       checkBox.setSelected(((MyTreeNode) value).isSelected());

设置树节点显示:

       labelText.setFont(tree.getFont());

       labelText.setText(stringValue);

       labelText.setSelected(isSelected);

       labelText.setFocus(hasFocus);

然后复写JPanelgetPreferredSize方法和doLayout方法,使显示合理:

    /**

     * set select node's prefer size.

     */

    @Override

    public Dimension getPreferredSize() {

       Dimension d_check = checkBox.getPreferredSize();

       Dimension d_label = labelText.getPreferredSize();

       returnnew Dimension(d_check.width + d_label.width,

              (d_check.height < d_label.height ? d_label.height

                     : d_check.height));

    }

    /**

     * set tree select node layout.

     */

    @Override

    publicvoid doLayout() {

       Dimension d_check = checkBox.getPreferredSize();

       Dimension d_label = labelText.getPreferredSize();

       int y_check = 0;

       int y_label = 0;

       if (d_check.height < d_label.height) {

           y_check = (d_label.height - d_check.height) / 2;

       } else {

           y_label = (d_check.height - d_label.height) / 2;

       }

       checkBox.setLocation(0, y_check);

        checkBox.setBounds(0, y_check, d_check.width, d_check.height);

       labelText.setLocation(d_check.width, y_label);

       labelText.setBounds(d_check.width, y_label, d_label.width,

              d_label.height);

    }

最后是使用,和前面得差不多,先取得JTree,再设置Renderer,监听鼠标.

        JTree tree = new JTree();

        tree.setCellRenderer(new MyCheckRenderer());

       tree.addMouseListener(new NodeSelectionListener(tree));

处理鼠标监听:

        @Override

        publicvoid mouseClicked(MouseEvent e) {

设置选择:

            MyTreeNode node = (MyTreeNode) path.getLastPathComponent();

            boolean isSelected = !(node.isSelected());

            node.setSelected(isSelected);

            ((DefaultTreeModel) tree.getModel()).nodeChanged(node);

然后和普通的JTree一样使用了.

最后是问题三的解决,这个是一个老外写的,很不错,但是很复杂,如图:

<!--[if gte vml 1]> <![endif]-->

它实现了无关的选中、父选择子全选择、子选择父选择和子单选择父选择四种选择状态.

代码别人写的就不写了,写下它的大概思路:

首先它定义了一个事件: TreeCheckingEvent,这个事件是描绘选择关系和选择路径的,这样就简化了鼠标事件处理;然后是事件的监听器: TreeCheckingListener,它提供监听.

然后定义了一个数据模型:TreeCheckingMode,在模型里它提供了checkPathuncheckPathupdateCheckAfterChildrenInsertedupdateCheckAfterChildrenRemovedupdateCheckAfterStructureChanged的虚方法,供子类实现,这些实现就是树的选择状态的表示,当一个树的节点选择、取消选择、插入、删除和更新之后,节点选择状态的变化.

TreeCheckingModeSimpleTreeCheckingModePropagateTreeCheckingModePropagatePreservingCheckTreeCheckingModePropagatePreservingUncheckTreeCheckingMode四个实现类,代表了四种选择关联状态,通过实现父类的虚方法,当树选择变化或内容变化时,选择节点变化,这样我们的树就可以了四种选择逻辑了,当然你也可以继承TreeCheckingMode实现自己的选择逻辑.

然后还有一个RendererDefaultCheckboxTreeCellRenderer,继承JPanel,实现TreeCellRenderer,来渲染树的节点,这个和我上面写的基本一致.所以大家可以看到,UI最后还是做逻辑,UI呈现也就那么多,还是逻辑多而复杂.

然后是树的CheckModelTreeCheckingModelDefaultTreeCheckingModel,主要是处理树的数据变化和增删改;以及监听和选择状态的记录(树的Model我们还用,在它的基础上添加了新的选择Model,这样就分离了数据和选择状态).
最后是CheckboxTree,它继承JTree,设置ModelTreeModel,设置CheckModelTreeCheckingModel,设置ModeTreeCheckingMode,增加TreeCheckingListener监听,并提供了展开树等事件.

使用很简单,new出来直接使用就可以了,可以设置选择状态:

    tree.getCheckingModel().setCheckingMode(CheckingMode.PROPAGATE);

总之,这个树写的还是不错了,它自己实现了事件和数据模型,这样可以很自由的进行树数据的处理,建议如果大家做大项目的时候,比较常用的组件还是自己实现写,使用自己的事件处理和数据模型甚至UI,这样虽然麻烦,但可以做出更利于自己的效果(当然是很大很复杂的项目,小项目还不够费时间呢).

到此为止,关于树的就写完了,除了一个DND拖拽应该没有漏什么东西了,树的组件并不复杂, 方法不算太多,UI可以重写的也很少,Mdoel因为数据集简单也不复杂,数据处理最多也就是个递归,监听也就是鼠标和树选择、展开事件,因此一般树的UI和事件处理不是我们的重点,我在这里写的可能大多数项目都不会用到,(至少我很少用).因此对树的处理大多还是逻辑,主要是生成树、更新和删除节点.

分享到:
评论

相关推荐

    ExtJs4实现下拉树选择框ComboTree

    ### ExtJs4 实现下拉树选择框 ComboTree #### 概述 在现代Web应用开发中,ExtJS 是一个非常强大的JavaScript库,用于构建复杂的客户端应用程序。它提供了丰富的组件库,使得开发者能够轻松地创建出功能丰富且交互性...

    带选择框树

    "带选择框树"是一种常见的用户界面元素,广泛应用于数据管理、配置设置或文件系统浏览等场景。在软件开发中,这种数据结构结合了树形结构的层次展示和复选框的功能,允许用户以视觉友好的方式对节点进行批量选择、...

    树形框选择框

    破解注册,是否选中,转换句柄,关闭注册窗口_,被按下,被选中,加载,项目

    layui树形下拉菜单

    2. 多选功能:如果需要支持多选,可以调整树形组件的配置项,如设置`check: true`开启复选框功能。 3. 异步加载:对于数据量较大的场景,可以采用异步加载的方式,提高页面性能。 总结,layui的树形下拉菜单通过...

    自定义WPF TreeSelect、MultiTreeSelect ,树形选择框,多选树形选择框

    在WPF中实现这一特性,我们需要确保每个节点都有一个复选框,用户可以通过勾选复选框来选择或取消选择节点。这可能涉及到自定义TreeViewItem模板,以及处理选中状态的逻辑。 以下是一些关键步骤和知识点: 1. **...

    jQuery树形插件下拉列表选择框.zip

    《jQuery树形插件下拉列表选择框:深入解析与应用》 在现代网页开发中,用户界面的交互性与用户体验至关重要。jQuery作为一款强大的JavaScript库,为开发者提供了丰富的功能和简便的操作方式,大大简化了复杂的DOM...

    易语言枚举目录文件到树形框

    "树型框_取项目索引"和"树型框_取子项目索引"这两个函数用于获取当前选中或指定的节点在树形框中的位置,这对于处理用户的选择或者获取特定节点的数据很有帮助。"内部调用_取目录路径"是从树形框中获取当前选中目录...

    felx AdvancedDataGrid 多选框 单选框

    非常好用的 felx AdvancedDataGrid 多选框 单选框支持渲染器,不需改到AdvancedDataGrid 代码; 支持 xml 数据源的网上可查到一些, 但这个可是 支持 Array 类型数据源的。

    android树形选择框

    在Android开发中,"android树形选择框"通常指的是使用ExpandableListView来实现的一种界面组件。这个组件可以展示数据以树形结构的方式,允许用户进行多级展开和折叠,同时支持单选和多选功能。在给定的场景中,描述...

    js横向扩展树

    JavaScript中的横向扩展树是一种在网页中展示数据结构的交互式方式,特别适用于处理层次关系复杂的组织结构或文件系统。这种树形布局使得用户可以水平滚动查看节点,而不是传统的垂直展开和折叠。在这个“js横向扩展...

    树形穿梭框

    在树形穿梭框中,这种结构用于展示可选项目和已选择项目的层次。 2. **穿梭框组件**: 穿梭框是UI设计中的一种组件,通常包含两个列表,用户可以在两个列表之间移动条目。在树形穿梭框中,这两个列表显示为树状...

    带选择框_的树

    在IT领域,"带选择框_的树"(checkbox_tree)是一种常见的用户界面元素,它结合了树形结构和复选框的功能。这种组件通常用于数据层级结构的展示,允许用户进行多选操作,比如在文件管理器、权限设置或者组织架构等...

    jQuery树形下拉列表选择框代码

    《jQuery树形下拉列表选择框的实现与应用》 在网页开发中,为了提高用户体验,我们经常需要设计一些交互性更强的元素,比如树形下拉列表选择框。这种控件可以让用户在多级分类中进行选择,既节省空间,又能清晰地...

    无刷新二级联动树,数据库版,无刷新选择框,数据库版

    CSS样式可能用于美化选择框和整个联动树的外观。 总的来说,无刷新二级联动树是一种提高用户交互效率和体验的技术,它结合了前端的动态渲染和后端的数据库交互,实现了在不刷新页面的情况下,动态更新相关数据。在...

    易语言树形框加入加强版

    当用户改变树形框中节点的选择状态时,易语言树形框加强版会通知开发者,从而执行相应的逻辑代码。 6. **加载(Load)**: 在树形框中,加载通常指的是从数据源(如文件、数据库)中加载数据到树形结构中。易语言...

    一个基于Vue2后台管理系统demo无限级菜单下拉树形选择框

    该资源是一个基于Vue2技术栈的后台管理系统的演示项目,主要使用了Element UI库来构建用户界面,并结合了Vuex进行状态管理,Vue Router用于页面路由,Axios处理API请求,以及ECharts进行数据可视化。...

    基于Layui, 下拉选择框的多选解决方案

    本话题主要关注的是如何在Layui中实现下拉选择框的多选功能。在实际项目中,这种功能常用于让用户能够一次性选择多个选项,如在用户资料编辑、商品属性筛选等场景。 首先,Layui自身提供的`layui-form`组件中并未...

    基于layui实现树形穿梭框

    "基于layui实现树形穿梭框"是layui框架中的一个组件,用于构建交互式的树状结构选择器,常用于权限管理、数据分类选择等场景。下面将详细介绍这个知识点。 1. layui框架基础: layui是一个轻量级的前端框架,包含...

Global site tag (gtag.js) - Google Analytics