Таблица с переменной высотой строки в tkinter

Я создаю графический интерфейс, в котором хочу отобразить некоторые данные в виде таблицы, подобной Excel. Для некоторых строк будет только одна строка текста, а для других - несколько строк. Следовательно, мне нужна таблица, в которой высота строк не одинакова.

Я нашел этот пост, в котором описывается, как создать таблицу с обернутым текстом с помощью treeview: Обернуть текст внутри строки в tkinter treeview

Однако я не могу изменить высоту конкретной строки.

Кто-нибудь знает, как это сделать, или знает, как лучше сделать таблицу, подобную описанной выше.


person Tola    schedule 22.07.2018    source источник


Ответы (1)


Итак, я нашел какое-то решение своей проблемы.

На основе этого сообщения: tkinter Canvas Scrollbar with Grid?. Я пришел к следующему решению. Python для меня новичок, поэтому его, вероятно, можно было бы сделать более элегантным :-)

Проблема, с которой я столкнулся сейчас, заключается в том, что ширина метки задается в текстовых единицах, а длина оболочки - в единицах экрана. Есть ли способ найти коэффициент преобразования между ними?

from tkinter import *
import math
class MyApp(Tk):
    def __init__(self):
        Tk.__init__(self)

        #self.columnconfigure(0, weight=1)
        self.rowconfigure(0, weight=1)
        self.geometry('950x500+100+100')

        label = Label(self,text='Table with some data', font=("Arial Bold", 25))
        label.pack()

        master_frame = Frame(self, bd=3, relief=RIDGE)
        master_frame.pack(side=BOTTOM)

        # Create a frame for the canvas and scrollbar(s).
        frame2 = Frame(master_frame)
        frame2.pack(side = BOTTOM)

        # Add a canvas in that frame.
        canvas = Canvas(frame2)
        canvas.grid(row=0, column=0)

        # Create a vertical scrollbar linked to the canvas.
        vsbar = Scrollbar(frame2, orient=VERTICAL, command=canvas.yview)
        vsbar.grid(row=0, column=1, sticky=NS)
        canvas.configure(yscrollcommand=vsbar.set)

        # Create a frame on the canvas to contain the buttons.
        self.table_frame = Frame(canvas)

        #Add some info to table
        newLine = ["Step#","Process Type","Tool Info","Process details","Cost","Comments"]
        self.newRow(0,newLine)
        newLine = ["Step# Step#","Process Type","Tool Info","Process details","Cost","Comments"]
        self.newRow(1,newLine)
        newLine = ["Step# Step# Step#","Process Type","Tool Info","Process details","Cost","Comments"]
        self.newRow(2,newLine)
        newLine = ["Step# Step# Step# Step#","Process Type","Tool Info","Process details","Cost","Comments"]
        self.newRow(3,newLine)
        newLine = ["Step# Step# Step# Step# Step#","Process Type","Tool Info","Process details","Cost","Comments"]
        self.newRow(4,newLine)

        # Create canvas window to hold the buttons_frame.
        canvas.create_window((0,0), window=self.table_frame, anchor=NW)

        self.table_frame.update_idletasks()  # Needed to make bbox info available.
        bbox = canvas.bbox(ALL)  # Get bounding box of canvas with Buttons.
        #print('canvas.bbox(tk.ALL): {}'.format(bbox))

        # Define the scrollable region as entire canvas with only the desired
        # number of rows and columns displayed.
        canvas.configure(scrollregion=bbox, width=925, height=200)

    #Add a new line to the table     
    def newRow(self, rowNumber, info2Add):

        numberOfLines = []                  #List to store number of lines needed
        columnWidths = [7,20,20,40,10,30]   #Width of the different columns in the table - unit: text
        stringLength = []                   #Lengt of the strings in the info2Add list

        #Find the length of each element in the info2Add list 
        for item in info2Add:
            stringLength.append(len(item))

        #Find the number of lines needed for each column
        for index, item in enumerate(stringLength):
            #print(math.ceil(item/columnWidths[index]))
            numberOfLines.append(math.ceil(item/columnWidths[index]))

        #Find the maximum number of lines needed
        lineNumber = max(numberOfLines)

        #Define the 6 labels (columns) in each row consist of.                
        col1 = Label(self.table_frame, relief=RIDGE,text=info2Add[0], wraplength=60,bg='white')
        col1.grid(row=rowNumber, column=1, sticky='news')
        col1.config(width=7, height=lineNumber)
        col2 = Label(self.table_frame, relief=RIDGE,text=info2Add[1], wraplength=140,bg='white')
        col2.grid(row=rowNumber, column=2, sticky='news')
        col2.config(width=20, height=lineNumber)
        col3 = Label(self.table_frame, relief=RIDGE,text=info2Add[2], wraplength=140,bg='white')
        col3.grid(row=rowNumber, column=3, sticky='news')
        col3.config(width=20, height=lineNumber)
        col4 = Label(self.table_frame, relief=RIDGE,text=info2Add[3], wraplength=280,bg='white')
        col4.grid(row=rowNumber, column=4, sticky='news')
        col4.config(width=40, height=lineNumber)
        col5 = Label(self.table_frame, relief=RIDGE,text=info2Add[4], wraplength=70,bg='white')
        col5.grid(row=rowNumber, column=5, sticky='news')
        col5.config(width=10, height=lineNumber)
        col6 = Label(self.table_frame, relief=RIDGE,text=info2Add[5], wraplength=210,bg='white')
        col6.grid(row=rowNumber, column=6, sticky='news')
        col6.config(width=30, height=lineNumber)


app = MyApp()
app.mainloop()
person Tola    schedule 23.07.2018