Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to left justify Python tkinter grid columns while filling entire cell

I'm trying to write a python class to display data in a tabular format. I'm sure there are classes out there already to do the same thing, however, I'm using this exercise as a way to teach myself Python and tkinter. For the most part, I have the class working the way I want it to, however I cannot get the header and data cells to fill their entire cell, while being aligned left. Here is what my class currently generates for a table:

How the table currently looks

I went ahead and changed the sticky on the cells to be (W,E) rather than just W, in order to show how I want the table to look, except each cell left justified. Below is what I'm shooting for:

How I want the table to look

Based on the research I've done, it would seem I need to be using the weight attribute of grid_columnconfigure and grid_rowconfigure, however every way I have tried using them I cannot, get it to work.

Here is the code for my class (I am using Python 3.4):

from tkinter import *
from tkinter import ttk
from tkinter import font

class TableData:

    def __init__(self,parent,attributes,columns,data):
        self.parent = parent
        self.tableName = StringVar()
        self.tableName.set(attributes['tableName'])
        self.columns = columns
        self.columnCount = 0
        self.borderColor = attributes['borderColor']
        self.titleBG = attributes['titleBG']
        self.titleFG = attributes['titleFG']
        self.titleFontSize = attributes['titleFontSize']
        self.headerBG = attributes['headerBG']
        self.headerFG = attributes['headerFG']
        self.headerFontSize = attributes['headerFontSize']
        self.dataRowColor1 = attributes['dataRowColor1']
        self.dataRowColor2 = attributes['dataRowColor2']
        self.dataRowFontSize = attributes['dataRowFontSize']
        self.dataRowFG = attributes['dataRowFG']
        self.data = data
        self.tableDataFrame = ttk.Frame(self.parent)
        self.tableDataFrame.grid(row=0,column=0)
        self.initUI()

    def countColumns(self):
        cnt = 0
        for i in self.columns:
            cnt += 1

        self.columnCount = cnt

    def buildTableTitle(self):
        tableTitleFont = font.Font(size=self.titleFontSize)
        Label(self.tableDataFrame,textvariable=self.tableName,bg=self.titleBG,fg=self.titleFG,font=tableTitleFont, highlightbackground=self.borderColor,highlightthickness=2).grid(row=0,columnspan=self.columnCount,sticky=(W,E), ipady=3)

    def buildHeaderRow(self):
        colCount = 0
        tableHeaderFont = font.Font(size=self.headerFontSize)
        for col in self.columns:
            Label(self.tableDataFrame,text=col,font=tableHeaderFont,bg=self.headerBG,fg=self.headerFG,highlightbackground=self.borderColor,highlightthickness=1).grid(row=1,column=colCount,sticky=W, ipady=2, ipadx=5)
            colCount += 1

    def buildDataRow(self):
        tableDataFont = font.Font(size=self.dataRowFontSize)
        rowCount = 2
        for row in self.data:
            if rowCount % 2 == 0:
                rowColor = self.dataRowColor2
            else:
                 rowColor = self.dataRowColor1
            colCount = 0
            for col in row:
                Label(self.tableDataFrame,text=col,bg=rowColor,fg=self.dataRowFG,font=tableDataFont,highlightbackground=self.borderColor,highlightthickness=1).grid(row=rowCount,column=colCount,sticky=W,ipady=1, ipadx=5)
                colCount += 1
            rowCount += 1

    def initUI(self):
        self.countColumns()
        self.buildTableTitle()
        self.buildHeaderRow()
        self.buildDataRow()

Here is a test file referencing the TableData class:

from tkinter import *
from tkinter import ttk
from tableData import TableData
import sqlite3

root = Tk()
root.geometry('1000x400')

mainframe = ttk.Frame(root).grid(row=0,column=0)

attributes = {}
attributes['tableName'] = 'Title'
attributes['borderColor'] = 'black'
attributes['titleBG'] = '#1975D1'
attributes['titleFG'] = 'white'
attributes['titleFontSize'] = 16
attributes['headerBG'] = 'white'
attributes['headerFG'] = 'black'
attributes['headerFontSize'] = 12
attributes['dataRowColor1'] = 'white'
attributes['dataRowColor2'] = 'grey'
attributes['dataRowFontSize'] = 10
attributes['dataRowFG'] = 'black'

columns = ['Col 1', 'Column 2', 'Column 3','Column    4']

results = [('1','Key','Desc','Attribute'),('2','Key Column','Description Column','AttributeColumn')]

table = TableData(mainframe,attributes,columns,results)

root.mainloop()

Thanks in advance for any insight. Please, let me know if there is any other info that would be helpful.

like image 577
Ryan Avatar asked May 30 '15 20:05

Ryan


People also ask

What does grid () do in Tkinter?

Python - Tkinter grid() Method This geometry manager organizes widgets in a table-like structure in the parent widget.

Can you have multiple grids Tkinter?

Tkinter can support the creation of more than one widget in the same frame. Not just this it also supports a mechanism to align them relative to each other. One of the easiest ways of aligning the different widgets in the Tkinter is through grid manager.

Can you use grid and place Tkinter?

Tkinter has three built-in layout managers that use geometric methods to position buttons in an application frame: pack, grid, and place. The pack manager organizes widgets in horizontal and vertical boxes that are limited to left, right, top, bottom positions offset from each other.

How do you center a grid label?

Just give the row and column in which the label appears a weight of 1 and be sure not to specify a sticky attribute. By default the row and column weight is set to zero, which means neither will grow to fill in any extra space in the widget.


1 Answers

If you want the text in a label to be left-aligned, use the anchor option. It takes a string representing a point on a compass (eg: "w" = "west", meaning the text is anchored to the left):

for col in row:
    Label(..., anchor="w").grid(...)
like image 70
Bryan Oakley Avatar answered Oct 12 '22 09:10

Bryan Oakley