`
icefire
  • 浏览: 123416 次
  • 性别: Icon_minigender_1
  • 来自: 深圳、重庆
社区版块
存档分类
最新评论

swing tree checkbox

阅读更多
swing标准库,实在有些简陋,很多显然的需求却无法满足,jdk5以前的版本,连表格列的排序功能都没有,swing最大的毛病也在这。最近学习python,同时也学习了一些GUI库,发现基本上tree都支持多列显示,在swing里,你就必须找第三方库了。

废话不说了,还是说说本来的需求。
我是需要在tree的node上显示checkbox。要满足这个需求,最明显的就有两个方法。
1 实现TreeCellRenderer接口,JCheckBox来做渲染,这样就可以,不过这有个问题,就是感观上和默认node实现,有很多差异,一些如选中,焦点,背景色等等,这些在DefaultTreeCellRenderer之类里有很多关于此类的考虑,如果自己再考虑,写一遍,似乎不合适。

2 用icon图片来代替,这是个方法,但是我有个期望是,希望checkbox能跟随look&feel做切换,所以期望是系统采用各个look&feel自己的chekbox。

大家知道,swing是自己画的,这样的话,那么icon也是,也就是说,我可以借用JCheckBox的渲染来渲染treenode的icon。最初想法是,直接用JCheckBox的icon放到DefaultTreeCellRenderer的icon里,但却报错,原因是DefaultTreeCellRenderer父类是JLabel,每个组件的icon的渲染,与组件相关的model是紧密联系的。

void paintIcon(Component c, Graphics g, int x, int y);


不同组件的icon不能直接使用。那么怎么办呢?其实也很简单,保证paintIcon的Component参数与icon一致就行了。

具体代码:

public class CheckboxTreeNodeRenderer extends DefaultTreeCellRenderer implements
		TreeCellRenderer {

	private static final long serialVersionUID = 1L;

	private JCheckBox checkbox = new JCheckBox();

	private Icon checkboxIcon = UIManager.getIcon("CheckBox.icon");
	
	private ProxyCheckBoxIcon proxyIcon = new ProxyCheckBoxIcon();
	
	private Font normal;
	
	private Font disabled;

	@SuppressWarnings("unchecked")
	public CheckboxTreeNodeRenderer() {
		normal = getFont().deriveFont(Font.PLAIN);
		Map<TextAttribute, Object> attrs = (Map<TextAttribute, Object>) normal.getAttributes();
		attrs.put(TextAttribute.STRIKETHROUGH, TextAttribute.STRIKETHROUGH_ON);
		//attrs.put(TextAttribute.FONT, getFont().deriveFont(Font.ITALIC));
		disabled = getFont().deriveFont(attrs);
	}

	public Component getTreeCellRendererComponent(JTree tree, Object value,
			boolean selected, boolean expanded, boolean leaf, int row,
			boolean hasFocus) {
		super.getTreeCellRendererComponent(tree, value, selected, expanded,
				leaf, row, hasFocus);
		if (value instanceof CheckboxTreeNode) {
			CheckboxTreeNode ctn = (CheckboxTreeNode) value;
			checkbox.setSelected(ctn.isChecked());
			setIcon(proxyIcon);
			if (ctn.isChecked()) {
				setFont(disabled);
				if (!selected)
					setForeground(Color.GRAY);
			} else {
				setFont(normal);
				//setForeground(Color.BLACK);
			}
		} else {
			setFont(normal);
		}
		return this;
	}
	
	private class ProxyCheckBoxIcon implements Icon, Serializable {
		
		private static final long serialVersionUID = 1L;

		@Override
		public void paintIcon(Component c, Graphics g, int x, int y) {
			checkboxIcon.paintIcon(checkbox, g, x, y);
		}

		@Override
		public int getIconWidth() {
			return checkboxIcon.getIconWidth();
		}

		@Override
		public int getIconHeight() {
			return checkboxIcon.getIconHeight();
		}
		
	}

}


以上代码除了实现checbox外,还实现了选中时,把显示文字增加删除线。(反正没找到简单方法,但在QT里很简单)。

下面是选中节点的判断监听类:

public class CheckboxNodeCheckedListener extends MouseAdapter implements MouseListener {

	@Override
	public void mousePressed(MouseEvent e) {
		JTree tree = (JTree) e.getSource();
		TreePath clickedPath = tree.getPathForLocation(e.getX(), e.getY());
		
		if (e.getClickCount() == 1) {
			
			if (clickedPath != null && !tree.isEditing()) {
				Object node = clickedPath.getLastPathComponent();
				
				if (node instanceof CheckboxTreeNode) {
					CheckboxTreeNode treeNode = (CheckboxTreeNode) node;
					DefaultTreeModel model = (DefaultTreeModel) tree.getModel();
					
					TreeNode[] currPath = model.getPathToRoot(treeNode);
					Rectangle rec = tree.getPathBounds(new TreePath(currPath));
					
					if (e.getX() - rec.getX() <= 13) { // 默认为 13x13大小
						treeNode.setChecked(!treeNode.isChecked());
						model.nodeChanged(treeNode);
					}
				}
			}
		}
	}
}

0
0
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics