简体   繁体   English

使用pyinstaller后Tkinter更新标签

[英]Tkinter updating label after using pyinstaller

When I run the .py file, the program runs fine as in self.error updates as robocopy is running.当我运行 .py 文件时,程序运行良好,就像在 robocopy 运行时的 self.error 更新中一样。 However after I've changed it to a .exe file using pyinstaller -F -w Shortcutsv2.1.py I've noticed that the tkinter label which shows how many files it has updated (self.error) doesn't update until after the terminal is closed.但是,在我使用pyinstaller -F -w Shortcutsv2.1.py将其更改为 .exe 文件后,我注意到显示它已更新的文件数量(self.error)的 tkinter 标签直到之后才会更新终端已关闭。 Is there a way to have it work like the script?有没有办法让它像脚本一样工作? I'm assuming this is due to a setting in pyinstaller but I may be wrong我假设这是由于 pyinstaller 中的设置,但我可能错了

CODE:代码:

from subprocess import PIPE, run
import tkinter as tk
from tkinter import ttk
import tkinter.messagebox as mb
import tkinter.font as tkFont
from os import path
from os import listdir
from os import mkdir
from os import walk
from glob import glob
import threading
import pandas as pd
from datetime import datetime

class Windows(threading.Thread):

    def __init__(self, master):
        threading.Thread.__init__(self)
        self.width = 400
        self.height = 150
        master.geometry(f"{self.width}x{self.height}")
        master.title("Shortcuts")
        #master.iconbitmap(r'ip.ico')
        self.frame = tk.Frame(master,bg="white")
        self.frame.place(relx=0, rely=0, relwidth=1, relheight=1)
        self.font = ('Helvetica', '10')

        #Source path label and text entry
        self.srcLabel = tk.Label(self.frame, text="Source Path:", font=self.font, bg="white")
        self.srcLabel.place(relx=0.001, rely=0.026, relwidth=0.31, relheight=0.2)
        self.srcEntry = tk.Entry(self.frame, font=self.font, bg="white")
        self.srcEntry.place(relx=0.31, rely=0.026, relwidth=0.68, relheight=0.2)

        #Destination path label and text entry
        self.dstLabel = tk.Label(self.frame, text="Destination Path:", font=self.font, bg="white")
        self.dstLabel.place(relx=0.001, rely=0.246, relwidth=0.31, relheight=0.2)
        self.dstEntry = tk.Entry(self.frame, font=self.font, bg="white")
        self.dstEntry.place(relx=0.31, rely=0.246, relwidth=0.68, relheight=0.2)

        #New Folder to be created label and text entry
        self.nfLabel = tk.Label(self.frame, text="New Folder:", font=self.font, bg="white")
        self.nfLabel.place(relx=0.001, rely=0.466, relwidth=0.31, relheight=0.2)
        self.nfEntry = tk.Entry(self.frame, font=self.font, bg="white")
        self.nfEntry.place(relx=0.31, rely=0.466, relwidth=0.68, relheight=0.2)

        #Submit
        self.submit = tk.Button(self.frame, text="Submit", bg="white", font=self.font,
                                command = self.threadCmd)
        self.submit.place(relx=0.5, rely=0.733, relwidth=0.3, relheight=0.2)

        #Errors
        self.error = tk.Label(self.frame, text="", font=self.font, bg="white", fg="red")
        self.error.place(relx=0.001, rely=0.733, relwidth=0.53, relheight=0.2)

    def findFile(self, dirPath):
        #finds the full path of all files including within the subdirectories
        i = 0
        temp = []
        filesInDir = [f"{dirPath}\\{a}" for a in listdir(dirPath)]
        for a in filesInDir:
            i += 1
            fullPath = path.join(dirPath, a)
            if path.isdir(fullPath):
                temp = temp + self.findFile(fullPath)
            else:
                temp.append(fullPath)
        return temp

    def lowestFolder(self, direc):
        #finds the lowest last folder if any and creates the ~~~~.txt in there to ensure it is the last file to be copied
        subdir = [x[0] for x in walk(direc)]
        subdir.sort()
        if subdir[-1] == direc:
            f = open(path.join(direc,"~~~~.txt"),"w+")
            f.close()
        else:
            self.lowestFolder(str(path.join(direc,subdir[-1])))

    def Run(self):
        if not path.exists(self.srcEntry.get()):
            self.error.config(text="Can't find src path", fg="red")
        elif not path.exists(self.dstEntry.get()):
            self.error.config(text="Can't find dstn path", fg="red")
        else:
            dest = self.dstEntry.get() + "\\" + self.nfEntry.get()
            if path.isdir(dest):
                self.error.config(text="Folder Exists", fg="red")
            else:
                self.error.config(text="")
                self.filename = "logs.xlsx"
                self.listOfFiles = glob(path.join(".",self.filename))

                self.lowestFolder(self.srcEntry.get())

                filesTransferred = self.findFile(self.srcEntry.get())
                length = len(filesTransferred)
                mkdir(dest)
                date = datetime.now()

                run(f"start cmd /K RoboCopy.exe \"{self.srcEntry.get()}\" \"{dest}\" *.* /E /Z", stdout=PIPE, stdin=PIPE, stderr=PIPE, shell=True)

                #Checks if all files have been transferred before moving on
                i = 0
                while(i < length):
                    fullPath = filesTransferred[i].replace(self.srcEntry.get(), dest)
                    if path.exists(fullPath):
                            i += 1
                    self.error.config(text=f'Transferring file(s): {i}/{length}', fg='black')

                temp2 = self.findFile(dest)
                temp2 = [x.replace(dest, "..") for x in temp2]

                if length == len(temp2):
                    #Creates log file if not created
                    if not self.listOfFiles:
                            writer = pd.ExcelWriter(self.filename, engine='xlsxwriter')
                            writer.save()

                    df = pd.read_excel(self.filename)

                    #creates file if it doesn't exist else apppends

                    df2 = pd.DataFrame({"Started" : [date],
                                        "Source": [self.srcEntry.get()],
                                        "Destination": [self.dstEntry.get()],
                                        "Files": [", ".join(temp2)]})
                    df = df.append(df2, sort=False)
                    df.to_excel(self.filename, index=False)
                    self.error.config(text="Files copied successfully.", fg="green")
                    #IF ROBOCOPY FREEZES WHEN YOU CLICK ON IT THEN JUST PRESS TAB AND IT SHOULD RESUME
                else:
                    self.error.config(text="All files were not copied.", fg="red")

    def threadCmd(self):
        self.result = None
        y = threading.Thread(target=self.Run)
        y.start()


if __name__ == "__main__":
    root = tk.Tk()
    x = threading.Thread(target=Windows, args=(root,))
    x.start()
    x.join
    root.mainloop()

EDIT 1编辑 1

" There are couple problems here. 1. Inherit class Windows(threading.Thread): but don't use this object. 2. Passing a class definition as .Thread(target=Windows. 3. Useless x.join without calling it. 4. Accessing tkinter objects, egself.srcEntry.get(), from a Thread. " "这里有几个问题。1. 继承类 Windows(threading.Thread): 但不要使用这个对象。2. 将类定义作为 .Thread(target=Windows. 3. 无用的 x.join 不调用它。 4.从线程访问tkinter对象,例如self.srcEntry.get()。

I've changed the code to the below so now: 1) Can't make this change as I'm using .start() 2) Changed this to an instance 3) called the function 4) Didn't make this change as wasn't sure what the issue was.我现在已将代码更改为以下代码:1) 无法进行此更改,因为我正在使用 .start() 2) 将此更改为实例 3) 调用函数 4) 未进行此更改不知道是什么问题。 Needs more clarification需要更多说明

The issue which I had posted for still persists however I appreciate the help to tidy up my code :)我发布的问题仍然存在,但我感谢您帮助整理我的代码:)

if __name__ == "__main__":
    root = tk.Tk()
    x = Windows(root)
    x.start()
    x.join()
    root.mainloop()

I was using subprocess.run instead of subprocess.Popen , subprocess.run waits for the terminal command to complete before moving on with the script.我使用的是subprocess.run而不是subprocess.Popensubprocess.run在继续执行脚本之前等待终端命令完成。 Whereas subprocess.Popen doesn't.subprocess.Popen没有。

Edit: What I find strange is that when I would run it as a .py file subprocess.run worked the same as subprocess.Popen however when I had used pyinstaller then subprocess.run worked how it's supposed to.编辑:我觉得奇怪的是,当我将运行它作为一个.py文件subprocess.run工作一样subprocess.Popen然而,当我用了pyinstaller然后subprocess.run工作它应该如何。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM