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

Tkinter调用第二个脚本时窗口空白问题求助

排查Tkinter多脚本程序中PDF查看器窗口空白问题及同类问题预防

问题描述

我用Python开发了一个包含登录、主页面、仪器申请和PDF查看器的多脚本程序,目前登录、主页面和PDF查看器模块已完成。登录与主页面功能正常,登录后主页面销毁登录窗口并保留数据,但调用SchedaTecnica类(PDF查看器脚本)时,弹出的窗口为空白状态,希望排查原因,同时担心仪器申请模块出现类似问题,寻求解决建议。

主脚本代码

import pandas
import sqlite3
from tkinter import ttk
import tkinter as tk
from tkinter import messagebox
import login
from PIL import ImageTk, Image
import richiesta_strumentario
import schede_tecniche

class MainPage(tk.Tk):
    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)
        self.wm_title("Richiesta Strumentario")
        self.wm_geometry("300x300")
        self.update()
    
        """immagine pagina"""
        menu_image = Image.open(globus_image)
        menu_image = menu_image.resize((self.winfo_width()-10,int(self.winfo_height()/2)), Image.ANTIALIAS)
        menu_image = ImageTk.PhotoImage(menu_image)

        label1 = tk.Label(image=menu_image)
        label1.image = menu_image
        label1.place(x= 2, y = 0)

        """script"""
        benvenuto_label = tk.Label(self, text=f"Benvenuto, {data[0]}")
        benvenuto_label.place(x=10, y=150)


        rich_strum_button = tk.Button(self, text='Richiesta\nStrumentario', height=5, width=19)
        rich_strum_button.config(command=lambda: richiesta_strumentario.RichStrum())
        rich_strum_button.place(x=5, y=180)
        visual_pdf_button = tk.Button(self, text='Visualizza\nSchede Tecniche', height=5, width=18)
        visual_pdf_button.config(command=lambda: schede_tecniche.SchedaTecnica())
        visual_pdf_button.place(x=157, y=180)

        exit_button = tk.Button(self, text='Exit', width=40, height=1, command=lambda: self.quit())
        exit_button.place(x=5, y=270)

if __name__ == '__main__':
    """con = sqlite3.connect("user_db.db")
    cur = con.cursor()
    cur.execute("CREATE TABLE IF NOT EXISTS user(name, surname, email, password, azienda)")
    con.close()"""
    """Login().mainloop()"""#utilizzare questo per script finale
    """data = Login.data"""#utilizzare questo per script finale
    data = ["test", "test", "test", "test", "test"]
    MainPage().mainloop()

PDF查看器脚本代码

import tkinter as tk
from tkinter import ttk
import os
from tkPDFViewer import tkPDFViewer as pdf

class ShowPdf(pdf.ShowPdf):

    def goto(self, page):
        try:
            self.text.see(self.img_object_li[page - 1])
        except IndexError:
            if self.img_object_li:
                self.text.see(self.img_object_li[-1])



class SchedaTecnica(tk.Tk):
    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)
        self.geometry("870x600")
        self.attributes("-topmost", True)
        self.focus_force()

        def show_pdf(*args):
            for widget in pdfframe.winfo_children():
                widget.destroy()

            pdf.ShowPdf.img_object_li.clear()
            file = listbox_pdffile.get(tk.ANCHOR)
            pdfview_frame = pdf.ShowPdf().pdf_view(pdfframe, pdf_location=f"{path_cartella_pdf}{file}.pdf",
                                               width=80, height=50)
            pdfview_frame.pack(fill=tk.BOTH)


        pdf_files = []

        for file in os.listdir(path_cartella_pdf):
            if file.endswith('.pdf') and os.path.isfile(os.path.join(path_cartella_pdf, file)):
                pdf_files.append(os.path.splitext(file)[0])

        var = tk.Variable(value=pdf_files)
        listbox_pdffile = tk.Listbox(self, listvariable=var, width=30, selectmode=tk.SINGLE)
        scroll_bar = tk.Scrollbar(self)
        scroll_bar.pack(side=tk.LEFT)
        listbox_pdffile.pack(side=tk.LEFT, fill=tk.Y)
        listbox_pdffile.bind('<<ListboxSelect>>', show_pdf)

        #quit_window = tk.Button(self, text='QUIT', command=lambda: self.destroy()).place(x=200, y=3)

        pdfframe = tk.Frame(self, width=80, height=50)
        pdfframe.pack()

问题原因分析

  1. 多tk.Tk实例冲突:Tkinter程序应仅存在一个主tk.Tk实例,MainPage已继承tk.Tk,SchedaTecnica再继承tk.Tk会创建第二个Tk实例,导致界面渲染异常,这是窗口空白的核心原因。
  2. path_cartella_pdf未定义:脚本中直接使用该变量但未赋值,导致无法遍历PDF文件,列表框无内容;同时加载PDF时路径无效,无法显示内容。
  3. Scrollbar未绑定Listbox:滚动条创建后未与列表框关联,无法正常工作,虽不直接导致空白,但属于功能缺陷。
  4. 自定义ShowPdf类未生效:自定义了扩展类,但加载PDF时仍使用原pdf.ShowPdf,自定义逻辑未被调用。

解决建议

1. 替换子窗口继承类

将SchedaTecnica改为继承tk.Toplevel,并传入主窗口作为父组件:

class SchedaTecnica(tk.Toplevel):
    def __init__(self, parent, *args, **kwargs):
        tk.Toplevel.__init__(self, parent, *args, **kwargs)
        # 后续代码保持不变

主脚本调用时传入当前窗口:

visual_pdf_button.config(command=lambda: schede_tecniche.SchedaTecnica(self))

2. 定义PDF文件夹路径

添加PDF存储路径的赋值,确保路径正确:

path_cartella_pdf = "./pdfs/"  # 根据实际存储路径修改,确保末尾带斜杠

3. 绑定Scrollbar与Listbox

修正滚动条的关联配置:

scroll_bar = tk.Scrollbar(self, command=listbox_pdffile.yview)
listbox_pdffile.config(yscrollcommand=scroll_bar.set)
scroll_bar.pack(side=tk.LEFT, fill=tk.Y)

4. 使用自定义ShowPdf类

修改show_pdf函数中的实例化逻辑:

pdfview_frame = ShowPdf().pdf_view(pdfframe, pdf_location=f"{path_cartella_pdf}{file}.pdf", width=80, height=50)

5. 添加异常捕获

在加载PDF的逻辑中加入异常处理,便于定位问题:

def show_pdf(*args):
    for widget in pdfframe.winfo_children():
        widget.destroy()
    pdf.ShowPdf.img_object_li.clear()
    file = listbox_pdffile.get(tk.ANCHOR)
    pdf_path = f"{path_cartella_pdf}{file}.pdf"
    try:
        if not os.path.exists(pdf_path):
            raise FileNotFoundError(f"PDF文件不存在: {pdf_path}")
        pdfview_frame = ShowPdf().pdf_view(pdfframe, pdf_location=pdf_path, width=80, height=50)
        pdfview_frame.pack(fill=tk.BOTH)
    except Exception as e:
        tk.messagebox.showerror("错误", f"加载PDF失败: {str(e)}")

仪器申请模块同类问题预防建议

  • 统一使用Toplevel作为子窗口:所有从主页面弹出的功能窗口都继承tk.Toplevel,避免创建多个tk.Tk实例。
  • 提前定义核心变量:确保路径、配置等核心变量在使用前完成赋值,避免未定义错误。
  • 添加异常处理:对文件操作、数据库交互等可能出错的环节添加异常捕获,快速定位问题。
  • 检查组件绑定:确保滚动条、下拉框等交互组件的关联配置正确,避免功能失效。

内容的提问来源于stack exchange,提问作者Nico

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 23:04:55