python - 为什么我的执行 MySQL 查询的函数在使用 ttk.combobox 的 postcommand 调用时会出错
问题描述
我有这个程序连接到 phpmyadmin MySQL 数据库。它有一个组合框,只要单击下拉箭头,我就想更新其值。我使用组合框的 postcommand 参数来调用执行查询并更新值的函数。这是我的代码简化:
from mysql.connector import connect, Error
from tkinter import *
from tkinter import ttk
root = Tk()
root.title('Program')
root.geometry('600x600+100+100')
def load_combobox(conn, cbox):
query = 'SELECT nama_sopir FROM sopir'
with conn.cursor() as cursor:
cursor.execute(query)
result = cursor.fetchall()
cbox.config(values=result)
try:
with connect(
host = 'localhost',
user = 'root',
password = '',
database = 'sinar_express_database'
) as conn:
frame1 = Frame(root)
frame1.pack(fill='both', expand=1)
# I want to call the function on postcommand. This calls the function but an error occurs
sopir_cbox = ttk.Combobox(frame1, state='readonly', postcommand=lambda : load_combobox(conn, sopir_cbox))
sopir_cbox.pack()
except Error as e:
print(e)
root.mainloop()
这会产生一个错误:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\Winston\AppData\Local\Programs\Python\Python37\lib\tkinter\__init__.py", line 1705, in __call__
return self.func(*args)
File "d:\Documents\Usaha Papa Mama\Program Uang Jalan\Baru\stackoverflow.py", line 27, in <lambda>
sopir_cbox = ttk.Combobox(frame1, state='readonly', postcommand=lambda : load_combobox(conn, sopir_cbox))
File "d:\Documents\Usaha Papa Mama\Program Uang Jalan\Baru\stackoverflow.py", line 11, in load_combobox
with conn.cursor() as cursor:
File "C:\Users\Winston\AppData\Local\Programs\Python\Python37\lib\site-packages\mysql\connector\connection.py", line 1025, in cursor
raise errors.OperationalError("MySQL Connection not available.")
mysql.connector.errors.OperationalError: MySQL Connection not available
我试过单独调用该函数,如下所示,它可以工作!但是,我想在每次单击下拉列表时更新值,而不仅仅是一次。
sopir_cbox = ttk.Combobox(frame1, state='readonly')
load_combobox(conn, sopir_cbox)
我对编程还是很陌生,因此非常感谢任何帮助或建议。
解决方案
GUI
框架不像input()
等待你的决定那样工作。Combobox
(和其他小部件)不会等待您的决定。它只通知tkinter
它必须在窗口中显示的内容 - 并且代码移动到下一行 -mainloop()
显示窗口。
所以你在它退出后看到窗口with connect()
,当你选择选项时,代码已经在外面with connect()
。你必须在with connect()
里面使用load_comobox
。
from mysql.connector import connect, Error
from tkinter import *
from tkinter import ttk
# --- functions ---
def load_combobox():
try:
with connect(
host = 'localhost',
user = 'root',
password = '',
database = 'sinar_express_database'
) as conn:
query = 'SELECT nama_sopir FROM sopir'
with conn.cursor() as cursor:
cursor.execute(query)
result = cursor.fetchall()
sopir_cbox.config(values=result)
except Error as e:
print(e)
# --- main ---
root = Tk()
root.title('Program')
root.geometry('600x600+100+100')
frame1 = Frame(root)
frame1.pack(fill='both', expand=1)
# I want to call the function on postcommand. This calls the function but an error occurs
sopir_cbox = ttk.Combobox(frame1, state='readonly', postcommand=load_combobox)
sopir_cbox.pack()
root.mainloop()
或者你必须把mailoop()
里面with connect()
with connect(
host = 'localhost',
user = 'root',
password = '',
database = 'sinar_express_database'
) as conn:
frame1 = Frame(root)
frame1.pack(fill='both', expand=1)
# I want to call the function on postcommand. This calls the function but an error occurs
sopir_cbox = ttk.Combobox(frame1, state='readonly', postcommand=lambda : load_combobox(conn, sopir_cbox))
sopir_cbox.pack()
root.mainloop()
except Error as e:
print(e)
但在这里我看到了一个问题——你不能sopir_cbox
在里面使用,ttk.Combobox(...)
因为它还没有退出。代码首先执行ttk.Combobox(...)
,然后它创建变量sopir_cbox = ...
,但您需要sopir_cbox
在尚未创建的ttk.Combobox(...)
时候。sopir_cbox = ...
您必须分两步完成
sopir_cbox = ttk.Combobox(frame1, state='readonly')
sopir_cbox["postcommand"] = lambda : load_combobox(conn, sopir_cbox)
推荐阅读
- javascript - 反应原生 - 将状态对象数组分配给变量并更新数组中特定元素的值
- matlab - MATLAB:array2table 中的错误
- r - 使用 ggplot 连接分组点图中的所有点
- vb.net - IErrorInfo.GetDescription 在 SQL 查询上失败,出现 E_FAIL(0x80004005)
- git - 如何恢复 git 存储库
- javascript - 在ionic 2中禁用移动硬件后退按钮
- vcpkg - 在“顶级”级别列出包?
- r - 绘制带有连续颜色图例的彩色地图
- c# - 错误的事件日志查询
- java - httpSession.getAttribute("userId") 在来自 Angular 前端的一些频繁 API 请求后在 Spring Boot 中返回 null