Swing自定义组件: JCheckTree

今天有一美女..说想要带JCheckBox的JTree.其实想一想..没什么不好实现的.
一个Renderer 一个Listener 应该可以搞定.. 自定义组件..关键就在交互事件上..
|----------------------------------------------------------------------------------------|
                     版权声明  版权所有 @chensiyu
            引用请注明来源 
www.blogjava.net/chensiyu04

            本文由  陈思羽 于 2011年8月24号 出品..
|----------------------------------------------------------------------------------------|



4个类.分别为:CheckTreeDemo,CheckTree,Node,CheckRenderer,CheckListener

从类名可以看出来. CheckTreeDemo是JFrame类 CheckTree是组件,Node是数据模型,CheckRenderer是CheckTree得渲染,CheckListener是CheckTree的事件


package tree;

import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

/**
 *
 * 
@author chensiyu
 * @createDate 2011/8/24
 
*/
public class CheckTreeDemo extends JPanel {

    
private CheckTree checkTree;
    
    
public CheckTreeDemo() {
        init();
    }
    
    
private void init(){
        setLayout(
new BorderLayout());
        
        Node rootNode 
= new Node("Root");
        Node []nodes 
= new Node[10];
        
for(int i = 0;i <nodes.length;i++){
            Node node 
= new Node("Node-"+i);
            rootNode.add(node);
        }
        checkTree 
= new CheckTree(rootNode);
        add(checkTree,BorderLayout.CENTER);
        
    }

    
public static void main(String[] args) {
        
final JFrame frame = new JFrame();
        frame.setTitle(
"CheckTree");
        frame.setLayout(
new BorderLayout());
        frame.setSize(
200400);
        frame.getContentPane().add(
new CheckTreeDemo());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        SwingUtilities.invokeLater(
new Runnable() {

            @Override
            
public void run() {
                frame.setVisible(
true);
            }
        });
    }
}


package tree;

import javax.swing.JTree;
import javax.swing.tree.TreeNode;

/**
 *
 * 
@author chensiyu
 * @createDate 2011/8/24
 
*/
public class CheckTree extends JTree {

    
private CheckRenderer checkRenderer;
    
private CheckListener checkListener;

    
public CheckTree() {
        init();
    }

    
public CheckTree(TreeNode node) {
        
super(node);
        init();
    }

    
private void init() {
        checkRenderer 
= new CheckRenderer();
        checkListener 
= new CheckListener();
        setCellRenderer(checkRenderer);
        addMouseListener(checkListener);
    }
}

package tree;

import javax.swing.tree.DefaultMutableTreeNode;

/**
 *
 * 
@author chensiyu
 * @createDate 2011/8/24
 
*/
public class Node extends DefaultMutableTreeNode{

    
private String name = "";
    
private boolean selected = false;

    
public Node(String name){
        
super(name);
        setName(name);
    }
    
public String getName() {
        
return name;
    }

    
public void setName(String name) {
        
this.name = name;
    }

    
public boolean isSelected() {
        
return selected;
    }

    
public void setSelected(boolean selected) {
        
this.selected = selected;
    }
}

package tree;

/**
 *
 * 
@author chensiyu
 * @createDate 2011/8/24
 
*/
import java.awt.*;
import javax.swing.*;
import javax.swing.tree.*;

class CheckRenderer extends JPanel implements TreeCellRenderer {

    
protected static JCheckBox check;
    
protected JLabel label;
    
private static Rectangle checkBounds;

    
public CheckRenderer() {
        setLayout(
null);
        add(check 
= new JCheckBox());
        add(label 
= new JLabel(""));
        check.setBackground(UIManager.getColor(
"Tree.textBackground"));
        label.setForeground(UIManager.getColor(
"Tree.textForeground"));
    }

    @Override
    
public Component getTreeCellRendererComponent(JTree tree, Object value,
            
boolean isSelected, boolean expanded, boolean leaf, int row,
            
boolean hasFocus) {
        String stringValue 
= tree.convertValueToText(value, isSelected,
                expanded, leaf, row, hasFocus);
        setEnabled(tree.isEnabled());
        label.setFont(tree.getFont());
        label.setText(stringValue);
        setBackground(tree.getBackground());
        setForeground(tree.getForeground());
        
        
if(value instanceof Node){
            Node node 
= (Node)value;
            check.setSelected(node.isSelected());
        }
        
return this;
    }

    @Override
    
public Dimension getPreferredSize() {
        Dimension d_check 
= check.getPreferredSize();
        Dimension d_label 
= label.getPreferredSize();
        
return new Dimension(d_check.width + d_label.width,
                (d_check.height 
< d_label.height ? d_label.height
                : d_check.height));
    }

    @Override
    
public void doLayout() {
        Dimension d_check 
= check.getPreferredSize();
        Dimension d_label 
= label.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;
        }
        check.setLocation(
0, y_check);
        check.setBounds(
0, y_check, d_check.width, d_check.height);
        label.setLocation(d_check.width, y_label);
        label.setBounds(d_check.width, y_label, d_label.width, d_label.height);
        
if (checkBounds == null){
            checkBounds 
= check.getBounds();
        }
                
    }
    
    
public static Rectangle getCheckBoxRectangle() {
        
ifnull == checkBounds )
            
return new Rectangle(0,0,0,0);
        
return (Rectangle) checkBounds.clone();
    }
}

package tree;

import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JTree;
import javax.swing.tree.TreePath;

/**
 *
 * 
@author chensiyu
 * @createDate 2011/8/24
 
*/
class CheckListener extends MouseAdapter {

    
public CheckListener() {
    }

    @Override
    
public void mouseClicked(MouseEvent e) {
        JTree tree 
= (JTree) e.getSource();
        Point p 
= e.getPoint();
        
int x = e.getX();
        
int y = e.getY();
        
int row = tree.getRowForLocation(x, y);
        TreePath path 
= tree.getPathForRow(row);

        
if (null == path) {
            
return;
        }

        Object component 
= path.getLastPathComponent();
        
if (null == component) {
            
return;
        }

        
if (component instanceof Node) {
            Rectangle chRect 
= CheckRenderer.getCheckBoxRectangle();
            Rectangle rowRect 
= tree.getPathBounds(path);
            chRect.setLocation(chRect.x 
+ rowRect.x, chRect.y + rowRect.y);
            
if (e.getClickCount() == 1 && chRect.contains(p)) {
                Node node 
= (Node)component;
                node.setSelected(
!node.isSelected());
                tree.repaint();
            }
        }
    }
}

posted on 2011-08-24 18:08 相信 阅读(1934) 评论(2)  编辑  收藏 所属分类: Swing文章

评论

# re: Swing自定义组件: JCheckTree[未登录] 2011-08-25 08:43 greatghoul

请问为什么要这样做,而不是直接frame.setVisible(true)呢?
SwingUtilities.invokeLater(new Runnable() {

@Override
public void run() {
frame.setVisible(true);
}
});  回复  更多评论   

# re: Swing自定义组件: JCheckTree 2011-08-25 09:57 相信

@greatghoul

关于这个问题.你可以参考 JDK API 里 关于 Swing 的线程策略 .

简单的说.
通常 Swing 不是线程安全的。除非另行说明,否则所有 Swing 组件及相关类都必须在事件调度线程上访问。  回复  更多评论   


只有注册用户登录后才能发表评论。


网站导航:
 
<2018年12月>
2526272829301
2345678
9101112131415
16171819202122
23242526272829
303112345

导航

统计

公告

不显示applet

常用链接

留言簿(16)

我参与的团队

随笔档案

文章分类

文章档案

新闻档案

相册

swingchina 专业搞Swing的网站

搜索

最新评论

阅读排行榜

评论排行榜