Tkinter中Treeview窗口无输出问题求助(Python PostgreSQL开发)
解决Tkinter中Treeview组件空窗口问题
核心问题分析
Treeview父组件绑定错误
在finestra函数中,创建Treeview时将父组件设为root(主窗口),但实际应该绑定到新创建的finestra(Toplevel弹窗),导致Treeview被渲染到主窗口而非目标弹窗。布局方法未执行
代码中tabella.pack缺少括号,没有调用布局方法,即便Treeview创建正确也无法显示。登录逻辑矛盾
paginaLogin里的vai_menu函数存在逻辑错误:先判断用户名和密码不为空,接着又判断两者为空才跳转,永远无法触发正确的登录跳转。
修复后的关键代码片段
修正finestra函数
def finestra(conn): finestra = tk.Toplevel() finestra.geometry('1200x1000') colonne = ('Nome', 'Cognome','Codice Fiscale','E-mail','Telefono','Luogo di nascita','Data di nascita','Residenza','CAP','Indirizzo') # 将Treeview的父组件改为finestra tabella = ttk.Treeview(finestra, columns=colonne, show='headings') stile=ttk.Style(finestra) stile.theme_use('clam') # 调整列宽避免内容截断 tabella.column('Nome',width=80,minwidth=50,anchor=tk.CENTER) tabella.column('Cognome',width=80,minwidth=50,anchor=tk.CENTER) tabella.column('Codice Fiscale',width=120,minwidth=80,anchor=tk.CENTER) tabella.column('E-mail',width=150,minwidth=100,anchor=tk.CENTER) tabella.column('Telefono',width=100,minwidth=70,anchor=tk.CENTER) tabella.column('Luogo di nascita',width=120,minwidth=80,anchor=tk.CENTER) tabella.column('Data di nascita',width=100,minwidth=70,anchor=tk.CENTER) tabella.column('Residenza',width=120,minwidth=80,anchor=tk.CENTER) tabella.column('CAP',width=60,minwidth=50,anchor=tk.CENTER) tabella.column('Indirizzo',width=150,minwidth=100,anchor=tk.CENTER) # 修正Indirizzo的表头文本错误 tabella.heading ('Nome',text='Nome',anchor=tk.CENTER) tabella.heading ('Cognome',text='Cognome',anchor=tk.CENTER) tabella.heading ('Codice Fiscale',text='Codice Fiscale',anchor=tk.CENTER) tabella.heading ('E-mail',text='E-mail',anchor=tk.CENTER) tabella.heading ('Telefono',text='Telefono',anchor=tk.CENTER) tabella.heading ('Luogo di nascita',text='Luogo di nascita',anchor=tk.CENTER) tabella.heading ('Data di nascita',text='Data di nascita',anchor=tk.CENTER) tabella.heading ('Residenza',text='Residenza',anchor=tk.CENTER) tabella.heading ('CAP',text='CAP',anchor=tk.CENTER) tabella.heading ('Indirizzo',text='Indirizzo',anchor=tk.CENTER) cur = conn.cursor() cur.execute('set search_path to DBFag;') cur.execute('SELECT * FROM vistaSoci') rows = cur.fetchall() for i in rows: tabella.insert('', 'end', values=i) tabella.pack(fill=tk.BOTH, expand=True) # 调用pack方法并添加填充参数
修正vai_menu函数
def vai_menu (): if(username.get()!='' and password.get()!=''): conn = db_login(nomeUtente=username.get(), passwordUtente=password.get()) if conn is not None: login.destroy() paginaMenu(conn) else: errore('Username o Password errati riprova') else: errore('Inserisci username e password')
完整修正代码
import psycopg2 import tkinter as tk from tkinter import ttk from tkinter import messagebox root = tk.Tk() root.title('DB') root.geometry('1500x1200') root.minsize(1600, 1200) root.maxsize(root.winfo_screenwidth(), root.winfo_screenheight()) def main(): paginaLogin() def errore(msg): messagebox.showerror('', msg) def paginaLogin(): def db_login(nomeUtente, passwordUtente): conn = None try: conn = psycopg2.connect( host='localhost', dbname='MyDB', user=nomeUtente, password=passwordUtente, port='5432' ) return conn except Exception as error: return conn def vai_menu(): if username.get() != '' and password.get() != '': conn = db_login(nomeUtente=username.get(), passwordUtente=password.get()) if conn is not None: login.destroy() paginaMenu(conn) else: errore('Username o Password errati riprova') else: errore('Inserisci username e password') login = tk.Frame(root) stringaUtente = tk.Label(login, text='Inserisci il nome utente', font=('Bold',25), bg='light blue') stringaUtente.place(x=180, y=100) username = tk.Entry(login, font=('Bold',15)) username.place(x=160, y=150, height=50, width=300) stringaPassword = tk.Label(login, text='Inserisci la password', font=('Bold',25), bg='light blue') stringaPassword.place(x=200, y=300) password = tk.Entry(login, font=('Bold',15), show='*') password.place(x=160, y=350, height=50, width=300) bottone = tk.Button(login, text='login', font=('Bold',15), bg='blue', fg='black', command=vai_menu) bottone.place(x=120, y=550, height=50, width=350) login.pack(padx=100, pady=100) login.pack_propagate(False) login.configure(height=800, width=600, bg='grey') def paginaMenu(conn): def vai_login(): menu.destroy() paginaLogin() def vai_bilanci(): menu.destroy() paginaBilanci(conn) def finestra(conn): finestra = tk.Toplevel() finestra.geometry('1200x1000') colonne = ('Nome', 'Cognome','Codice Fiscale','E-mail','Telefono','Luogo di nascita','Data di nascita','Residenza','CAP','Indirizzo') tabella = ttk.Treeview(finestra, columns=colonne, show='headings') stile = ttk.Style(finestra) stile.theme_use('clam') tabella.column('Nome', width=80, minwidth=50, anchor=tk.CENTER) tabella.column('Cognome', width=80, minwidth=50, anchor=tk.CENTER) tabella.column('Codice Fiscale', width=120, minwidth=80, anchor=tk.CENTER) tabella.column('E-mail', width=150, minwidth=100, anchor=tk.CENTER) tabella.column('Telefono', width=100, minwidth=70, anchor=tk.CENTER) tabella.column('Luogo di nascita', width=120, minwidth=80, anchor=tk.CENTER) tabella.column('Data di nascita', width=100, minwidth=70, anchor=tk.CENTER) tabella.column('Residenza', width=120, minwidth=80, anchor=tk.CENTER) tabella.column('CAP', width=60, minwidth=50, anchor=tk.CENTER) tabella.column('Indirizzo', width=150, minwidth=100, anchor=tk.CENTER) tabella.heading('Nome', text='Nome', anchor=tk.CENTER) tabella.heading('Cognome', text='Cognome', anchor=tk.CENTER) tabella.heading('Codice Fiscale', text='Codice Fiscale', anchor=tk.CENTER) tabella.heading('E-mail', text='E-mail', anchor=tk.CENTER) tabella.heading('Telefono', text='Telefono', anchor=tk.CENTER) tabella.heading('Luogo di nascita', text='Luogo di nascita', anchor=tk.CENTER) tabella.heading('Data di nascita', text='Data di nascita', anchor=tk.CENTER) tabella.heading('Residenza', text='Residenza', anchor=tk.CENTER) tabella.heading('CAP', text='CAP', anchor=tk.CENTER) tabella.heading('Indirizzo', text='Indirizzo', anchor=tk.CENTER) cur = conn.cursor() cur.execute('set search_path to DBFag;') cur.execute('SELECT * FROM vistaSoci') rows = cur.fetchall() for i in rows: tabella.insert('', 'end', values=i) tabella.pack(fill=tk.BOTH, expand=True) menu = tk.Frame(root) bottone = tk.Button(menu, text='Vai a login', font=('Bold',15), bg='blue', fg='black', command=vai_login) bottone.place(x=0, y=0, height=50, width=1400) stringaUtente = tk.Label(menu, text='Inserisci aggiorna o elimina uno di questi campi', font=('Bold',25), bg='light blue', height=2, width=100) stringaUtente.place(x=-40, y=150) bottone = tk.Button(menu, text='Soci', font=('Bold',30), bg='blue', fg='black', command=vai_login) bottone.place(x=100, y=300, height=50, width=250) bottone = tk.Button(menu, text='Tessere', font=('Bold',30), bg='blue', fg='black', command=vai_login) bottone.place(x=400, y=300, height=50, width=250) bottone = tk.Button(menu, text='Entrate', font=('Bold',30), bg='blue', fg='black', command=vai_login) bottone.place(x=700, y=300, height=50, width=250) bottone = tk.Button(menu, text='Uscite', font=('Bold',30), bg='blue', fg='black', command=vai_login) bottone.place(x=1000, y=300, height=50, width=250) stringaUtente = tk.Label(menu, text='Visualizza uno di questi campi', font=('Bold',25), bg='light blue', height=2, width=100) stringaUtente.place(x=-40, y=500) bottone = tk.Button(menu, text='Bilanci', font=('Bold',50), bg='blue', fg='black', command=vai_bilanci) bottone.place(x=250, y=600, height=100, width=950) bottone = tk.Button(menu, text='Soci', font=('Bold',30), bg='blue', fg='black', command=lambda:finestra(conn)) bottone.place(x=200, y=800, height=70, width=450) bottone = tk.Button(menu, text='Tessere', font=('Bold',30), bg='blue', fg='black', command=vai_login) bottone.place(x=800, y=800, height=70, width=450) menu.pack(padx=100, pady=100) menu.pack_propagate(False) menu.configure(height=1200, width=1500, bg='grey') def paginaBilanci(conn): cur = conn.cursor() def vai_menu(): bilanci.destroy() paginaMenu(conn) bilanci = tk.Frame(root) goBack_btn = tk.Button(bilanci, text='X', font=('Bold', 30), bd=0, command=vai_menu) goBack_btn.pack(side=tk.TOP, anchor=tk.E) cur.execute('set search_path to DBFag;') cur.execute('SELECT * FROM Rendiconto') val = cur.fetchall() stringaRendiconto = tk.Label(bilanci, text=str(val), font=('Bold',15), bg='light blue', height=10, width=100) stringaRendiconto.place(x=-40, y=100) bilanci.pack(padx=100, pady=100) bilanci.pack_propagate(False) bilanci.configure(height=1200, width=1500, bg='grey') main() root.mainloop()
额外优化建议
- 可以在
paginaBilanci中也使用Treeview展示数据,比Label更美观易读 - 为数据库操作添加异常捕获,避免程序崩溃
- 统一按钮的回调函数,避免重复代码
内容的提问来源于stack exchange,提问作者RandomGuy
相关产品推荐
相关产品推荐

