<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,我们扩展Java的TreeNode,添加了我们自己的选择属性:
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,这样就避免了刷新;同时我们可以额外实现一个单选效果.
选择模式简单(需要鼠标事件),验证数据单一(关联关系不好),封装性不好(使用达不到完全封闭)
这个问题就需要定义接口和数据结构了,本来想自己写呢,后来发现一个老外写了一个,很强大,比我写的好多了,就用它了.
先看我们简单解决1和2的例子,如图:
<!--[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);
然后复写JPanel的getPreferredSize方法和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,在模型里它提供了checkPath、uncheckPath、updateCheckAfterChildrenInserted、updateCheckAfterChildrenRemoved和updateCheckAfterStructureChanged的虚方法,供子类实现,这些实现就是树的选择状态的表示,当一个树的节点选择、取消选择、插入、删除和更新之后,节点选择状态的变化.
TreeCheckingMode有SimpleTreeCheckingMode、PropagateTreeCheckingMode、PropagatePreservingCheckTreeCheckingMode、PropagatePreservingUncheckTreeCheckingMode四个实现类,代表了四种选择关联状态,通过实现父类的虚方法,当树选择变化或内容变化时,选择节点变化,这样我们的树就可以了四种选择逻辑了,当然你也可以继承TreeCheckingMode实现自己的选择逻辑.
然后还有一个Renderer类DefaultCheckboxTreeCellRenderer,继承JPanel,实现TreeCellRenderer,来渲染树的节点,这个和我上面写的基本一致.所以大家可以看到,做UI最后还是做逻辑,UI呈现也就那么多,还是逻辑多而复杂.
然后是树的CheckModel类TreeCheckingModel和DefaultTreeCheckingModel,主要是处理树的数据变化和增删改;以及监听和选择状态的记录(树的Model我们还用,在它的基础上添加了新的选择Model,这样就分离了数据和选择状态).
最后是CheckboxTree,它继承JTree,设置Model是TreeModel,设置CheckModel是TreeCheckingModel,设置Mode是TreeCheckingMode,增加TreeCheckingListener监听,并提供了展开树等事件.
使用很简单,new出来直接使用就可以了,可以设置选择状态:
tree.getCheckingModel().setCheckingMode(CheckingMode.PROPAGATE);
总之,这个树写的还是不错了,它自己实现了事件和数据模型,这样可以很自由的进行树数据的处理,建议如果大家做大项目的时候,比较常用的组件还是自己实现写,使用自己的事件处理和数据模型甚至UI,这样虽然麻烦,但可以做出更利于自己的效果(当然是很大很复杂的项目,小项目还不够费时间呢).
到此为止,关于树的就写完了,除了一个DND拖拽应该没有漏什么东西了,树的组件并不复杂, 方法不算太多,UI可以重写的也很少,Mdoel因为数据集简单也不复杂,数据处理最多也就是个递归,监听也就是鼠标和树选择、展开事件,因此一般树的UI和事件处理不是我们的重点,我在这里写的可能大多数项目都不会用到,(至少我很少用).因此对树的处理大多还是逻辑,主要是生成树、更新和删除节点.
分享到:
相关推荐
### ExtJs4 实现下拉树选择框 ComboTree #### 概述 在现代Web应用开发中,ExtJS 是一个非常强大的JavaScript库,用于构建复杂的客户端应用程序。它提供了丰富的组件库,使得开发者能够轻松地创建出功能丰富且交互性...
"带选择框树"是一种常见的用户界面元素,广泛应用于数据管理、配置设置或文件系统浏览等场景。在软件开发中,这种数据结构结合了树形结构的层次展示和复选框的功能,允许用户以视觉友好的方式对节点进行批量选择、...
破解注册,是否选中,转换句柄,关闭注册窗口_,被按下,被选中,加载,项目
2. 多选功能:如果需要支持多选,可以调整树形组件的配置项,如设置`check: true`开启复选框功能。 3. 异步加载:对于数据量较大的场景,可以采用异步加载的方式,提高页面性能。 总结,layui的树形下拉菜单通过...
在WPF中实现这一特性,我们需要确保每个节点都有一个复选框,用户可以通过勾选复选框来选择或取消选择节点。这可能涉及到自定义TreeViewItem模板,以及处理选中状态的逻辑。 以下是一些关键步骤和知识点: 1. **...
《jQuery树形插件下拉列表选择框:深入解析与应用》 在现代网页开发中,用户界面的交互性与用户体验至关重要。jQuery作为一款强大的JavaScript库,为开发者提供了丰富的功能和简便的操作方式,大大简化了复杂的DOM...
"树型框_取项目索引"和"树型框_取子项目索引"这两个函数用于获取当前选中或指定的节点在树形框中的位置,这对于处理用户的选择或者获取特定节点的数据很有帮助。"内部调用_取目录路径"是从树形框中获取当前选中目录...
非常好用的 felx AdvancedDataGrid 多选框 单选框支持渲染器,不需改到AdvancedDataGrid 代码; 支持 xml 数据源的网上可查到一些, 但这个可是 支持 Array 类型数据源的。
在Android开发中,"android树形选择框"通常指的是使用ExpandableListView来实现的一种界面组件。这个组件可以展示数据以树形结构的方式,允许用户进行多级展开和折叠,同时支持单选和多选功能。在给定的场景中,描述...
JavaScript中的横向扩展树是一种在网页中展示数据结构的交互式方式,特别适用于处理层次关系复杂的组织结构或文件系统。这种树形布局使得用户可以水平滚动查看节点,而不是传统的垂直展开和折叠。在这个“js横向扩展...
在树形穿梭框中,这种结构用于展示可选项目和已选择项目的层次。 2. **穿梭框组件**: 穿梭框是UI设计中的一种组件,通常包含两个列表,用户可以在两个列表之间移动条目。在树形穿梭框中,这两个列表显示为树状...
在IT领域,"带选择框_的树"(checkbox_tree)是一种常见的用户界面元素,它结合了树形结构和复选框的功能。这种组件通常用于数据层级结构的展示,允许用户进行多选操作,比如在文件管理器、权限设置或者组织架构等...
《jQuery树形下拉列表选择框的实现与应用》 在网页开发中,为了提高用户体验,我们经常需要设计一些交互性更强的元素,比如树形下拉列表选择框。这种控件可以让用户在多级分类中进行选择,既节省空间,又能清晰地...
CSS样式可能用于美化选择框和整个联动树的外观。 总的来说,无刷新二级联动树是一种提高用户交互效率和体验的技术,它结合了前端的动态渲染和后端的数据库交互,实现了在不刷新页面的情况下,动态更新相关数据。在...
当用户改变树形框中节点的选择状态时,易语言树形框加强版会通知开发者,从而执行相应的逻辑代码。 6. **加载(Load)**: 在树形框中,加载通常指的是从数据源(如文件、数据库)中加载数据到树形结构中。易语言...
该资源是一个基于Vue2技术栈的后台管理系统的演示项目,主要使用了Element UI库来构建用户界面,并结合了Vuex进行状态管理,Vue Router用于页面路由,Axios处理API请求,以及ECharts进行数据可视化。...
本话题主要关注的是如何在Layui中实现下拉选择框的多选功能。在实际项目中,这种功能常用于让用户能够一次性选择多个选项,如在用户资料编辑、商品属性筛选等场景。 首先,Layui自身提供的`layui-form`组件中并未...
"基于layui实现树形穿梭框"是layui框架中的一个组件,用于构建交互式的树状结构选择器,常用于权限管理、数据分类选择等场景。下面将详细介绍这个知识点。 1. layui框架基础: layui是一个轻量级的前端框架,包含...