TreeView用于展示表格

# 展示表格的窗口

class TableViewWindow : EditorWindow
{
    [MenuItem("TreeView Examples/Table View Window")]
    static void ShowWindow()
    {
        var window = GetWindow<TableViewWindow>();
        window.titleContent = new GUIContent("My Window");
        window.Show();
    }

    TableView _tableView;
    TreeViewState _treeViewState;
    MultiColumnHeaderState _multiColHeaderState;

    private void OnEnable()
    {
        if (null == _treeViewState)
            _treeViewState = new TreeViewState(); //单独用一个类, 以便于序列化状态

        _multiColHeaderState = CreateStateWith3Cols();
        var multiColHeader = new MultiColumnHeader(_multiColHeaderState);
        multiColHeader.ResizeToFit();

        _tableView = new TableView(_treeViewState, multiColHeader);
    }

    private void OnGUI()
    {
        var xMargin = 10;
        var yMargin = 10;
        var rect = new Rect(xMargin, yMargin, position.width - xMargin * 2, position.height - yMargin * 2);
        _tableView.OnGUI(rect);
    }

    static MultiColumnHeaderState CreateStateWith3Cols()
    {
        var columns = new[]
        {
            new MultiColumnHeaderState.Column
            {
                headerContent = new GUIContent(EditorGUIUtility.FindTexture("FilterByType"), "这里是tooltips"),
                contextMenuText = "Type",
                width = 60,
                minWidth = 50,
                maxWidth = 100,
                headerTextAlignment = TextAlignment.Center,
                autoResize = false,
                allowToggleVisibility = true,
            },
            new MultiColumnHeaderState.Column
            {
                headerContent = new GUIContent("Key"),
                width = 100,
                minWidth = 30,
                headerTextAlignment = TextAlignment.Left,
                canSort = true,
                autoResize = false,
            },
            new MultiColumnHeaderState.Column
            {
                headerContent = new GUIContent("Value"),
                width = 200,
                minWidth = 50,
                headerTextAlignment = TextAlignment.Right,
                canSort = true,
                autoResize = false,
            },
        };

        var state = new MultiColumnHeaderState(columns);
        return state;
    }

}

# 数据类

class RowData
{
    public int id;
    public string name;
    public string value;

    public RowData(int id, string name, string value)
    {
        this.id = id;
        this.name = name;
        this.value = value;
    }
}

# TreeView用于展示表格,重写BuildRoot和RowGUI。

class TableView : TreeView
{
    Dictionary<int, RowData> _testDatas;

    public TableView(TreeViewState state, MultiColumnHeader multiColumnHeader)
        : base(state, multiColumnHeader)
    {
        CreateTestData();

        rowHeight = 35;
        showAlternatingRowBackgrounds = true; //隔行显示颜色
        showBorder = true; //表格边框
        Reload();
    }

    void CreateTestData()
    {
        Debug.Log($"CreateTestData");
        _testDatas = new Dictionary<int, RowData>();
        _testDatas.Add(0, new RowData(0, "n0", "zero"));
        _testDatas.Add(1, new RowData(1, "n1", "one"));
        _testDatas.Add(2, new RowData(2, "n2", "two"));
        _testDatas.Add(3, new RowData(3, "n3", "three"));
        _testDatas.Add(4, new RowData(4, "n4", "four"));
        _testDatas.Add(5, new RowData(5, "n5", "five"));
        _testDatas.Add(6, new RowData(6, "n6", "six"));
    }

    protected override TreeViewItem BuildRoot()
    {
        var rootTreeViewItem = new TreeViewItem(-1, -1); //root的depth必须为-1
        for (var id = 0; id < _testDatas.Count; ++id)
        {
            var rowData = _testDatas[id];
            var childTreeViewItem = new TreeViewItem(rowData.id, 0, $"dummy_{id}");
            rootTreeViewItem.AddChild(childTreeViewItem);
        }

        return rootTreeViewItem;
    }

    protected override void RowGUI(RowGUIArgs args)
    {
        for (var i = 0; i < args.GetNumVisibleColumns(); ++i)
        {
            CellGUI(args.GetCellRect(i), args.item, args.GetColumn(i), ref args);
        }
    }

    private void CellGUI(Rect cellRect, TreeViewItem item, int col, ref RowGUIArgs args)
    {
        //var kv = _testDatas[item.id];
        if (!_testDatas.TryGetValue(item.id, out var cellRowData))
            return;

        CenterRectUsingSingleLineHeight(ref cellRect); //控件的区域居中
        switch (col)
        {
        case 0:
            GUI.Label(cellRect, $"{args.row}_id:{item.id}");
            break;

        case 1:
            GUI.Label(cellRect, $"{cellRowData.name}");
            break;

        case 2:
            GUI.TextField(cellRect, $"{cellRowData.value}");
            break;
        }
    }
}

# 效果图

 

 

【一些tips】

# 如果要用TreeView展示多列,肯定需要重写RowGUI,自己绘制每一列。

# CenterRectUsingSingleLineHeight这个函数的作用是将控件居中,不然会被拉伸。下面就是不调用的效果

 

# 关于为啥会有TreeViewState和MultiColumnHeaderState这种单独的State类,主要是可以用于序列化界面关闭时的状态,下次再打开时

可以恢复到上次的状态。

 

posted @ 2022-03-23 21:23  yanghui01  阅读(692)  评论(0编辑  收藏  举报