簡體   English   中英

具有自定義打開/關閉圖標的自定義JTree單元格渲染器

[英]Custom JTree cell renderers with custom open/close icons

我想創建一個自定義JTree,它的節點是JProgressBar我的工作就像我想要的一樣

在此輸入圖像描述

但是你會注意到它缺少它的打開/關閉圖標,我也希望它是一個自定義+/-圖標而不是標准的可擴展文件夾。 不完全確定我做錯了什么(只是在美化代碼之前開發概念)

package com.testingarea;

import java.awt.Component;
import java.awt.Graphics;
import java.util.HashMap;

import javax.swing.BoxLayout;
import javax.swing.Icon;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.UIManager;
import javax.swing.plaf.IconUIResource;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeCellRenderer;

public class TestTrees {  

  public static void main(String args[]) {  
    JFrame frame = new JFrame("Tree");  
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    ProgressTreeCellRenderer renderer = new ProgressTreeCellRenderer();

    JProgressBar progressBar = new JProgressBar(0, 100);
    progressBar.setValue(50);
    progressBar.setStringPainted(true);
    DefaultMutableTreeNode top =
        new DefaultMutableTreeNode(progressBar);
    renderer.getNodeMap().put(top, new ProgressTreeCellRenderer2(progressBar));

    createNodes(top, renderer);
    DefaultTreeModel model = new DefaultTreeModel(top);    

    JTree tree = new JTree(model);
    tree.setCellRenderer(renderer);
    JScrollPane pane = new JScrollPane(tree);
    tree.clearSelection();
    frame.getContentPane().add(pane);  
    frame.setSize(250, 250);  
    frame.setVisible(true);  
  }

  private static void createNodes(DefaultMutableTreeNode top, ProgressTreeCellRenderer renderer) {
    JProgressBar progressBar1 = new JProgressBar(0, 100);
    progressBar1.setValue(25);
    progressBar1.setStringPainted(true);
    DefaultMutableTreeNode one =
        new DefaultMutableTreeNode(progressBar1);
    top.add(one);
    renderer.getNodeMap().put(one, new ProgressTreeCellRenderer2(progressBar1));

    JProgressBar progressBar2 = new JProgressBar(0, 100);
    progressBar2.setValue(25);
    progressBar2.setStringPainted(true);
    DefaultMutableTreeNode two =
        new DefaultMutableTreeNode(progressBar2);
    top.add(two);
    renderer.getNodeMap().put(two, new ProgressTreeCellRenderer2(progressBar2));
  }

}

@SuppressWarnings("serial")
class ProgressTreeCellRenderer extends DefaultTreeCellRenderer {

  private HashMap<DefaultMutableTreeNode, ProgressTreeCellRenderer2> nodeMap = new HashMap<DefaultMutableTreeNode, ProgressTreeCellRenderer2>();

  @Override
  public Component getTreeCellRendererComponent(JTree tree, final Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
    if(nodeMap.containsKey(value)) {
      //I was expecting this to work, alas it does not?
      setClosedIcon(new IconUIResource(new NodeIcon('+')));
      setOpenIcon(new IconUIResource(new NodeIcon('-')));
      return nodeMap.get(value).getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus);
    }
    return super.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus);
  }

  public HashMap<DefaultMutableTreeNode, ProgressTreeCellRenderer2> getNodeMap() {
    return nodeMap;
  }
}

class ProgressTreeCellRenderer2 implements TreeCellRenderer {

  private JProgressBar _progressBar;
  private DefaultTreeCellRenderer _defaultRenderer;

  public ProgressTreeCellRenderer2(JProgressBar progressBar) {
    _progressBar = progressBar;
    _defaultRenderer = new DefaultTreeCellRenderer();
  }

  @Override
  public Component getTreeCellRendererComponent(JTree tree, final Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
    Component render = _defaultRenderer.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus);
    final JPanel panel = new JPanel();
    BoxLayout layout = new BoxLayout(panel, BoxLayout.X_AXIS);

    panel.setLayout(layout);
    panel.add(_progressBar);
    render = panel;    
    return render;
  }

}

class NodeIcon implements Icon {

  private static final int SIZE = 9;

  private char type;

  public NodeIcon(char type) {
    this.type = type;
  }

  public void paintIcon(Component c, Graphics g, int x, int y) {
    g.setColor(UIManager.getColor("Tree.background"));
    g.fillRect(x, y, SIZE - 1, SIZE - 1);

    g.setColor(UIManager.getColor("Tree.hash").darker());
    g.drawRect(x, y, SIZE - 1, SIZE - 1);

    g.setColor(UIManager.getColor("Tree.foreground"));
    g.drawLine(x + 2, y + SIZE / 2, x + SIZE - 3, y + SIZE / 2);
    if (type == '+') {
      g.drawLine(x + SIZE / 2, y + 2, x + SIZE / 2, y + SIZE - 3);
    }
  }

  public int getIconWidth() {
    return SIZE;
  }

  public int getIconHeight() {
    return SIZE;
  }
}

如果ProgressTreeCellRenderer調用setClosedIconsetOpenIcon沒有效果,則返回從nodeMap檢索的另一個渲染器。 您必須在ProgressTreeCellRenderer2的實現中添加圖標。 例如,嘗試將此圖標添加到ProgressTreeCellRenderer2的面板:

panel.add((new JLabel((Icon)UIManager.get("Tree.closedIcon"))));

但請注意,您當前的實施非常昂貴。 您不僅每個節點都有一個新的渲染器,而且還要在getTreeCellRendererComponent()重新分配面板實例。 嘗試對具有預分配控件的所有節點使用單個渲染器,其中只根據getTreeCellRendererComponent的參數更新屬性。 有關渲染器詳細信息和樹顯示自定義的示例,請參見如何使用樹

看一下這個答案 (由@mKorbel提供),它說明了表格中的單個進度條渲染器。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM