如何正确计算wx.TreeCtrl的完全展开宽度

2 投票
2 回答
936 浏览
提问于 2025-04-15 12:04

wx.TreeCtrl的首选大小似乎是当树完全折叠时,所有元素都能适应的最小大小。有没有一种好的(也就是跨平台兼容的)方法来计算树在完全展开时的宽度?我现在的解决方案是:

def max_width(self):
    dc = wx.ScreenDC()
    dc.SetFont(self.GetFont())
    widths = []
    for item, depth in self.__walk_items():
        if item != self.root:
            width = dc.GetTextExtent(self.GetItemText(item))[0] + self.GetIndent()*depth
            widths.append(width)
    return max(widths) + self.GetIndent()

这个方法在win32上效果很好,但在linux上就不行了。有没有办法让TreeCtrl自己告诉我它的大小,这样我就可以覆盖它报告的大小?(总是返回最大展开的宽度)

补充说明:抱歉没有提供我上面使用的函数,但你大概明白我的意思,我是在遍历树,获取每个标签的宽度,并返回最宽的那个的总宽度(考虑了缩进)

2 个回答

0

这段代码在我的Windows和Linux系统上都能正常运行:

def compute_best_size(self):
    if os.name == 'nt':
        best_size = (self.__max_width_win32(), -1)
    else:
        best_size = (self.__max_width(), -1)
    self.SetMinSize(best_size)

def __max_width_win32(self):
    dc = wx.ScreenDC()
    dc.SetFont(self.GetFont())
    widths = []
    for item, depth in self.__walk_items():
        if item != self.root:
            width = dc.GetTextExtent(self.GetItemText(item))[0] + self.GetIndent()*depth
            widths.append(width)
    return max(widths) + self.GetIndent()

def __max_width(self):
    self.Freeze()
    expanded = {}
    for item in self.get_items():
        if item is not self.root:
            expanded[item] = self.IsExpanded(item)
    self.ExpandAll()
    best_size = self.GetBestSize()
    for item in expanded:
        if not expanded[item]: self.Collapse(item)
    self.Thaw()
    return best_size[0]

... 每次往树里添加新项目时,都要调用一下 compute_best_size() 这个函数。

1

我发现 GetBestSize 这个方法似乎会考虑到那些被折叠的项目。例如,在演示中的 wxTreeCtrl(我用的是Ubuntu和wxPython 2.8.7.1),当我改变内部文本字符串的长度(在我版本的演示中是第74行)时,调用 self.tree.GetBestSize() 返回的值会考虑到这个新的字符串长度,即使这个树状结构没有展开。也许你需要调用一下 SetQuickBestSize(False) 呢?

撰写回答