You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Tkinter中Treeview窗口无输出问题求助(Python PostgreSQL开发)

解决Tkinter中Treeview组件空窗口问题

核心问题分析

  1. Treeview父组件绑定错误
    在finestra函数中,创建Treeview时将父组件设为root(主窗口),但实际应该绑定到新创建的finestra(Toplevel弹窗),导致Treeview被渲染到主窗口而非目标弹窗。

  2. 布局方法未执行
    代码中tabella.pack缺少括号,没有调用布局方法,即便Treeview创建正确也无法显示。

  3. 登录逻辑矛盾
    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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 10:02:02