【问题标题】:Automatically resize text widget's width to fit all text自动调整文本小部件的宽度以适合所有文本
【发布时间】:2021-01-04 21:02:48
【问题描述】:

我正在尝试使用文本小部件打印表格。我已经创建了一种使用标签和框架来执行此操作的方法,但问题是我需要将更大的表格呈现到需要使用滚动条的地步。

我正在使用选项卡为文本小部件制作表格,效果很好,但我似乎无法找到一种方法来设置小部件的宽度以适合文本。我正在尝试使用下面的 get_width() 方法,但它并不总是有效。

宽度选项以字体的平均大小字符来衡量,但问题是选项卡“字符”的大小会有所不同。文本小部件的 tab 键工作方式与终端或文本文件的 print() 函数不同。

下面是我的代码:

from tkinter import *
import math


class App(Text):
    def __init__(self, matrix, parent, **kwargs):
        Text.__init__(self, parent, **kwargs)
        self.parent = parent
        self.matrix = matrix

        temp = []
        for row in matrix:
            temp.append(len(row))

        # Making sure all the rows are of equal length and string values...
        for row in matrix:
            for _ in range(max(temp) - len(row)):
                row.append('')

        matrix = [[str(matrix[r][c]) for c in range(len(matrix[0]))] for r in range(len(matrix))]
        
        # I need to get the maximum length for each column in the matrix...
        c_lengths = {}
        for c in range(len(matrix[0])):
            c_lengths.update({c: []})
            for r in range(len(matrix)):
                c_lengths[c].append(len(matrix[r][c]))

        self.tab_list = []
        for r in range(len(matrix)):
            temp = []
            for c in range(len(matrix[0])):
                if c != len(matrix[0]) - 1:
                    tab_count = (math.floor(max(c_lengths[c])/8)+1)
                    '''if (tab_count + max(c_lengths[c])) % 8 == 0:
                        tab_count += 1'''
                    temp.append(tab_count)
                    tabs = ['\t'] * tab_count
                    string = matrix[r][c] + ''.join(tabs)
                else:
                    string = matrix[r][c]
                self.insert(END, string)
            self.tab_list.append(sum(temp))
            self.insert(END, '\n')

        self.configure(state=DISABLED, wrap=NONE, width=self.get_width())

    def get_width(self):
        temp = []
        for row in self.matrix:
            temp.append(len(''.join(row)))
        return max(temp) + max(self.tab_list)*4


if __name__ == '__main__':
    import random
    root = Tk()
    root.state('zoomed')

    m = [['0' for _ in range(5)] for _ in range(40)]

    for i in range(40):
        for j in range(5):
            m[i][j] = '*' * random.randint(1, 25)

    App(m, root, font=('Times', '12'), height=40).pack()
    root.mainloop()

这是输出:

这个运行结果很好,但有时它会切断一些桌子。

【问题讨论】:

  • 您的问题不清楚。您希望 Text 小部件可滚动吗?
  • @JacksonPro 我希望小部件自动调整宽度以适合里面的文本。我上面的 get_width() 方法并不总是有效,因为它取决于制表符的长度而变化。
  • 我会给你一个答案你介意检查一下吗?可能不是 100% 正确。
  • 是的,我可以检查你的答案@JacksonPro
  • 我的答案是否适用于所有情况?

标签: python python-3.x tkinter


【解决方案1】:
from tkinter import *
import math


class App(Text):
    def __init__(self, matrix, parent, **kwargs):
        Text.__init__(self, parent, **kwargs)
        self.parent = parent
        self.matrix = matrix

        temp = []
        for row in matrix:
            temp.append(len(row))

        # Making sure all the rows are of equal length and string values...
        for row in matrix:
            for _ in range(max(temp) - len(row)):
                row.append('')

        matrix = [[str(matrix[r][c]) for c in range(len(matrix[0]))] for r in range(len(matrix))]

        # I need to get the maximum length for each column in the matrix...
        c_lengths = {}
        for c in range(len(matrix[0])):
            c_lengths.update({c: []})
            for r in range(len(matrix)):
                c_lengths[c].append(len(matrix[r][c]))

        self.tab_list = []

        for r in range(len(matrix)):
            temp = []
            for c in range(len(matrix[0])):
                if c != len(matrix[0]) - 1:
                    tab_count = (math.floor(max(c_lengths[c])/8)+1)
                    '''if (tab_count + max(c_lengths[c])) % 8 == 0:
                        tab_count += 1'''
                    temp.append(tab_count)
                    tabs = ['\t'] * tab_count
                    string = matrix[r][c] + ''.join(tabs)
                else:
                    string = matrix[r][c]
                self.insert(END, string)
            self.tab_list.append(sum(temp))
            self.insert(END, '\n')

        self.configure(state=DISABLED, wrap=NONE, width=self.getWidth())


    def getWidth(self):
        lst = []

        for x in range(int(self.index('end-1c').split('.')[0])):
            lst.append(len(self.get(f'end-{x} lines linestart', f'end-{x} lines lineend')))

        return max(lst)+52


if __name__ == '__main__':
    import random
    root = Tk()
    root.state('zoomed')

    m = [['0' for _ in range(5)] for _ in range(40)]

    for i in range(40):
        for j in range(5):
            m[i][j] = '*' * random.randint(1, 25)

    App(m, root, font=('Times', '12'), height=40).pack()
    root.mainloop()

说明: self.get(f'end-{x} lines linestart', f'end-{x} lines lineend')这里get(index1, index2)方法用于获取index1和index2之间的字符。

您可以阅读linestartlineend 参数的作用here

end-x x 从 0 到最后一行,所以 end-1 是最后一行,依此类推。所以所有end-{x} lines linestart获取每一行的起始索引,end-{x} lines lineend获取同一行的最后索引。

更新

操作你的 get_width:

 def get_width(self):
        temp = []
        for row in self.matrix:
            temp.append(len(''.join(row)))
        return max(temp) + max(self.tab_list)*4

相同
    def getWidth(self):
        lst = []
        spaces = []
        for x in range(int(self.index('end-1c').split('.')[0])+1):
            spaces = len([x for x in self.get(f'end-{x} lines linestart', f'end-{x} lines lineend') if x=='\t'])
            lst.append(len(self.get(f'end-{x} lines linestart', f'end-{x} lines lineend'))+spaces*4)
        return max(lst)

差别不大。

我还发现选项卡不一致我不完全确定原因。设置self['tabs'] = '2c' 提供更多一致性,您可能想查看更多here

【讨论】:

  • OP 如果这是您要查找的内容,请打勾,我会添加解释。如果您有任何疑问,请发表评论。
  • 这肯定比我有的更好,但宽度仍然有一些额外的空间。但只要它横向显示所有内容,我就很高兴。谢谢你的回答!
  • @GabeMorris 你可以通过改变return max(lst)+52来改变额外的宽度
  • 如果你能添加更多细节会更好,这样其他人可能会觉得这更有帮助。
  • @CoolCloud 是的,我会的,我只是在检查是否有更好的方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-05
  • 1970-01-01
  • 2023-04-01
  • 2023-03-17
  • 2012-02-06
相关资源
最近更新 更多