<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    zeyuphoenix

    愿我愛的人快樂,愿愛我的人快樂,為了這些,我愿意不快樂.

    樹(選擇框)

    先是春游然后又開始忙了,都沒時間寫了,不爽.

    JTree的選擇框其實也是Renderer的一種表現,單純實現效果的話很簡單,只需要設置Renderer就可以了,但是如果你想實現一個好的JTree選擇框就比較難了,因為這里有選擇問題、監聽問題、選中后的父子關系等,這里主要是參考別人的實現寫的.

    先看一個簡單的例子,從網上看到的,如圖:

    它只是單純的實現了樹的選擇框效果,寫的很簡單.

    首先是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的例子,如圖:

    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一樣使用了.

    最后是問題三的解決,這個是一個老外寫的,很不錯,但是很復雜,如圖:

    它實現了無關的選中、父選擇子全選擇、子選擇父選擇和子單選擇父選擇四種選擇狀態.

    代碼別人寫的就不寫了,寫下它的大概思路:

    首先它定義了一個事件: TreeCheckingEvent,這個事件是描繪選擇關系和選擇路徑的,這樣就簡化了鼠標事件處理;然后是事件的監聽器: TreeCheckingListener,它提供監聽.

    然后定義了一個數據模型:TreeCheckingMode,在模型里它提供了checkPath、uncheckPathupdateCheckAfterChildrenInserted、updateCheckAfterChildrenRemovedupdateCheckAfterStructureChanged的虛方法,供子類實現,這些實現就是樹的選擇狀態的表示,當一個樹的節點選擇、取消選擇、插入、刪除和更新之后,節點選擇狀態的變化.

    TreeCheckingModeSimpleTreeCheckingMode、PropagateTreeCheckingMode、PropagatePreservingCheckTreeCheckingMode、PropagatePreservingUncheckTreeCheckingMode四個實現類,代表了四種選擇關聯狀態,通過實現父類的虛方法,當樹選擇變化或內容變化時,選擇節點變化,這樣我們的樹就可以了四種選擇邏輯了,當然你也可以繼承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和事件處理不是我們的重點,我在這里寫的可能大多數項目都不會用到,(至少我很少用).因此對樹的處理大多還是邏輯,主要是生成樹、更新和刪除節點.

    posted on 2010-04-27 21:54 zeyuphoenix 閱讀(2728) 評論(0)  編輯  收藏 所屬分類: JTree的使用

    導航

    <2010年4月>
    28293031123
    45678910
    11121314151617
    18192021222324
    2526272829301
    2345678

    統計

    常用鏈接

    留言簿(52)

    隨筆分類

    隨筆檔案

    搜索

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 日韩精品无码免费一区二区三区| 精品亚洲福利一区二区| 99精品免费视品| 亚洲色婷婷六月亚洲婷婷6月| 国产无限免费观看黄网站| 久久亚洲AV永久无码精品| a级毛片在线视频免费观看| 亚洲乱码精品久久久久..| 在线观看黄片免费入口不卡| 亚洲国产第一站精品蜜芽| 99re免费99re在线视频手机版| 亚洲午夜在线电影| 999国内精品永久免费观看| 亚洲中文无码永久免费| 热99re久久精品精品免费| 无码 免费 国产在线观看91| 国产亚洲真人做受在线观看| 中文字幕免费在线观看| 中文字幕亚洲综合久久综合| 国产精品免费电影| 男人天堂免费视频| ASS亚洲熟妇毛茸茸PICS| mm1313亚洲精品无码又大又粗| 最近国语视频在线观看免费播放| 亚洲一区二区三区日本久久九| 国产情侣激情在线视频免费看| 亚洲国产精品无码久久九九大片| 免费观看午夜在线欧差毛片 | 亚洲精品国产suv一区88| 亚洲成A∨人片天堂网无码| 男人天堂免费视频| 亚洲人成电影院在线观看| 免费va人成视频网站全| 日韩电影免费在线观看| 亚洲欧美日韩中文无线码| 色噜噜亚洲精品中文字幕| 午夜宅男在线永久免费观看网| 日本一区二区三区在线视频观看免费| 亚洲AV日韩AV永久无码免下载| 免费看a级黄色片| 日韩视频在线观看免费|