<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          使用PyQt5實現(xiàn)自動化測試,太便利了

          共 8430字,需瀏覽 17分鐘

           ·

          2021-01-28 22:21

          關(guān)注、星標(biāo)公眾號,直達(dá)精彩內(nèi)容

          公眾號:技術(shù)讓夢想更偉大

          作者:Boudewijn Rempt 和 David Mertz


          最近在使用pyqt寫個自動化測試軟件,對python和Qt都需要有一些了解,輸出這篇文章主要是想分享一下Qt和PyQt用于Python的高級GUI庫的知識。也有些感慨,當(dāng)然這個pyqt用不上的可以直接不看了,先分享幾點。

          1. 嵌入式開發(fā)學(xué)的東西真的很多很多,各種單片機(jī)、模電數(shù)電硬件基礎(chǔ)、Linux驅(qū)動內(nèi)核、C/C++編程、Qt、計算機(jī)等相關(guān)知識。

          2. 在編程過程中,其實語言都是相通的,會了C語言其余的語言學(xué)起來就很快,編程的思想很重要,當(dāng)然要是想的深好還是要多家鉆研。

          3. 不要拒絕任何學(xué)習(xí)的機(jī)會,工作中常說這個我不會,或者這個跟我做的不相關(guān);這種想法還是要摒棄,給自己一個機(jī)會,多動手。

          Qt 和 PyQt 用于 Python 的高級 GUI 庫

          一般來說,選擇用于應(yīng)用程序的 GUI 工具箱會是一件棘手的事。使用 Python(許多語言也一樣)的程序員可以選擇的 GUI 工具箱種類繁多,而每個工具箱都有各自的優(yōu)缺點。有些速度比其它工具箱快,有些比較小;有些易于安裝,有些更適合于跨平臺使用(對于這一點,還要指出,有些支持您需要滿足的特定特性)。當(dāng)然,各種庫都相應(yīng)具有各種許可證。

          對于 Python 程序員而言,缺省的 GUI 選擇是 Tk(通過 Tkinter 綁定)— 其原因顯而易見。Tkinter 和閑置的 IDE 是由 Python 創(chuàng)始人編寫的,它們是作為大多數(shù) Python 分發(fā)版的缺省選擇而出現(xiàn)的。標(biāo)準(zhǔn) Python 文檔討論了 Tkinter,但沒有涉及任何其它 GUI 綁定。這是故意的!至少可以這么認(rèn)為,如果 Tk 和 Tkinter 不是這么糟糕,程序員就沒有理由去尋找替代品了。要誘導(dǎo) Python 程序員放棄缺省選擇,那么工具箱必須提供額外的東西。PyQt 就是這樣一個工具箱。

          PyQt 所具有的優(yōu)點遠(yuǎn)遠(yuǎn)超過了 Tkinter(它也有幾個缺點)。Qt 和 PyQt 速度都很快;Qt 和 PyQt 的設(shè)計完全是面向?qū)ο蟮模籕t 提供了一個設(shè)計良好的窗口構(gòu)件集合,它比 Tk 所提供的要大得多。就其缺點而言,Qt 的許可證受到的限制比許多工具箱(至少在非 Linux 平臺方面)都多;正確安裝 Qt 和 PyQt 常常會很復(fù)雜;另外,Qt 是一個相當(dāng)大的庫。PyQt 應(yīng)用程序的用戶將需要設(shè)法完成安裝 Qt 和 PyQt,這使分發(fā)變得很困難。

          PyQt 嚴(yán)格遵循 Qt 的發(fā)放許可。特別是,它可用于 UNIX/X11 平臺上的 GPL,并可用于 Zaurus 上的 Qt Palmtop Environment 環(huán)境,還存在用于較老的 Qt 版本的免費(free-as-in-free-beer)Windows 軟件包。PyQt 的商業(yè)許可證可用于 Windows。

          對于本文而言,PyQt 有一個方面優(yōu)于許多其它工具箱,它值得我們特別關(guān)注。Qt 使用一種稱為 信號/插槽(signals/slots)的機(jī)制在窗口構(gòu)件(以及其它對象)之間傳遞事件和消息。這種機(jī)制完全不同于包括 Tkinter 在內(nèi)的大多數(shù)工具箱所用的回調(diào)(callback)機(jī)制。使用信號/插槽以靈活且可維護(hù)的方式控制對象間通信要比使用脆弱的回調(diào)風(fēng)格容易得多。應(yīng)用程序越大,Qt 的這個優(yōu)勢就越重要。

          樣本應(yīng)用程序

          要顯示信號/插槽和回調(diào)之間的反差,我們提供了一個寫著玩玩的應(yīng)用程序,它使用 Tkinter 和 PyQt。盡管實際上 PyQt 版本對于這個基本程序并不更簡單,但是它已經(jīng)演示了 PyQt 應(yīng)用程序更好的模塊性和可維護(hù)性。

          應(yīng)用程序包括四個窗口構(gòu)件:

          1. “Quit”按鈕(用來與整個應(yīng)用程序通信)

          2. “Log Timestamp”按鈕(用于窗口構(gòu)件間的消息)

          3. 文本區(qū)域,顯示可滾動的已記錄日志的時間戳記列表

          4. 消息窗口構(gòu)件,顯示已記錄日志的時間戳記數(shù)

          在 Tkinter 中,我們可以這樣實現(xiàn)應(yīng)用程序:

          清單 1. Logger.py Tkinter 應(yīng)用程序

          #!/usr/bin/python
          import?sys,?time
          from?Tkinter?import?*
          class?Logger(Frame):
          ????def?__init__(self):
          ????????Frame.__init__(self)
          ????????self.pack(expand=YES,?fill=BOTH)
          ????????self.master.title("Timestamp?logging?application")
          ????????self.tslist?=?[]
          ????????self.tsdisp?=?Text(height=6,?width=25)
          ????????self.count?=?StringVar()
          ????????self.cntdisp?=?Message(font=('Sans',24),
          ???????????????????????????????textvariable=self.count)
          ????????self.log?=?Button(text="Log?Timestamp",
          ??????????????????????????command=self.log_timestamp)
          ????????self.quit?=?Button(text="Quit",?command=sys.exit)
          ????????self.tsdisp.pack(side=LEFT)
          ????????self.cntdisp.pack()
          ????????self.log.pack(side=TOP,?expand=YES,?fill=BOTH)
          ????????self.quit.pack(side=BOTTOM,?fill=BOTH)
          ????def?log_timestamp(self):
          ????????stamp?=?time.ctime()
          ????????self.tsdisp.insert(END,?stamp+"\n")
          ????????self.tsdisp.see(END)
          ????????self.tslist.append(stamp)
          ????????self.count.set("%?3d"?%?len(self.tslist))
          if?__name__=='__main__':
          ????Logger().mainloop()

          這個 Tk 版本使用了 log_timestamp() 方法作為按鈕的 command= 參數(shù)。這個方法需要依次單獨操作它要影響的所有窗口構(gòu)件。如果我們想更改按鈕按下的效果(例如還要記錄時間戳記),那么這個風(fēng)格就很脆弱。通過繼承您可以實現(xiàn)這一點:

          清單 2. StdOutLogger.py Tkinter 增強(qiáng)

          ????class?StdOutLogger(Logger):
          def?log_timestamp(self):
          ????Logger.log_timestamp(self)
          ????print?self.tslist[-1]

          但是這個子類的作者需要相當(dāng)精確地理解 Logger.log_timestamp() 已經(jīng)做了什么;而且除非通過在子類中完全重寫 .log_timestamp() 方法并且不調(diào)用父方法,否則沒有辦法 除去消息。

          一個非常基本的 PyQt 應(yīng)用程序總有一些樣本代碼,這些代碼在哪里都相同,Tkinter 代碼也是這樣。但是,當(dāng)我們進(jìn)一步研究設(shè)置應(yīng)用程序所需的代碼,以及顯示窗口構(gòu)件的代碼時,區(qū)別就顯現(xiàn)出來了。

          清單 3. logger-qt.py PyQt 應(yīng)用程序

          ????#!/usr/bin/env?python
          import?sys,?time
          from?qt?import?*?#?Generally?advertised?as?safe
          class?Logger(QWidget):
          ????def?__init__(self,?*args):
          ????????QWidget.__init__(self,?*args)
          ????????self.setCaption("Timestamp?logging?application")
          ????????self.layout?=?QGridLayout(self,?3,?2,?5,?10)
          ????????self.tsdisp?=?QTextEdit(self)
          ????????self.tsdisp.setMinimumSize(250,?300)
          ????????self.tsdisp.setTextFormat(Qt.PlainText)
          ????????self.tscount?=?QLabel("",?self)
          ????????self.tscount.setFont(QFont("Sans",?24))
          ????????self.log?=?QPushButton("&Log?Timestamp",?self)
          ????????self.quit?=?QPushButton("&Quit",?self)
          ????????self.layout.addMultiCellWidget(self.tsdisp,?0,?2,?0,?0)
          ????????self.layout.addWidget(self.tscount,?0,?1)
          ????????self.layout.addWidget(self.log,?1,?1)
          ????????self.layout.addWidget(self.quit,?2,?1)
          ????????self.connect(self.log,?SIGNAL("clicked()"),
          ?????????????????????self.log_timestamp)
          ????????self.connect(self.quit,?SIGNAL("clicked()"),
          ?????????????????????self.close)
          ????def?log_timestamp(self):
          ????????stamp?=?time.ctime()
          ????????self.tsdisp.append(stamp)
          ????????self.tscount.setText(str(self.tsdisp.lines()))
          if?__name__?==?"__main__":
          ????app?=?QApplication(sys.argv)
          ????app.connect(app,?SIGNAL('lastWindowClosed()'),?app,
          ??????????????????SLOT('quit()'))
          ????logger?=?Logger()
          ????logger.show()
          ????app.setMainWidget(logger)
          ????app.exec_loop()

          通過創(chuàng)建布局管理器, Logger 類開始工作了。布局管理器在任何 GUI 系統(tǒng)中都是一個很復(fù)雜的主題,但是 Qt 的實現(xiàn)使之變得簡單。在大多數(shù)情況下,您會使用 Qt Designer 創(chuàng)建一般的 GUI 設(shè)計,隨后可將它用于生成 Python 或 C++ 代碼。然后您可以使生成的代碼生成子類,以添加功能。

          但是在這個示例中,我們選擇手工創(chuàng)建布局管理器。窗口構(gòu)件被置于網(wǎng)格的各個單元中,或者可以跨多個單元放置。在 Tkinter 需要命名參數(shù)的地方,PyQt 就不允許它們。這是一個很重要的差異,它經(jīng)常會使在兩種環(huán)境中工作的人們無所適從。

          所有 Qt 窗口構(gòu)件都可以和 QString 對象很自然地一起工作,而不能和 Python 字符串或 Unicode 對象一起工作。幸運的是,轉(zhuǎn)換是自動的。如果您在 Qt 方法中使用了字符串或 Unicode 參數(shù),那么它將自動轉(zhuǎn)換成 QString。不能進(jìn)行反向轉(zhuǎn)換:如果您調(diào)用了一個返回 QString 的方法,那么您獲得的是 QString。

          應(yīng)用程序中最有趣的部分是我們將 clicked 信號連接到功能的位置。一個按鈕連接到了 log_timestamp 方法;另一個連接到了 QWidget 類的 close 方法。

          圖 1. logger-qt 的屏幕快照

          現(xiàn)在我們想將日志記錄添加到這個應(yīng)用程序的標(biāo)準(zhǔn)輸出。這十分容易。我們可以使 Logger 類生成子類,或者為了演示,創(chuàng)建簡單的獨立函數(shù):

          清單 4. logger-qt.py PyQt 增強(qiáng)

          ???def?logwrite():
          ????print(time.ctime())
          if?__name__?==?"__main__":
          ???app?=?QApplication(sys.argv)
          ???app.connect(app,?SIGNAL('lastWindowClosed()'),?app,
          ???????????????SLOT('quit()'))
          ???logger?=?Logger()
          ???QObject.connect(logger.log,?SIGNAL("clicked()"),?logwrite)
          ???logger.show()
          ???app.setMainWidget(logger)
          ???app.exec_loop()

          從上述代碼我們可以看到,這就是將 log QPushButton 的 clicked() 信號連接到新函數(shù)的事情。注:信號也可以將任何數(shù)據(jù)傳送到它們所連接的插槽,盡管在這里我們沒有顯示這樣的示例。

          如果您不想調(diào)用原始方法,那么可以從插槽 disconnect 信號,例如通過在 logger.show() 行之前添加以下行:

          清單 5. logger-qt.py PyQt 增強(qiáng)

          QObject.disconnect(logger.log,?SIGNAL("clicked()"),
          logger.log_timestamp)

          現(xiàn)在將不再更新 GUI。

          用于 Python 的其它 GUI 綁定

          PyQt 在給定實例中可能不是很有用,可能是許可證狀態(tài)問題,也可能是平臺可用性問題(或者,可能因為再分發(fā)很困難,例如大小很大)。由于這個原因(也為了比較),我們想指出一些用于 Python 的其它流行 GUI 工具箱。

          Anygui

          Anygui 實際上不是 GUI 工具箱,而是一個作用于大量工具箱(甚至是令人驚奇的象 curses 和 Java/Jython Swing 那樣的工具箱)的抽象包裝器。在編程風(fēng)格方面,使用 Anygui 類似于使用 Tkinter,但是要選中這個底層工具箱,要么自動進(jìn)行,要么進(jìn)行配置調(diào)用。Anygui 很好用,因為它允許應(yīng)用程序未經(jīng)更改就可以運行在差異很大的平臺上(但因此它支持受支持工具箱的“最低級公共特性”)。

          PyGTK

          PyGTK 綁定包裝了 GPL 下使用的 GTK 工具箱,它是流行的 Gnome 環(huán)境的基礎(chǔ)。GTK 在根本上是 X Window 工具箱,但是它還有 Win32 的 beta 級支持和 BeOS 的 alpha 級支持。在常規(guī)范例中,PyGTK 對窗口構(gòu)件使用回調(diào)。綁定存在于 GTK 和 大量編程語言之間,而不僅僅是 Qt,或甚至是 Tk。

          FXPy

          Python 綁定 FXPy 包裝了 FOX 工具箱。FOX 工具箱已經(jīng)被移植到大多數(shù)類 UNIX 平臺上,以及 Win32 上。與大多數(shù)工具箱類似,F(xiàn)OX 和 FXPy 都使用回調(diào)范例。FOX 由 LGPL 特許。

          wxPython

          這個綁定包裝了 wxWindows 工具箱。與 FOX 或 GTK 類似,wxWindows 被移植到 Win32 和類 UNIX 平臺上(但是沒有移植到 MacOS、OS/2、BeOS 或其它“次要”平臺上 — 盡管它對 MacOSX 的支持是 alpha 級的)。在范例方面,wxPython 接近回調(diào)風(fēng)格。wxPython 對繼承結(jié)構(gòu)的關(guān)注程度高于大多數(shù)其它工具箱,而且它使用“事件”,而不是回調(diào)。但是本質(zhì)上,事件仍舊被連接到單個方法上,隨后可能需要作用于各種窗口構(gòu)件。

          win32ui

          win32ui 屬于 win32all 軟件包,它包裝了 MFC 類。很顯然,這個工具箱是特定于 Win32 的庫。MFC 實際上不只是 GUI 工具箱,它還使用各種范例的混合。對于想創(chuàng)建 Windows 應(yīng)用程序的讀者而言,與其它工具箱相比,win32ui 會讓您“更接近于實質(zhì)”。

          從其它語言使用 Qt

          如同 Python,從大量其它編程語言使用 Qt 工具箱是可能的。如果可以自由選擇,我們會首選 Python,而不是其它語言。諸如公司政策以及與其它代碼庫連接之類的外部約束可以決定編程語言的選擇。Qt 的原始語言是 C++,但也有用于 C、Java、Perl 和 Ruby 的綁定。就與 Python 示例的比較而言,讓我們討論一下用 Ruby 和 Java 寫著玩玩的應(yīng)用程序。

          Ruby/Qt 在用法上十分類似于 PyQt。這兩種語言具有相似的動態(tài)性和簡明性,所以除了拼寫上的差別外,其代碼很類似:

          清單 6. HelloWorld.rb Qt2 應(yīng)用程序

          #!/usr/local/bin/ruby
          require?'qt2'
          include?Qt2
          a?=?QApplication.new([$0]?+?ARGV)
          hello?=?QPushButton.new('Hello?world!')
          hello.resize(100,?30)
          a.connect(?hello,?QSIGNAL('clicked()'),?a,?QSLOT('quit()'))
          a.setMainWidget(hello)
          hello.show
          a.exec

          Java 總是比腳本編制語言要冗長一點,但是基本部分都相同。一個同等功能的最小 qtjava 應(yīng)用程序類似于:

          清單 7. HelloWorld.java Qt2 應(yīng)用程序

          import?org.kde.qt.*;
          public?class?HelloWorld?{
          ??public?static?void?main(String[]?args)
          ??{
          ????QApplication?myapp?=?new?QApplication(args);
          ????QPushButton?hello?=?new?QPushButton("Hello?World",?null);
          ????hello.resize(100,30);
          ????myapp.connect(hello,?SIGNAL("clicked"),
          ??????????????????this,?SLOT("quit()"));
          ????myapp.setMainWidget(hello);
          ????hello.show();
          ????myapp.exec();
          ????return;
          ??}
          ??static?{
          ????System.loadLibrary("qtjava");
          ????try?{
          ????????Class?c?=?Class.forName("org.kde.qt.qtjava");
          ????}?catch?(Exception?e)?{
          ????????System.out.println("Can't?load?qtjava?class");
          ????}
          ??}
          }

          PyQt 是一個吸引人和快速的接口,它將 Qt 工具箱和 Python 編程語言集成在一起。除了該工具箱提供的種類繁多的窗口構(gòu)件外,Qt 所用的信號/插槽編程風(fēng)格在生產(chǎn)能力和可維護(hù)性方面都要優(yōu)于大多數(shù)其它 GUI 工具箱所用的回調(diào)風(fēng)格。

          https://www.ibm.com/developerworks/cn/linux/l-qt/index.html

          ???????????????? ?END ?????????????????

          掃描下方微信,加作者微信進(jìn)技術(shù)交流群,請先自我介紹喔。



          推薦閱讀:


          嵌入式編程專輯
          Linux 學(xué)習(xí)專輯
          C/C++編程專輯
          Qt進(jìn)階學(xué)習(xí)專輯
          關(guān)注微信公眾號『技術(shù)讓夢想更偉大』,后臺回復(fù)“m”查看更多內(nèi)容。

          長按前往圖中包含的公眾號關(guān)注

          瀏覽 115
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  日韩黄色影视 | 天天热天天干 | 国产一a毛一a毛A免费看图 | 极品日韩 | 在线看v片|