Heim > Artikel > Backend-Entwicklung > Beispiel-Tutorial zur Entwicklung von Python-GUI-Programmen in Windows mit wxPython und py2exe
Python unterstützt die visuelle Programmierung, also das Schreiben von GUI-Programmen. Sie können damit Ihre bevorzugten Desktop-Programme schreiben. Die Verwendung von wxPython zum Erstellen einer Schnittstelle ist sehr einfach, Sie können jedoch keine Steuerelemente wie C# ziehen und müssen das Codelayout selbst schreiben. Gibt es nach Abschluss des Schreibens ein Tool, das für die Ausführung auf jedem Computer gepackt werden kann, da die direkte py-Datei nicht auf einem Computer ausgeführt werden kann, auf dem Python nicht installiert ist? Ich habe festgestellt, dass py2exe diese Funktion einfach ausführen kann. Sowohl wxPython als auch py2exe sind freie Open-Source-Software.
Umgebungskonfiguration
wxPython: Sourceforge-Projektseite https://sourceforge.net/projects/py2exe/files/py2exe/0.6.9/
Doppelklicken Sie nach dem Herunterladen zum Installieren. Das Installationsprogramm wird automatisch in den entsprechenden Python-Skripten installiert.
py2exe: Offizielle Download-Homepage https://www.wxpython.org/download.php
Sie können es auch installieren, indem Sie darauf doppelklicken. Achten Sie auf die Python-Version, die Sie herunterladen möchten.
Die folgenden Beispiele veranschaulichen die einfache Verwendung von wxPython und py2exe.
Grundlegendes Beispiel
Dateiname: wxTest.py:
# -*- coding: cp936 -*- '''MainWindow类完成最简单的编辑功能,添加一个主菜单,两个子菜单(about和exit)''' import wx class MainWindow(wx.Frame): '''定义一个窗口类''' def __init__(self, parent, title): wx.Frame.__init__(self, parent, title=title, size=(300, 300)) self.control = wx.TextCtrl(self, style=wx.TE_MULTILINE) self.setupMenuBar() self.Show(True) def setupMenuBar(self): self.CreateStatusBar() menubar = wx.MenuBar() menufile = wx.Menu() mnuabout = menufile.Append(wx.ID_ABOUT, '&About', 'about this shit') mnuexit = menufile.Append(wx.ID_EXIT, 'E&xit', 'end program') menubar.Append(menufile, '&File') #事件绑定 self.Bind(wx.EVT_MENU, self.onAbout, mnuabout) self.Bind(wx.EVT_MENU, self.onExit, mnuexit) self.SetMenuBar(menubar) def onAbout(self, evt): '''点击about的事件响应''' dlg = wx.MessageDialog(self, 'This app is a simple text editor', 'About my app', wx.OK) dlg.ShowModal() dlg.Destroy() def onExit(self, evt): '''点击退出''' self.Close(True) app = wx.App(False) frame = MainWindow(None, 'Small Editor') app.MainLoop() #循环监听事件
Nachdem Sie die geänderte Datei bearbeitet haben, kompilieren Sie das Python-Skript mit py2exe in eine ausführbare Windows-Datei, sodass kein Python-Interpreter erforderlich ist. Um py2exe verwenden zu können, müssen Sie zunächst ein Kompilierungsskript schreiben und dann das Kompilierungsskript über Python ausführen, um andere Skripts in ausführbare Dateien zu kompilieren. Das folgende Beispiel ist ein Skript, das in eine ausführbare Datei kompiliert wird: Dateiname: setup.py
import distutils import py2exe distutils.core.setup(windows=['wxTest.py'])
Neben dem Import der notwendigen Module gibt es in setup.py nur eine Anweisung:
distutils.core.setup(windows=['wxTest.py'])
Die eckigen Klammern geben den Namen des zu kompilierenden Skripts an, und die Fenster davor bedeuten, dass es in ein GUI-Programm kompiliert wird. Wenn Sie eine ausführbare Datei für die Befehlszeilenschnittstelle kompilieren möchten, ändern Sie einfach Windows in die Konsole. Wenn Sie das Skript in einen Windows-Dienst kompilieren müssen, können Sie die Service-Option verwenden.
Nachdem Sie alles bearbeitet haben, legen Sie wxTest.py und setup.py im selben Pfad ab, geben Sie den Pfad mit cmd ein und geben Sie Folgendes ein:
setup.py py2exe
error: MSVCP90.dll: No such file or directory
ImportError: No module named sip
setup.py py2exe --includes sip
Nach der Ausführung werden im Pfad zwei Verzeichnisse, dist und build, generiert. Das Verzeichnis dist enthält die durch die Kompilierung generierten Dateien. Wenn Sie das kompilierte Programm auf anderen Computern ausführen möchten, auf denen Python nicht installiert ist, kopieren Sie einfach das Verzeichnis dist auf andere Computer. Doppelklicken Sie, um wxTest.exe auszuführen, wie in der Abbildung gezeigt:
Verwenden Sie wxPython, um ein GUI-Tool zur Berechnung der Datei md5 zu erstellen
Das Gadget sieht schließlich so aus. Ziehen Sie die Datei darauf und ihr MD5 und ihre Größe werden automatisch berechnet
Das Folgende ist der vollständige Code
#coding:gbk import wx import optparse import time,hashlib import threading import os def checkMD5(pefile): try: f = open(pefile,'rb') data = f.read() m = hashlib.md5() m.update(data) f.close() return m.hexdigest() except: return 'error' def getFileSize(filename): try: size = int(os.path.getsize(filename)) return size except: return 'error' #线程函数 class FuncThread(threading.Thread): def __init__(self, func, *params, **paramMap): threading.Thread.__init__(self) self.func = func self.params = params self.paramMap = paramMap self.rst = None self.finished = False def run(self): self.rst = self.func(*self.params, **self.paramMap) self.finished = True def getResult(self): return self.rst def isFinished(self): return self.finished def doInThread(func, *params, **paramMap): t_setDaemon = None if 't_setDaemon' in paramMap: t_setDaemon = paramMap['t_setDaemon'] del paramMap['t_setDaemon'] ft = FuncThread(func, *params, **paramMap) if t_setDaemon != None: ft.setDaemon(t_setDaemon) ft.start() return ft class FileDropTarget(wx.FileDropTarget): def __init__(self, filetext,md5tx,filesizetx): wx.FileDropTarget.__init__(self) self.filepath = filetext self.md5tx = md5tx self.filesizetx = filesizetx def OnDropFiles(self, x, y, fileNames): filename = fileNames[0].encode('gbk') print filename print type(filename) self.filepath.SetValue(filename) md5 = doInThread(checkMD5,filename) filesize = doInThread(getFileSize,filename) while True: if not md5.isFinished(): time.sleep(0.5) else: self.md5tx.SetValue(md5.getResult()) break while True: if not filesize.isFinished(): time.sleep(0.5) else: self.filesizetx.SetValue(str(filesize.getResult())) break class Frame(wx.Frame): #Frame 进行初始化 def __init__(self,title): wx.Frame.__init__(self,None,title=title,size = (400,300)) boxSizer = wx.BoxSizer(wx.VERTICAL) self.panel = wx.Panel(self) # boxSizer.Add(self.panel,1,wx.EXPAND|wx.ALL) #wx.ALL 周围的距离,EXPAND扩充到全部 filepath = wx.StaticText(self.panel,-1,"FileDir(请将文件拖到本对话框中)") filetext = wx.TextCtrl(self.panel,-1,"",size=(350,20)) md5st = wx.StaticText(self.panel,-1,"MD5") md5tx = wx.TextCtrl(self.panel,-1,size=(250,20)) filesizest = wx.StaticText(self.panel,-1,'FileSize') filesizetx = wx.TextCtrl(self.panel,-1,size=(250,20)) # hashst = wx.StaticText(self.panel,-1,'Hash') # hashtx = wx.TextCtrl(self.panel,-1,size=(250,20)) boxSizer.Add(filepath,0,wx.EXPAND|wx.LEFT|wx.TOP,border=10) boxSizer.Add(filetext,0,wx.LEFT|wx.TOP,border=10) boxSizer.Add((-1,20)) boxSizer.Add(md5st,0,wx.LEFT|wx.TOP,border=10) boxSizer.Add(md5tx,0,wx.LEFT|wx.TOP,border=10) boxSizer.Add((-1,10)) boxSizer.Add(filesizest,0,wx.LEFT|wx.TOP,border=10) boxSizer.Add(filesizetx,0,wx.LEFT|wx.TOP,border=10) # boxSizer.Add((-1,10)) # boxSizer.Add(hashst,0,wx.LEFT|wx.TOP,border=10) # boxSizer.Add(hashtx,0,wx.LEFT|wx.TOP,border=10) dropTarget = FileDropTarget(filetext,md5tx,filesizetx) self.panel.SetDropTarget( dropTarget ) self.panel.SetSizer(boxSizer) class App(wx.App): ##继承wx.App def OnInit(self): ##还没有调起来的时候读取初始化 self.frame = Frame('MD5&size信息') self.frame.Centre() self.frame.Show(True) return True def killSelf(evt = None): os.system('taskkill /F /T /PID %d >NUL 2>NUL' % win32process.GetCurrentProcessId()) if __name__ == '__main__': parser = optparse.OptionParser() parser.add_option('-x', '--no-update', dest = 'test', action = 'store_true', help = 'start without update') parser.add_option('-t', '--no-update-test', dest = 'test2', action = 'store_true', help = 'start without update debug') options, args = parser.parse_args() if options.test: print("-x param") if options.test2: print("-t param") App(redirect = False).MainLoop()
Eine kleine Erklärung:
Klasse App und App().MainLoop() sind feste Schreibmethoden. Unter der Klasse App gibt es eine definierte OnInit-Methode, um den Hauptrahmen zu initialisieren, ihn zu zentrieren und ihn anzuzeigen die Rahmendefinition
Dieses Gadget verwendet boxSizer für das Layout. Der Einfachheit halber verwende ich nur einen boxSizer und ordne alle darin enthaltenen Steuerelemente VERTIKAL (vertikal) an. Wenn Sie MD5 und das folgende Textfeld in dasselbe einfügen möchten, ist dies der Fall. Dann müssen Sie einen horizontalen BoxSizer hinzufügen und diesen horizontalen BoxSizer dann in den Haupt-BoxSizer einfügen
boxSizer = wx.BoxSizer(wx.VERTICAL) #初始化一个垂直的boxSizer,也是整个框架的主Sizer self.panel = wx.Panel(self) #初始化一个panel,这个panel是放了放之后的控件的 filepath = wx.StaticText(self.panel,-1,"FileDir(请将文件拖到本对话框中)") filetext = wx.TextCtrl(self.panel,-1,"",size=(350,20)) md5st = wx.StaticText(self.panel,-1,"MD5") md5tx = wx.TextCtrl(self.panel,-1,size=(250,20)) filesizest = wx.StaticText(self.panel,-1,'FileSize') filesizetx = wx.TextCtrl(self.panel,-1,size=(250,20))
boxSizer.Add(filepath,0,wx.EXPAND|wx.LEFT|wx.TOP,border=10)
Dateipfad zum Haupt-BoxSizer hinzufügen Ich war zunächst etwas verwirrt. Zuerst dachte ich, ich würde zuerst alle Steuerelemente in das Panel einfügen und dann das Panel in den BoxSizer einfügen, aber das ist falsch. , sollte aber direkt in den boxSizer eingegeben werden, setzen Sie die übergeordnete Klasse des Steuerelements auf Panel, und dann ist es nicht erforderlich, das Panel in den boxSizer einzufügen. Der Parameter wx.LEFT|wx.TOP, border=10 repräsentiert das Steuerelement 10 Pixel von oben und links entfernt ist, und dann wx.EXPAND verwenden, um den Bereich, in dem es sich befindet, vollständig auszufüllen. Ich habe einmal darüber nachgedacht, ob es auf 10 Pixel von oben und 20 Pixel von links eingestellt werden könnte, aber es scheint so Es kann nicht auf diese Weise festgelegt werden. Es kann nur einen Randparameter in der Funktion geben. Mit anderen Worten, ich werde sehen, ob er später implementiert werden kann.
boxSizer.Add((-1,20)) #这个是添加一个空距离,距离上20px dropTarget = FileDropTarget(filetext,md5tx,filesizetx) self.panel.SetDropTarget( dropTarget )
Dies dient dazu, der Fensterklasse eine Drag-and-Drop-Methode hinzuzufügen, was ebenfalls eine relativ feste Schreibweise ist
Die Methoden __init__ und OnDropFiles in der obigen Klasse FileDropTarget sind ebenfalls feste Methoden, aber die Verarbeitungsfunktionen darin sind unterschiedlich.
Einige Stil- und Flag-Parameter in wxPython erfordern einige Erfahrung im Layout, ebenso wie viele seiner Steuerelemente und Methoden, um sie kompetent zu beherrschen. Die folgenden beiden Websites sind detaillierter , bitte lesen Sie mehr