格式化可编辑的tkinter python gui

时间:2017-04-28 13:43:11

标签: python sql tkinter

我正在构建我的第一个python tkinter gui,其中一部分是一个可编辑的表。该代码基于这篇文章,其中Bryan Oakley的答案是一个很棒的资源:SQL Query results in tkinter

我还发现这个引用对基于SQL的可编辑guis很有用: https://www.ssucet.org/old/pluginfile.php/778/mod_resource/content/2/Python%20Database%20Lab.pdf

在Bryan Oakely的解决方案中,我认为数据是元组的元组。例如,

data = (
(45417, "rodringof", "CSP L2 Review", 0.000394, "2014-12-19 
10:08:12", "2014-12-19 10:08:12"),...

我从SQL连接中获取的数据是元组列表。我将它转换为元组元组 - 它解决了我收到的错误并使GUI能够填充数据。我很感激评论描述为tkinter重构SQL数据的更好方法,相当于我的' big_tuple'在代码中创建?(注意,这是读取Access .mdb文件,这是我可以做的唯一类型的SQL连接 - 也许这是我必须克服的特定问题)。完整代码发布在问题的最后。

更重要的是,这是一个真正的问题:

图片显示片段制作' big_tuple' GUI和控制台输出之间的差异 enter image description here

你可以在这里看到数据包含在' for'中使用strftime重新格式化的datetime对象。循环,分配元组的元组' data1'。但是,根据GUI,“数据1”中的浮点数。没有在这个循环中重新格式化。如果' big_tuple'打印到控制台,它显示浮动已成功重新格式化,但在GUI中,它们保持未格式化。 请告诉我为什么浮动片在打印输出中显示格式但在GIU中没有?以下是完整代码:

#import tkinter as tk
#import pyodbc
import datetime

# db = pyodbc.connect('DRIVER={Microsoft Access Driver (*.mdb, *.accdb)};\
#                     UID=admin;UserCommitSync=Yes;Threads=3;SafeTransactions=0;\
#                     PageTimeout=5;MaxScanRows=8;MaxBufferSize=2048;FIL={MS Access};DriverId=25;\
#                     DefaultDir=C:\\Tim local ;DBQ=C:\\Tim local\\copy2MobileBases.mdb')

# s= 'SELECT * FROM MASTER1' 
# cursor = db.cursor()
# cursor.execute(s)
# data = cursor.fetchall() # our SQL data 

data = [(1, 'AAA001', '07770000000', datetime.datetime(2016, 2, 16, 0, 0), datetime.datetime(2018, 2, 15, 0, 0), 10.0, 0.0, 0.0, 0.0),
        (2, 'AAA001', '07770000001', datetime.datetime(2016, 2, 26, 0, 0), datetime.datetime(2018, 2, 25, 0, 0), 10.129999999999999, 0.0, 0.0, 0.0),
        (3, 'AAA001', '07770000002', datetime.datetime(2016, 3, 8, 0, 0), datetime.datetime(2018, 2, 15, 0, 0), 10.129999999999999, 2.5, 0.0, 0.0),
        (4, 'AAA001', '07770000003', datetime.datetime(2016, 4, 8, 0, 0), datetime.datetime(2018, 2, 15, 0, 0), 10.129999999999999, 0.0, 0.0, 0.0)
       ]

# class to convert the floats to 2dp
class prettyfloat(float):
    def __repr__(self):
        return "%0.2f" % self

# format to convert the strftime
format = ('%d/%m/%Y')

# MAKE 'big_tuple': solving the list of tuples problem - make a tuple of tuples and format too
x = list(data)
list_of_lists = [list(elem) for elem in x]

big_list = []
for i in list_of_lists:
    data1=(str(i[0]),i[1],str(i[2]),(i[3].strftime(format)), (i[4].strftime(format)), 
           prettyfloat(i[5]), prettyfloat(i[6]), prettyfloat(i[7]), prettyfloat(i[8]))
    big_list.append(data1)

big_tuple = tuple(big_list)
print(big_tuple)

class Example(tk.Frame):
    def __init__(self, parent):
        tk.Frame.__init__(self, parent)
        b = tk.Button(self, text="Done!", command=self.upload_cor)
        b.pack()
        table = tk.Frame(self)
        table.pack(side="top", fill="both", expand=True)

        self.widgets = {}
        row = 0
        for rent_id, Client, CLI, Connected_Date, Contract_End_Date, Current_Line_Rental, V1, V2, V3 in (big_tuple):
            row += 1
            self.widgets[rent_id] = {
                "rent_id": tk.Label(table, text=rent_id),
                "Client": tk.Label(table, text=Client),
                "CLI": tk.Label(table, text=CLI),
                "handset": tk.Entry(table),
                "Connected_Date": tk.Label(table, text=Connected_Date),
                "Contract_End_Date": tk.Label(table, text=Contract_End_Date),
                "Current_Line_Rental": tk.Label(table, text=str(Current_Line_Rental)),
                "V1": tk.Label(table, text=V1),
                           }

            self.widgets[rent_id]["rent_id"].grid(row=row, column=0, sticky="nsew")
            self.widgets[rent_id]["Client"].grid(row=row, column=1, sticky="nsew")
            self.widgets[rent_id]["CLI"].grid(row=row, column=2, sticky="nsew")
            self.widgets[rent_id]["handset"].grid(row=row, column=3, sticky="nsew")
            self.widgets[rent_id]["Connected_Date"].grid(row=row, column=4, sticky="nsew")
            self.widgets[rent_id]["Contract_End_Date"].grid(row=row, column=5, sticky="nsew")
            self.widgets[rent_id]["Current_Line_Rental"].grid(row=row, column=6, sticky="nsew")
            self.widgets[rent_id]["V1"].grid(row=row, column=7, sticky="nsew")


        table.grid_columnconfigure(1, weight=1)
        table.grid_columnconfigure(2, weight=1)
        # invisible row after last row gets all extra space
        table.grid_rowconfigure(row+1, weight=1)



    def upload_cor(self):
        updates = []
        for rent_id in (sorted(self.widgets.keys())):
            entry_widget = self.widgets[rent_id]["handset"]
            new_value = entry_widget.get()
            print("%s: %s" % (rent_id, new_value))
            updates.append(new_value)
        print (updates)

if __name__ == "__main__":
    root = tk.Tk()
    Example(root).pack(fill="both", expand=True)
    root.mainloop()


# cursor.close()    
# db.close()  

1 个答案:

答案 0 :(得分:2)

您看到差异的原因是print将打印字符串值prettyfloat,但您将实际的浮点数传递给标签小部件。此浮点值将传递给tkinter所基于的底层tcl解释器,并且正是此tcl解释器正在转换浮点值以进行显示。 tcl解释器不知道如何调用__repr__函数。

如果您使用repr将值显式转换为字符串,则可以看到漂亮的版本,因为您定义了__repr__方法:

self.widgets[rent_id] = {
    ...
    "Current_Line_Rental": tk.Label(..., text=repr(Current_Line_Rental)),
    ...
}

或者,您可以定义__str__,然后使用str(Current_Line_Rental)