酷! 給python腳本配一個動畫界面

python黑乎乎的命令行輸出太乏味了。本篇用pyui4win開發一個有動畫界面的python執行程序。 當用戶選擇執行時,動畫開啓,開始轉圈,直到python功能函數執行完成。在執行過程當中,界面上的信息也在不斷更新。 爲了讓界面不被卡住,採用了多線程技術。 執行的功能函數在非界面線程執行。從結果能夠看到,界面上的動畫很流暢。 python

目錄

  • 執行效果
  • 界面設計
  • 代碼編輯與調試
  • 使用多線程保證界面流暢
  • 執行程序
  • 這是怎麼回事?

執行效果

用戶選擇執行時,動畫開啓,開始轉圈,直到python功能函數執行完成。在執行過程當中,界面上的信息也在不斷更新。最後動畫中止。 github

執行效果

界面設計

主界面xml爲MainFrame.xml,在skin中。全部的界面xml和界面圖片都在該目錄下。 shell

在界面設計中,佈局注意3點;一個是相似的空控件,它們是填充控件。 注意這個例子中的這些填充控件。2是如何讓有的控件自適應大小,就像這個例子中的richedit控件。這時,不要給控件設置大小和位置屬性便可。 3注意float屬性,設置這個屬性後,位置和大小就相對於父控件了。


...
    <VerticalLayout bordersize="2" height="654" bkimage="file=&apos;dialog_background_new.png&apos; corner=&apos;95,715,2,255&apos;">
        <HorizontalLayout name="HLU_caption" height="95">
            <HorizontalLayout width="179" height="95">
                <Label float="true" pos="43,11,0,0" width="72" height="72" bkimage="xiaoniu.png" textcolor="#FF000000" disabledtextcolor="#FFA7A6AA" />
            </HorizontalLayout>
            <VerticalLayout>
                <HorizontalLayout height="24">
                    <VerticalLayout />
                    <VerticalLayout width="79">
                        <HorizontalLayout>
                            <Button name="minbtn" width="25" height="24" textcolor="#FF000000" disabledtextcolor="#FFA7A6AA" align="center" normalimage="file=&apos;sysmenu_.png&apos; source=&apos;0,0,24,23&apos;" hotimage="file=&apos;sysmenu_.png&apos; source=&apos;25,0,49,23&apos;" pushedimage="file=&apos;sysmenu_.png&apos; source=&apos;50,0,74,23&apos;" />
                            <Button name="maxbtn" width="25" height="24" textcolor="#FF000000" disabledtextcolor="#FFA7A6AA" align="center" normalimage="file=&apos;sysbtn_max.png&apos; source=&apos;0,0,24,23&apos;" hotimage="file=&apos;sysbtn_max.png&apos; source=&apos;25,0,49,23&apos;" pushedimage="file=&apos;sysbtn_max.png&apos; source=&apos;50,0,74,23&apos;" />
                            <Button name="restorebtn" visible="false" width="25" height="24" textcolor="#FF000000" disabledtextcolor="#FFA7A6AA" align="center" normalimage="file=&apos;sysbtn_restore.png&apos; source=&apos;0,0,24,23&apos;" hotimage="file=&apos;sysbtn_restore.png&apos; source=&apos;25,0,49,23&apos;" pushedimage="file=&apos;sysbtn_restore.png&apos; source=&apos;50,0,74,23&apos;" />
                            <Button name="closebtn" width="29" height="24" textcolor="#FF000000" disabledtextcolor="#FFA7A6AA" align="center" normalimage="file=&apos;sysmenu_close.png&apos; source=&apos;0,0,28,23&apos;" hotimage="file=&apos;sysmenu_close.png&apos; source=&apos;29,0,57,23&apos;" pushedimage="file=&apos;sysmenu_close.png&apos; source=&apos;58,0,86,23&apos;" />
                        </HorizontalLayout>
                    </VerticalLayout>
                </HorizontalLayout>
                (中間一部分省略)...
        <TabLayout name="TLU_client">
            <VerticalLayout name="DriverDiagnoseTab">
                <Animation name="AnimationJuhua1" enabled="false" float="true" pos="350,150,0,0" width="95" height="95" framesize="95,95" animationimage="fw_update_soft_checking.png" frameinterval="200" />
                <RichEdit name="txtDiagnose" bordersize="1" bordercolor="#00008000" inset="1,1,1,1" vscrollbar="true" hscrollbar="true" autohscroll="true" autovscroll="true" />
                <HorizontalLayout height="62">
                    <VerticalLayout />
                    <VerticalLayout width="465">
                        <HorizontalLayout>
                            <Button name="btnOpenLog" text="打開日誌" float="true" pos="0,10,0,0" width="134" height="42" textcolor="#00FFFBF0" disabledtextcolor="#FFA7A6AA" font="1" align="center" normalimage="reboot.png" hotimage="file=&apos;reboot-hot.png&apos; corner=&apos;20,20,20,20&apos;" pushedimage="reboot.png" focusedimage="reboot.png" />
                            <Button name="btnClearLog" text="清空日誌" float="true" pos="155,10,0,0" width="134" height="42" textcolor="#00FFFBF0" disabledtextcolor="#FFA7A6AA" font="1" align="center" normalimage="reboot.png" hotimage="file=&apos;reboot-hot.png&apos; corner=&apos;20,20,20,20&apos;" pushedimage="reboot.png" focusedimage="reboot.png" />
                            <Button name="btnExcute" text="執行" float="true" pos="310,10,0,0" width="134" height="42" textcolor="#00FFFBF0" disabledtextcolor="#FFA7A6AA" font="1" align="center" normalimage="reboot.png" hotimage="file=&apos;reboot-hot.png&apos; corner=&apos;20,20,20,20&apos;" pushedimage="reboot.png" focusedimage="reboot.png" />
                        </HorizontalLayout>
                    </VerticalLayout>
                </HorizontalLayout>
            </VerticalLayout>
        </TabLayout>
	...

代碼編輯與調試

界面設計完成後,選擇設計器中的編輯->生成python類來生成一個界面類MainFrame.py。將該文件拷貝到父目錄中。執行Launcher.exe能夠看到界面效果。 編程

如今咱們加入業務處理代碼。 多線程

# 界面事件處理
    def OnNotify(self, sendor, sType, wParam, lParam):
        # 用戶點擊事件
        if sType == DUI_MSGTYPE_CLICK:
            ...
            elif sendor == "btnExcute":
                self.ExecutePython()
            ...

    ...
    # 真正業務函數
    def ExecutePython(self,):
        CommonUtils.ReverseToExePath()
        ISOTIMEFORMAT='%Y-%m-%d %X'
        self.ShowAndLog(time.strftime( ISOTIMEFORMAT, time.localtime() ))

        i = 0
        while i < 20:
            self.AppendAndLog('等待了%d秒' % i)
            time.sleep(1)
            i = i + 1

        self.AppendAndLog('成功')

執行程序,點擊執行按鈕,發現界面卡住了。過了20秒界面才正常。這是這個業務函數須要執行20秒致使的。 app

使用多線程保證界面流暢

當用戶選擇執行時,動畫開啓,開始轉圈,直到python功能函數執行完成。在執行過程當中,界面上的信息也在不斷更新。 爲了讓界面不被卡住,採用了多線程技術。執行的功能函數在非界面線程執行。下面分析一下代碼。 函數

# 界面事件處理
    def OnNotify(self, sendor, sType, wParam, lParam):
        # 用戶點擊事件
        if sType == DUI_MSGTYPE_CLICK:
            ...
            elif sendor == "btnExcute":
                t = threading.Thread(target=PyThreadPythonExecute,args=(self,)) #啓動了業務線程
                t.start()
            ...
注意ExecutePython是真正的業務處理函數,在該python類中定義。PyThreadPythonExecute只是真正業務函數的代理,而且在該python類外定義。 這時多線程編程中經常使用的方法。

代理函數,在python類外定義: 佈局

# 業務線程實際上只是一個代理函數
def PyThreadPythonExecute(PyClassInstance, ):
    try:
        PyClassInstance.StartAnimation()
        PyClassInstance.ExecutePython()
    except Exception, e:
        PyLog().LogText(str(e))
    PyClassInstance.StopAnimation()
    PyLog().LogText('PyThreadExecute exit')

執行程序

執行Launcher.exe或者DebugEntry.py,點擊執行按鈕。如今動畫開啓,開始轉圈,直到python功能函數執行完成。 在執行過程當中,界面上的信息也在不斷更新。界面很流暢。 動畫

這是怎麼回事?

有趣的是,在pyui4win中,使用ctyps中的界面相關函數,會致使程序崩潰。日誌裏頭輸出是

'exceptions.WindowsError': exception: access violation writing 0x0000000C...
錯誤緣由尚未找到。 好比在這個例子中,對打開日誌的處理中:
...
            elif sendor == "btnOpenLog":
                if os.path.isfile(PyWinUtils().GetExeDirectory() + '\\applog.ini'):
                    shell32 = ctypes.windll.LoadLibrary("shell32.dll");
                    #shell32.ShellExecuteA(None,'open', 'notepad',PyWinUtils().GetExeDirectory() + '\\applog.ini','',1);
                    PyWinUtils().ShellExcute(0, 'open', PyWinUtils().GetExeDirectory() + '\\applog.ini', '', '', 1)
                else:
                    UICommon.ShowMessageBox(self.GetHWnd(), '錯誤', '日誌文件不存在')
            ...

若是使用shell32.ShellExecuteA就會崩潰。你知道是什麼緣由嗎?

不要使用ctyps中的界面相關函數,不然會致使程序崩潰。該緣由尚未找到。可是,針對經常使用的界面函數,如MessageBox等,請使用PyWinUtils類中的對應函數
相關文章
相關標籤/搜索