在項目中需要使用下拉一棵樹來選擇的空間,參考了下別人的自己改進了不少,使用方法就是:
TreeComboBox tcb = new TreeComboBox();就可以建立一個最簡單的下拉樹了,下拉的tree就是最原始的tree。
TreeComboBox的原始碼如下:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.IllegalComponentStateException;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionAdapter;
import java.awt.event.MouseMotionListener;
import javax.swing.BorderFactory;
import javax.swing.DefaultListCellRenderer;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.MenuSelectionManager;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.plaf.ComboBoxUI;
import javax.swing.plaf.basic.ComboPopup;
import javax.swing.plaf.metal.MetalComboBoxUI;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeCellRenderer;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import com.sun.java.swing.plaf.motif.MotifComboBoxUI;
import com.sun.java.swing.plaf.windows.WindowsComboBoxUI;
public class TreeComboBox extends JComboBox {
/**
* 顯示用的樹
*/
private JTree tree;
public TreeComboBox() {
this(new JTree());
}
public TreeComboBox(JTree tree) {
this(tree, null);
}
public TreeComboBox(JTree tree, TreeCellRenderer treeCellRenderer){
this(tree, treeCellRenderer, false);
}
/**
* 不顯示根節點的TreeComboBox
* @param tree
* @param treeCellRenderer
* @param showRoot
*/
public TreeComboBox(JTree tree, TreeCellRenderer treeCellRenderer, boolean showRoot){
this.setTree(tree);
tree.setCellRenderer(treeCellRenderer);
if (!showRoot){
tree.expandPath(new TreePath(tree.getModel().getRoot()));
tree.setRootVisible(false);
}
}
/**
* 設定樹
* @param tree JTree
*/
public void setTree(JTree tree) {
this.tree = tree;
if (tree != null) {
this.setSelectedItem(tree.getSelectionPath());
this.setRenderer(new TreeComboBoxRenderer());
}
this.updateUI();
}
/**
* 取得樹
* @return JTree
*/
public JTree getTree() {
return tree;
}
/**
* 設定當前選擇的樹路徑
* @param o Object
*/
public void setSelectedItem(Object o) {
this.tree.setSelectionPath((TreePath) o);
this.getModel().setSelectedItem(o);
}
/**
* 獲得當前選中的節點的值
* @return o Object
*/
public Object getSelectedObject(){
TreePath treePath = (TreePath)this.getSelectedItem();
if (treePath == null){
return null;
}
DefaultMutableTreeNode node = (DefaultMutableTreeNode)treePath.getLastPathComponent();
return node.getUserObject();
}
public void updateUI() {
ComboBoxUI cui = (ComboBoxUI) UIManager.getUI(this);
if (cui instanceof MetalComboBoxUI) {
cui = new MetalTreeComboBoxUI();
} else if (cui instanceof MotifComboBoxUI) {
cui = new MotifTreeComboBoxUI();
} else if (cui instanceof WindowsComboBoxUI) {
cui = new WindowsTreeComboBoxUI();
} else {
cui = new FRTreeComboBoxUI();
}
setUI(cui);
}
// richer:皮膚
class FRTreeComboBoxUI extends TinyComboBoxUI {
protected ComboPopup createPopup() {
return new TreePopup(comboBox);
}
}
class MetalTreeComboBoxUI extends MetalComboBoxUI {
protected ComboPopup createPopup() {
return new TreePopup(comboBox);
}
}
class WindowsTreeComboBoxUI extends WindowsComboBoxUI {
protected ComboPopup createPopup() {
return new TreePopup(comboBox);
}
}
class MotifTreeComboBoxUI extends MotifComboBoxUI {
protected ComboPopup createPopup() {
return new TreePopup(comboBox);
}
}
private class TreeComboBoxRenderer extends DefaultListCellRenderer {
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
if (value != null) {
TreePath path = (TreePath) value;
TreeNode node = (TreeNode) path.getLastPathComponent();
value = node;
TreeCellRenderer treeCellRenderer = tree.getCellRenderer();
JLabel lb = (JLabel) treeCellRenderer.getTreeCellRendererComponent(tree, value, isSelected, false, node.isLeaf(), index, cellHasFocus);
return lb;
}
return super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
}
}
}
/*
* richer:彈出部分
*/
class TreePopup extends JPopupMenu implements ComboPopup {
protected TreeComboBox comboBox;
protected JScrollPane scrollPane;
protected MouseMotionListener mouseMotionListener;
protected MouseListener mouseListener;
private MouseListener treeSelectListener = new MouseAdapter() {
public void mouseReleased(MouseEvent e) {
JTree tree = (JTree)e.getSource();
TreePath treePath = tree.getPathForLocation(e.getPoint().x, e.getPoint().y);
if (treePath == null){
return;
}
DefaultMutableTreeNode node = (DefaultMutableTreeNode)treePath.getLastPathComponent();
// richer:只有是樹葉才選中這個節點,這裡可以根據需要自己定義
if (node.isLeaf()){
comboBox.setSelectedItem(treePath);
togglePopup();
MenuSelectionManager.defaultManager().clearSelectedPath();
}
}
};
public TreePopup(JComboBox comboBox) {
this.comboBox = (TreeComboBox) comboBox;
this.setBorder(BorderFactory.createLineBorder(Color.black));
this.setLayout(new BorderLayout());
this.setLightWeightPopupEnabled(comboBox.isLightWeightPopupEnabled());
JTree tree = this.comboBox.getTree();
if (tree != null) {
this.scrollPane = new JScrollPane(tree);
this.scrollPane.setBorder(null);
this.add(this.scrollPane, BorderLayout.CENTER);
tree.addMouseListener(this.treeSelectListener);
}
}
public void show() {
this.updatePopup();
try {
this.show(comboBox, 0, comboBox.getHeight());
} catch (IllegalComponentStateException e) {
//richer:這裡有可能會拋出一個異常,可以不用處理
}
this.comboBox.getTree().requestFocus();
}
public void hide() {
this.setVisible(false);
this.comboBox.firePropertyChange("popupVisible", true, false);
}
protected JList list = new JList();
public JList getList() {
return list;
}
public MouseMotionListener getMouseMotionListener() {
if (mouseMotionListener == null) {
mouseMotionListener = new MouseMotionAdapter() {
};
}
return mouseMotionListener;
}
public KeyListener getKeyListener() {
return null;
}
public void uninstallingUI() {
}
/**
* Implementation of ComboPopup.getMouseListener().
*
* @return a <code>MouseListener</code> or null
* @see ComboPopup#getMouseListener
*/
public MouseListener getMouseListener() {
if (mouseListener == null) {
mouseListener = new InvocationMouseHandler();
}
return mouseListener;
}
protected void togglePopup() {
if (this.isVisible()) {
this.hide();
} else {
this.show();
}
}
protected void updatePopup() {
this.setPreferredSize(new Dimension(this.comboBox.getSize().width, 120));
Object selectedObj = this.comboBox.getSelectedItem();
if (selectedObj != null) {
TreePath tp = (TreePath) selectedObj;
((TreeComboBox) this.comboBox).getTree().setSelectionPath(tp);
}
}
protected class InvocationMouseHandler extends MouseAdapter {
public void mousePressed(MouseEvent e) {
if (!SwingUtilities.isLeftMouseButton(e) || !comboBox.isEnabled()) {
return;
}
if (comboBox.isEditable()) {
Component comp = comboBox.getEditor().getEditorComponent();
if ((!(comp instanceof JComponent)) || ((JComponent) comp).isRequestFocusEnabled()) {
comp.requestFocus();
}
} else if (comboBox.isRequestFocusEnabled()) {
comboBox.requestFocus();
}
togglePopup();
}
}
}