【问题标题】:Format editable tkinter python gui格式化可编辑的 tkinter python gui
【发布时间】:2017-04-28 13:43:11
【问题描述】:

我正在构建我的第一个 python tkinter gui,其中一部分是一个可编辑的表。该代码基于这篇文章,其中 Bryan Oakley 的回答是一个极好的资源:@​​987654321@

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

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

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

我从我的 SQL 连接获得的数据是一个元组列表。我将它转换为元组的元组 - 这解决了我收到的错误并使 GUI 能够填充数据。我会感谢 cmets 描述 一种更好的方法来为 tkinter 重构 SQL 数据,相当于我在代码中创建的“big_tuple”?(注意,这是读取一个 Access .mdb 文件,它是唯一的我可以建立的 SQL 连接类型 - 也许这是我必须克服的特定问题)。完整代码贴在问题末尾。

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

图像显示 sn-p 制作“big_tuple”以及 GUI 和控制台输出之间的差异

您可以在此处看到数据包含 datetime 对象,这些对象在分配元组“data1”的“for”循环中使用 strftime 重新格式化。但是,根据 GUI,“data1”中的浮点数在此循环中没有重新格式化。如果 '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()  

【问题讨论】:

  • 就我的原始答案而言,元组元组、元组列表或列表列表的行为方式完全相同。
  • 我们无法运行您的代码,因为我们没有您的数据库。请用一些静态数据重写您的示例。此外,您还有缩进问题。例如,upload_cor 的缩进错误。
  • @BryanOakley,对格式不正确的代码表示歉意。我还用静态数据替换了连接。

标签: python sql tkinter


【解决方案1】:

您看到差异的原因是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)

【讨论】:

  • @Bryan_Oakley 感谢您的及时回复。我已经尝试过您的建议,但显式转换也不会格式化 GUI: "Current_Line_Rental": tk.Label(table, text=str(Current_Line_Rental)),
  • @Tim0th1:你是对的;我很抱歉。您定义了__repr__,而不是__str__。我会更新我的答案。
猜你喜欢
  • 2021-02-12
  • 1970-01-01
  • 2020-10-01
  • 1970-01-01
  • 2014-05-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-04
相关资源
最近更新 更多