激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

腳本之家,腳本語言編程技術(shù)及教程分享平臺(tái)!
分類導(dǎo)航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服務(wù)器之家 - 腳本之家 - Python - Windows中使用wxPython和py2exe開發(fā)Python的GUI程序的實(shí)例教程

Windows中使用wxPython和py2exe開發(fā)Python的GUI程序的實(shí)例教程

2020-09-01 09:22Kevin_Yang Python

wxPython是一款集成了Python的圖形化類庫的工具,而py2exe是一款將Python程序轉(zhuǎn)換為exe可執(zhí)行文件的程序,二者搭配可以輕松地在Windows中創(chuàng)建圖形化程序,這里我們就來學(xué)習(xí)Windows中使用wxPython和py2exe開發(fā)Python的GUI程序的實(shí)例教程:

Python是支持可視化編程,即編寫gui程序,你可以用它來編寫自己喜歡的桌面程序。使用wxPython來做界面非常的簡單,只是不能像C#一樣拖動(dòng)控件,需要自行寫代碼布局。在完成編寫之后,由于直接的py文件不能再?zèng)]有安裝python的電腦上運(yùn)行,能否有一個(gè)打包成在任意電腦都能運(yùn)行的工具,網(wǎng)上找找發(fā)現(xiàn)了py2exe正好可以完成這個(gè)功能。wxPython和py2exe都是開源免費(fèi)軟件。

環(huán)境配置
wxPython: sourceforge項(xiàng)目頁https://sourceforge.net/projects/py2exe/files/py2exe/0.6.9/
下載后雙擊安裝即可,安裝程序會(huì)自動(dòng)安裝到對應(yīng)python\Scripts下。
py2exe:官方下載主頁https://www.wxpython.org/download.php
同樣雙擊即可安裝,注意下載要對應(yīng)使用的Python版本。
下面分別示例說明wxPython和py2exe的簡單使用。

基本示例
文件名:wxTest.py:

# -*- coding: cp936 -*-
'''MainWindow類完成最簡單的編輯功能,添加一個(gè)主菜單,兩個(gè)子菜單(about和exit)'''
import wx
 
class MainWindow(wx.Frame):
 '''定義一個(gè)窗口類'''
 def __init__(self, parent, title):
  wx.Frame.__init__(self, parent,  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):
   '''點(diǎn)擊about的事件響應(yīng)'''
   dlg = wx.MessageDialog(self, 'This app is a simple text editor', 'About my app', wx.OK)
   dlg.ShowModal()
   dlg.Destroy()
 
 def onExit(self, evt):
   '''點(diǎn)擊退出'''
   self.Close(True)
app = wx.App(False)
frame = MainWindow(None, 'Small Editor')
app.MainLoop() #循環(huán)監(jiān)聽事件

編輯好改文件后,使用py2exe將Python腳本編譯成Windows可執(zhí)行文件,這樣就不需要Python解釋器了。要使用py2exe,首先要編寫一個(gè)編譯腳本,然后通過Python運(yùn)行編譯腳本即可將其他的腳本編譯成可執(zhí)行文件。以下實(shí)例是將要編譯成可執(zhí)行文件的腳本,文件名:setup.py

import distutils
import py2exe
distutils.core.setup(windows=['wxTest.py'])

在setup.py中除了導(dǎo)入必需的模塊以外,只有一條語句:

distutils.core.setup(windows=['wxTest.py'])

方括號中就是要編譯的腳本名,前邊的windows 表示將其編譯成GUI程序。如果要編譯命令行界面的可執(zhí)行文件,只要將windows改為console,如果需要將腳本編譯成Windows服務(wù),則可以使用service選項(xiàng)。
都編輯好之后,將wxTest.py和setup.py放在同一個(gè)路徑下,cmd進(jìn)入該路徑,輸入:

setup.py py2exe

如果在運(yùn)行時(shí)報(bào)以下錯(cuò)誤:

error: MSVCP90.dll: No such file or directory
是因?yàn)闆]有找到MSVCP90.dll,在windows目錄下搜索MSVCP90.dll這個(gè)文件,然后拷到python安裝目錄的DLLs下就可以了。
當(dāng)打包PyQt項(xiàng)目時(shí),可能會(huì)報(bào)以下錯(cuò)誤
ImportError: No module named sip
這時(shí)只需要在打包時(shí)加上--includes sip就行啦,如:
setup.py py2exe --includes sip

運(yùn)行結(jié)束之后,會(huì)在路徑下生成dist和 build兩個(gè)目錄。其中dist目錄中就是編譯生成的文件。如果要在其他未安裝Python的機(jī)器上運(yùn)行編譯好的程序,只要將dist目錄復(fù)制到其他機(jī)器上即可。雙擊運(yùn)行wxTest.exe,如圖:

Windows中使用wxPython和py2exe開發(fā)Python的GUI程序的實(shí)例教程

使用wxPython建立一個(gè)計(jì)算文件md5的GUI工具
小工具最終是下面這個(gè)樣子,將文件拖到上面會(huì)自動(dòng)計(jì)算其md5與size

Windows中使用wxPython和py2exe開發(fā)Python的GUI程序的實(shí)例教程

下面是全部的代碼

#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'
   
#線程函數(shù)
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 進(jìn)行初始化
  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擴(kuò)充到全部
    
    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): ##還沒有調(diào)起來的時(shí)候讀取初始化
    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()

一點(diǎn)點(diǎn)的解釋:

class App與App().MainLoop()是固定寫法,在class App下有一個(gè)def OnInit方法來初始化主的Frame,將其居中并且Show()出來,沒什么好說的,主要看一下Frame的定義

這個(gè)小工具使用的是boxSizer來布局,為了簡單我只使用了一個(gè)boxSizer,將里面的所有控件采用VERTICAL(垂直)的方式來布局,如果想要將MD5與后面的文本框放在同一行,那么就需要添加一個(gè)水平的boxSizer,然后那將這個(gè)水平的boxSizer再放入主的boxSizer

boxSizer = wx.BoxSizer(wx.VERTICAL) #初始化一個(gè)垂直的boxSizer,也是整個(gè)框架的主Sizer

self.panel = wx.Panel(self) #初始化一個(gè)panel,這個(gè)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))



上面是初始化相應(yīng)的靜態(tài)文本與文本框,方法中的第一個(gè)參數(shù)是其所在的父類窗口,這里也就是self.panel,其實(shí)也可以不用panel,而是將其直接放入到boxSizer中

boxSizer.Add(filepath,0,wx.EXPAND|wx.LEFT|wx.TOP,border=10) 

將filepath加入到主的boxSizer中,這里一開始我有一些困惑,一開始我一直以為先將所有的控件放入到panel中,然后再將panel放入到boxSizer中,但是這樣是不對的,而應(yīng)該是直接就入到boxSizer中,將該控件的父類設(shè)置為panel,之后就沒有將panel放入boxSizer這一步操作,wx.LEFT|wx.TOP,border=10 這個(gè)參數(shù)表示的是該控件距離上來左各有10個(gè)像素的距離,再使用wx.EXPAND來使其充分的填充其所在的區(qū)域,我曾經(jīng)想,可否設(shè)置成距離上10px,左20px,但是貌似不能這樣設(shè)置,Add函數(shù)里只能有一個(gè)border參數(shù),換句話說只能設(shè)置相同的數(shù)值,之后我再找找是否可以實(shí)現(xiàn)。

boxSizer.Add((-1,20)) #這個(gè)是添加一個(gè)空距離,距離上20px

dropTarget = FileDropTarget(filetext,md5tx,filesizetx) 
self.panel.SetDropTarget( dropTarget )

這個(gè)是放該窗口類添加一個(gè)拖拽方法,也是比較固定的寫法

上面的class FileDropTarget中的__init__與OnDropFiles方法也是固定的方法,只是里面的處理函數(shù)不同。

wxPython中的一些style與flag等參數(shù)在布局中使用需要一些經(jīng)驗(yàn),還有它的很多控件和與之綁定的方法,要想熟練掌握還需要下一些工夫,下面兩個(gè)網(wǎng)站算是介紹比較詳細(xì),要多多查閱

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 宅男噜噜噜66国产免费观看 | 色人阁五月天 | 日韩精品中文字幕一区 | 欧美性受ⅹ╳╳╳黑人a性爽 | 欧美精品一区二区免费 | 欧美国产第一页 | 欧美性生活久久久 | 中文国产在线视频 | 欧美大片一级毛片 | 欧美a一| 国产69精品99久久久久久宅男 | 欧洲色阁中文字幕 | 久久精品国产99国产精品亚洲 | 嗯哈~不行好大h双性 | av色偷偷| 亚州综合网| 香蕉在线看 | 激情综合在线 | 成人做爰高潮片免费视频韩国 | 国产妇女乱码一区二区三区 | jj视频在线播放 | 婷婷亚洲一区二区三区 | 久久精品亚洲欧美日韩精品中文字幕 | 国产日韩欧美一区 | 日本精品免费观看 | 亚洲va久久久噜噜噜久牛牛影视 | 毛片视频网站 | 666sao| 国产精品av久久久久久无 | 久久久一二三 | 性大片1000免费看 | 久久久国产精品网站 | 成人观看网站 | 亚洲成人福利 | 91短视频在线免费观看 | 国产伦精品一区二区三区 | 精品一区二区三区免费 | 国产中文一区 | 嫩草影院在线观看网站成人 | 夏目友人帐第七季第一集 | 国产午夜精品一区二区三区在线观看 |