Seagan Damian
Seagan Damian

Reputation: 21

How to format a multi lined string nicely in tkinter

So I'm really new to tkinter and what I'm trying to do is display an output in a tkinter frame. Due to not knowing any other way, I'm trying to set a label to a string(the output i want to display) and then pack the label onto a frame. This kinda works my only problem is the way its being formatted. The string is supposed to be like below: enter image description here

But when i put it into tkinter it looks like this: enter image description here

Is there anyway to fix this or a better way to output strings into tkinter instead of using labels. The function I'm using to get the string that way looks like this(the reason the getPrettyString function has so many elif's is so that i can change the size of each column as i need):

def getPrettyString(record):
    string = ""
    for i in range(len(record)):
        if i == 0:
            string += '{:<25}'.format(record[i])
        elif i == 1:
            string += '{:<25}'.format(record[i])
        elif i == 2:
            string += '{:<25}'.format(record[i])
        elif i == 3:
            string += '{:<25}'.format(record[i])
        elif i == 4:
            string += '{:<25}'.format(record[i])
        elif i == 5:
            string += '{:<25}'.format(record[i])
        elif i == 6:
            string += '{:<25}'.format(record[i])
        elif i == 7:
            string += '{:<25}'.format(record[i])
return string


def writeTable(table):
    record = ''
    header = ["ID", "Assignment Name", "Submission Date", "Time of submission", "Group Assignment", "Group comments",
              "Assignment Text", "Marks"]
    record += getPrettyString(header)
    record += '\n'

    for team in table:
        record += getPrettyString(team)
        record += '\n'
    return record

My tkinter code looks like this:

class View_marks_student:
    def __init__(self, master):
        master.geometry('1080x1920')
        master.title("Student Marks Page")
        string = StringVar()
        string.set(writeTable(table_details))
        self.label = Label(master, textvariable=string, anchor=N, justify=LEFT)
        self.label.pack(anchor=NW, fill=BOTH, expand=1)

Any help will be appreciated

Upvotes: 0

Views: 612

Answers (1)

Ethan Field
Ethan Field

Reputation: 4730

For drawing tables, using .grid() is a lot simpler and tends to look an awful lot better.

See my example below:

from tkinter import *

root = Tk()

header = ["ID", "Assignment Name", "Submission Date", "Time of submission", "Group Assignment", "Group comments", "Assignment Text", "Marks"]

for i in range(10):
    Grid.rowconfigure(root, i, weight=1)
    if i == 0:
        for c in range(len(header)):
            Grid.columnconfigure(root, c, weight=1)
            Label(root, text=header[c], borderwidth=1, relief="solid").grid(column=c, row=i, sticky=N+S+E+W)
    else:
        for c in range(len(header)):
            Grid.columnconfigure(root, c, weight=1)
            Label(root, text=header[c]+" Row:"+str(i)+", Col:"+str(c), borderwidth=1, relief="solid").grid(column=c, row=i, sticky=N+S+E+W)

So, we create the first for loop to represent the rows of the table, each increment of i increments to the next line of the table. We then create a nested for loop for each line of the table (increment of i) which represents each cell in each column of the specific row.

So we start on the header, accessing row "0", we then iterate through the list of headers to print each cell value in each column of the row we are on and then move on to the next row.

We also use some fancy operations like rowconfigure and columnconfigure to set the weight of each row and column to 1, this means that the cells will expand to fill the available space assigned to them, and by making each label we create sticky in all directions (N+S+E+W) the borders will expand to fit the assigned space too.

If you have a set of data that you wanted to input to the table then you could create a list oflist`s and specify the data your outputting where the first iteration value is the row and the second is the column.

So this:

for c in range(len(header)):
    Grid.columnconfigure(root, c, weight=1)
    Label(root, text=header[c]+" Row:"+str(i)+", Col:"+str(c), borderwidth=1, relief="solid").grid(column=c, row=i, sticky=N+S+E+W)

Would become this (where data is your list of lists):

for c in range(len(header)):
    Grid.columnconfigure(root, c, weight=1)
    Label(root, text=data[i][c]+" Row:"+str(i)+", Col:"+str(c), borderwidth=1, relief="solid").grid(column=c, row=i, sticky=N+S+E+W)

Upvotes: 1

Related Questions