使用 cx_freeze 构建应用程序并执行 .exe 文件后,使用 tkinter 的 GUI 应用程序中的 TreeView 无法正常工作
My TreeView from my GUI app with tkinter doesn't work after I build the app using cx_freeze and executing the .exe file
我用 tkinter 创建了一个应用程序来练习,它类似于一个虚拟钱包来跟踪你的支出。您可以添加不同类别的存款和取款,然后使用 tkinter ttk TreeView 小部件将所有这些都显示在树视图中。这是一张图片,因此更容易理解:
App treeview example
当我 运行 它和我的 main.py 文件一样时,它像任何其他 python 文件一样工作完美,但是当我使用 cx_freeze 将它构建到可执行文件中时,即使构建工作正常并且应用程序 运行s,通过“历史”菜单访问的 TreeView 小部件的站点也不会加载并且显示完全为空,但它不会崩溃或引发任何错误:
App treeview error
这是我的 setup.py 文件代码:
import sys
import os
from cx_Freeze import setup, Executable
application_title = "Monedero App"
main_python_file = "main.py"
PYTHON_INSTALL_DIR = os.path.dirname(sys.executable)
os.environ['TCL_LIBRARY'] = os.path.join(PYTHON_INSTALL_DIR, 'tcl', 'tcl8.6')
os.environ['TK_LIBRARY'] = os.path.join(PYTHON_INSTALL_DIR, 'tcl', 'tk8.6')
base = None
if sys.platform == "win64":
base = "Win64GUI"
elif sys.platform == "win32":
base = "Win32GUI"
options = {
"build_exe": {
"packages": ["tkinter", "tkinter.ttk", "shelve", "datetime"],
"include_files": [
"D:\Programacion\Projects and exercices\Monedero\imagenes\logo.ico",
(os.path.join(PYTHON_INSTALL_DIR, 'DLLs', 'tk86t.dll'), os.path.join('lib', 'tk86t.dll')),
(os.path.join(PYTHON_INSTALL_DIR, 'DLLs', 'tcl86t.dll'), os.path.join('lib', 'tcl86t.dll')),
],
}
}
setup(
name = application_title,
version = "0.1",
description = "Test 1",
options = options,
executables = [Executable(main_python_file, base=base)],
)
另一个重要的部分是我使用 shelve python 库来保存我的数据。我这样做是因为首先我使用 sqlite 来做,但我遇到了同样的问题,我认为 sqlite 可能是问题所在。现在我不知道可能是什么问题。
我还会附上 TreeView 小部件配置函数代码,以防我从那里更改一些内容:
def configure(self):
self.parent.refresh()
try:
self.historial_frame.destroy()
except:
pass
self.title.config(
fg = "white",
bg = "black",
font = ("Arial", 30),
padx = 110,
pady = 20
)
self.title.pack(side = tk.TOP, fill = tk.X, expand = tk.YES)
self.historial_frame = tk.Frame(self)
style = ttk.Style()
style.configure("mystyle.Treeview", highlightthickness = 0, bd = 0, font = ('Calibri', 11)) # Modify the font of the body
style.configure("mystyle.Treeview.Heading", font = ('Calibri', 13,'bold')) # Modify the font of the headings
style.layout("mystyle.Treeview", [('mystyle.Treeview.treearea', {'sticky': 'nswe'})]) # Remove the borders
self.historial = ttk.Treeview(self.historial_frame, columns = ('Fecha', 'Cantidad', 'Descripción'), style = "mystyle.Treeview", height = 10)
self.historial.column("#0", width = 150, stretch = tk.NO)
self.historial.column("#1", width = 150, stretch = tk.NO)
self.historial.column("#2", width = 100, stretch = tk.NO)
self.historial.column("#3", width = 200, minwidth = 100, stretch = tk.YES)
self.historial.heading("#0", text = "Categoría", anchor = tk.W)
self.historial.heading("#1", text = "Fecha", anchor = tk.W)
self.historial.heading("#2", text = "Cantidad", anchor = tk.W)
self.historial.heading("#3", text = "Descripción", anchor = tk.W)
self.historial.grid(row=0, column=0, columnspan=15, padx=10, pady=10, sticky="nsew")
scrollbar = ttk.Scrollbar(self.historial_frame, orient = tk.VERTICAL, command = self.historial.yview)
scrollbar.grid(row=0, column=15, sticky="nse", pady="10")
self.historial.configure(yscrollcommand = scrollbar.set)
self.parent.import_categories()
total = self.fill_historial()
totalLabel = tk.Label(self.historial_frame, text = "Balance total: ")
totalLabel.config(font = ('Calibri', 13))
totalLabel.grid(row = 1, column = 0, sticky = "w", pady = 10, padx = 5)
total_dato = tk.StringVar()
total_dato.set("{:.2f}".format(total) + " €")
totalLabel_dato = tk.Label(self.historial_frame, textvariable = total_dato, justify = 'left')
totalLabel_dato.config(font = ('Calibri', 13))
totalLabel_dato.grid(row = 1, column = 1, sticky = "w", pady = 10, padx = 5)
self.historial.tag_configure('odd', font = 'Calibri 13')
deleteLabel = tk.Label(self.historial_frame, text = "Eliminar registro: ")
deleteLabel.grid(row = 1, column = 3, sticky = "w", pady = 10, padx = 5)
deleteButton = tk.Button(self.historial_frame, text="Borrar", command=self.delete_register)
deleteButton.grid(row = 1, column = 4, sticky = "w", pady = 10, padx = 5)
self.historial_frame.pack()
self.pack(fill = "both")
因此,如果有人知道发生了什么,我们将不胜感激。如果需要更多信息,请询问。代码或图片上的西班牙名字和文字是因为我来自西班牙:)。
谢谢!
这是一个替代方法,使用 pyinstaller
。
在你的终端说:
pip install pyinstaller
然后在终端中使用这个命令,比如
pyinstaller -F -w -i"path.ico" name.py
这里,
-w
表示程序应该是窗口化的,因为它使用 GUI
-F
表示程序应该做成一个文件而不是一个目录
-i"path.ico"
这可用于为您的 exe 设置图标
并确保使用 dist
文件夹中的 exe,如果您使用任何图像文件,则将 exe 复制到项目目录。
Take a look at the documentation
希望它消除了您的疑问,如果有任何错误请告诉我
干杯
我用 tkinter 创建了一个应用程序来练习,它类似于一个虚拟钱包来跟踪你的支出。您可以添加不同类别的存款和取款,然后使用 tkinter ttk TreeView 小部件将所有这些都显示在树视图中。这是一张图片,因此更容易理解:
App treeview example
当我 运行 它和我的 main.py 文件一样时,它像任何其他 python 文件一样工作完美,但是当我使用 cx_freeze 将它构建到可执行文件中时,即使构建工作正常并且应用程序 运行s,通过“历史”菜单访问的 TreeView 小部件的站点也不会加载并且显示完全为空,但它不会崩溃或引发任何错误:
App treeview error
这是我的 setup.py 文件代码:
import sys
import os
from cx_Freeze import setup, Executable
application_title = "Monedero App"
main_python_file = "main.py"
PYTHON_INSTALL_DIR = os.path.dirname(sys.executable)
os.environ['TCL_LIBRARY'] = os.path.join(PYTHON_INSTALL_DIR, 'tcl', 'tcl8.6')
os.environ['TK_LIBRARY'] = os.path.join(PYTHON_INSTALL_DIR, 'tcl', 'tk8.6')
base = None
if sys.platform == "win64":
base = "Win64GUI"
elif sys.platform == "win32":
base = "Win32GUI"
options = {
"build_exe": {
"packages": ["tkinter", "tkinter.ttk", "shelve", "datetime"],
"include_files": [
"D:\Programacion\Projects and exercices\Monedero\imagenes\logo.ico",
(os.path.join(PYTHON_INSTALL_DIR, 'DLLs', 'tk86t.dll'), os.path.join('lib', 'tk86t.dll')),
(os.path.join(PYTHON_INSTALL_DIR, 'DLLs', 'tcl86t.dll'), os.path.join('lib', 'tcl86t.dll')),
],
}
}
setup(
name = application_title,
version = "0.1",
description = "Test 1",
options = options,
executables = [Executable(main_python_file, base=base)],
)
另一个重要的部分是我使用 shelve python 库来保存我的数据。我这样做是因为首先我使用 sqlite 来做,但我遇到了同样的问题,我认为 sqlite 可能是问题所在。现在我不知道可能是什么问题。
我还会附上 TreeView 小部件配置函数代码,以防我从那里更改一些内容:
def configure(self):
self.parent.refresh()
try:
self.historial_frame.destroy()
except:
pass
self.title.config(
fg = "white",
bg = "black",
font = ("Arial", 30),
padx = 110,
pady = 20
)
self.title.pack(side = tk.TOP, fill = tk.X, expand = tk.YES)
self.historial_frame = tk.Frame(self)
style = ttk.Style()
style.configure("mystyle.Treeview", highlightthickness = 0, bd = 0, font = ('Calibri', 11)) # Modify the font of the body
style.configure("mystyle.Treeview.Heading", font = ('Calibri', 13,'bold')) # Modify the font of the headings
style.layout("mystyle.Treeview", [('mystyle.Treeview.treearea', {'sticky': 'nswe'})]) # Remove the borders
self.historial = ttk.Treeview(self.historial_frame, columns = ('Fecha', 'Cantidad', 'Descripción'), style = "mystyle.Treeview", height = 10)
self.historial.column("#0", width = 150, stretch = tk.NO)
self.historial.column("#1", width = 150, stretch = tk.NO)
self.historial.column("#2", width = 100, stretch = tk.NO)
self.historial.column("#3", width = 200, minwidth = 100, stretch = tk.YES)
self.historial.heading("#0", text = "Categoría", anchor = tk.W)
self.historial.heading("#1", text = "Fecha", anchor = tk.W)
self.historial.heading("#2", text = "Cantidad", anchor = tk.W)
self.historial.heading("#3", text = "Descripción", anchor = tk.W)
self.historial.grid(row=0, column=0, columnspan=15, padx=10, pady=10, sticky="nsew")
scrollbar = ttk.Scrollbar(self.historial_frame, orient = tk.VERTICAL, command = self.historial.yview)
scrollbar.grid(row=0, column=15, sticky="nse", pady="10")
self.historial.configure(yscrollcommand = scrollbar.set)
self.parent.import_categories()
total = self.fill_historial()
totalLabel = tk.Label(self.historial_frame, text = "Balance total: ")
totalLabel.config(font = ('Calibri', 13))
totalLabel.grid(row = 1, column = 0, sticky = "w", pady = 10, padx = 5)
total_dato = tk.StringVar()
total_dato.set("{:.2f}".format(total) + " €")
totalLabel_dato = tk.Label(self.historial_frame, textvariable = total_dato, justify = 'left')
totalLabel_dato.config(font = ('Calibri', 13))
totalLabel_dato.grid(row = 1, column = 1, sticky = "w", pady = 10, padx = 5)
self.historial.tag_configure('odd', font = 'Calibri 13')
deleteLabel = tk.Label(self.historial_frame, text = "Eliminar registro: ")
deleteLabel.grid(row = 1, column = 3, sticky = "w", pady = 10, padx = 5)
deleteButton = tk.Button(self.historial_frame, text="Borrar", command=self.delete_register)
deleteButton.grid(row = 1, column = 4, sticky = "w", pady = 10, padx = 5)
self.historial_frame.pack()
self.pack(fill = "both")
因此,如果有人知道发生了什么,我们将不胜感激。如果需要更多信息,请询问。代码或图片上的西班牙名字和文字是因为我来自西班牙:)。
谢谢!
这是一个替代方法,使用 pyinstaller
。
在你的终端说:
pip install pyinstaller
然后在终端中使用这个命令,比如
pyinstaller -F -w -i"path.ico" name.py
这里,
-w
表示程序应该是窗口化的,因为它使用 GUI-F
表示程序应该做成一个文件而不是一个目录-i"path.ico"
这可用于为您的 exe 设置图标
并确保使用 dist
文件夹中的 exe,如果您使用任何图像文件,则将 exe 复制到项目目录。
Take a look at the documentation
希望它消除了您的疑问,如果有任何错误请告诉我
干杯