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

Tkinter程序经PyInstaller打包为exe后主程序控件不显示问题

Tkinter程序PyInstaller打包后主窗口控件不显示问题

本地VS Code运行正常,但PyInstaller打包为.exe后,登录界面能正常工作,登录成功后调用的main_program类仅能生成对应尺寸和背景色的窗口,但所有控件都不显示。

登录界面代码

from config import *
import base64
from PIL import ImageTk,Image
from attribution_tool_main_program_class import main_program
import pandas as pd
import os
import sys
from sql_uploader import azure_sql_connector
from tkinter import Tk,Label,Canvas,Entry,Button, messagebox, Toplevel,mainloop

class login_screen_class():

    def __init__(self):

        self.df  = azure_sql_connector('opr_dev').read_table('SELECT * FROM [dbo].[attribution_username_file]')
        self.root = Tk()
        self.root.withdraw()
        self.login_screen = Toplevel(self.root)
        self.login_screen.title("Attribution Tool - Login")
        self.login_screen.geometry("1920x1080")
        train_icon = self.resource_path('train.ico')
        self.login_screen.iconbitmap(train_icon)
        background_image=self.resource_path('background_image_2.png')
        self.my_img = ImageTk.PhotoImage(Image.open(background_image))
        my_label = Label(self.login_screen,image=self.my_img)
        my_label.grid(row=0,column=0, sticky='N')
        my_canvas1 = Canvas(self.login_screen,bg = "#75787B")
        my_canvas1.grid(row=0,column=0,padx=200,pady=200)
 
        font= "Helvetica, 16"

        user_Name = Label(my_canvas1,text="Username",bg = "#75787B", fg="white",font=font)
        user_Name.grid(row=0,column=0,columnspan=2,pady=10,padx=10,sticky='N')
        self.username_entry = Entry(my_canvas1,width =30,bg = "#75787B",font=font,foreground='white')
        self.username_entry.grid(row=1,column=0,padx=10)
        
        password_name = Label(my_canvas1,text="Password",bg = "#75787B", fg="white",font=font,borderwidth=0)
        password_name.grid(row=2,column=0,columnspan=2,pady=10,padx=10)
        self.password_entry = Entry(my_canvas1,width =30,bg = "#75787B",font=font,foreground='white',show='*')
        self.password_entry.grid(row=3,column=0,padx=10)

        login_image=self.resource_path('login-button-png-7.png')
        my_img_login = ImageTk.PhotoImage(Image.open(login_image))
        sign_in_button = Button(my_canvas1,image=my_img_login, command = lambda: self.username_password_check(), borderwidth=0)
        sign_in_button.grid(row=4,column=0,columnspan=2, pady=10, padx=10)
        self.login_screen.bind_all("<Return>",self.username_password_check)
        mainloop()
    
    def resource_path(self,relative_path):
        try:
            base_path = sys._MEIPASS
        except Exception:
            base_path = os.path.abspath(".")

        return os.path.join(base_path, relative_path)

    def username_password_check(self,event=None):

        self.username = self.username_entry.get().lower()
        password=self.password_entry.get()
        if self.username =="":
            messagebox.showerror("No username entered", "Please enter a valid username to login to Attribution Tool")
        elif password =="":
            messagebox.showerror("No password entered", "Please enter a valid password to login to Attribution Tool")

        login_list =  self.df.values.tolist()
        for record in login_list:
            if record[0].lower() ==self.username:
                if base64.b64decode(record[1]).decode("utf-8") == password:
                    self.login_screen.withdraw()
                    main_program((self.username).capitalize(),self.root)  
                else:        
                    messagebox.showerror("Login Error", "The details you have entered are invalid")
                    break

if __name__ == '__main__':

    login_screen_class()

使用的PyInstaller打包命令

pyinstaller --name Attribution_tool --onefile --windowed --icon=Train.ico --add-data "login-button-png-7.png;." --add-data "background_image_2.png;." --add-data "train.ico;." Attribution_tool_v19.py

问题排查与解决方案

1. 主程序资源路径未正确处理

登录界面用resource_path函数处理资源路径,但main_program类中如果用到图片、配置等外部文件,很可能没做同样处理,导致打包后无法找到资源,控件渲染失败。

  • 把resource_path函数复制到main_program所在模块,或封装成公共函数供所有模块调用,确保所有资源加载都通过该函数获取路径。

2. 主窗口Tk实例管理问题

登录界面创建self.root = Tk()并隐藏,传给main_program后,主程序可能未正确复用这个根实例:

  • 检查main_program的__init__方法,确保基于传入的root参数构建界面,先调用root.deiconify()显示根窗口,再添加控件,不要重新创建Tk()实例(Tkinter仅允许一个根实例)。

3. 控件引用被垃圾回收

Tkinter中,ImageTk.PhotoImage创建的图片若为局部变量,会被Python垃圾回收机制清理,导致控件空白。登录界面把图片绑定到self.my_img,但主程序可能没这么做:

  • 主程序中所有图片对象都要绑定到实例属性(如self.btn_img = ImageTk.PhotoImage(...)),避免被回收。

4. 打包命令遗漏依赖

打包时可能未包含main_program依赖的模块或资源:

  • 若主程序有额外资源文件,添加对应的--add-data参数;
  • 若PyInstaller未自动识别自定义模块(如attribution_tool_main_program_class.py、config.py),在打包命令中加入--hidden-import attribution_tool_main_program_class --hidden-import config --hidden-import sql_uploader;
  • 暂时去掉--windowed参数打包,运行.exe时查看控制台输出的错误信息,快速定位问题(如缺失模块或资源)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 03:09:50