第15.39節、splitDockWidget和tabifyDockWidget嵌套佈局QDockWidget的PyQt人機對話案例:笨笨機器人

一、引言

在第《第三十一章、containers容器類部件QDockWidget停靠窗功能介紹》詳細介紹了QDockWidget的屬性、方法和信號,並介紹了利用QMainWindow的splitDockWidget和tabifyDockWidget等方法實現基於主窗口布局的方法。本節將利用相關方法實現一個簡單的人機對話應用:笨笨機器人。

二、案例介紹

2.1、功能介紹

笨笨機器人是老猿測試QDockWidget的一個測試程序,其運行界面如圖所示:
在這裏插入圖片描述
可以看到,該測試程序實現了一個簡單的人機對話(機器應答是在設定應答語句中隨機挑選一個),可以設置對話雙方的名字,可以設置聊天信息的字體和顏色。

2.2、實現思路

要實現這個簡單應用,有很多種方法,本次測試是爲了使用QDockWidget,因此通過QMainWindow和QDockWidget配套實現。

由於QDockWidget本身的內容區域(內容)也是一個QWidget對象,要實現在QMainWindow上放置多個停靠窗、每個停靠窗要放置對應的內容子部件對象、並對停靠窗進行排列布局操作,在Designer中進行UI設計反而比通過代碼實現麻煩很多,因此整體UI佈局大部分都是通過代碼實現的,在Designer中只實現了暱稱配置信息窗口的界面和主窗口QMainWindow的主窗口基本界面。

2.3、暱稱設置窗實現

暱稱設置設計界面如下:
在這裏插入圖片描述
其中兩個輸入框的名稱分別爲myName和robertName。

ui設計後將其生成代碼模塊文件ui_configWin.py,然後派生類,只實現構造方法,其他都不進行處理。

class configWin(ui_configWin.Ui_configWin,QtWidgets.QWidget):
    def __init__(self,parent=None):
        super().__init__(parent)
        self.setupUi(self)

2.4、主窗口基礎實現

2.4.1、ui設計界面

在這裏插入圖片描述
主窗口基本界面就是一個mainWindow,沒有放置任何子部件,名稱也是mainWindow,設置了標題信息爲:“老猿Python:DockWidget測試 網址:https://blog.csdn.net/LaoYuanPython”。生成代碼後存放在模塊文件ui_mainWin.py中。

2.4.2、主窗口派生類及構造方法

主窗口派生類及構造方法代碼如下:

class mainWin(QtWidgets.QMainWindow,ui_mainWin.Ui_mainWindow):
    def __init__(self):
        super().__init__()
        self.setupUi(self)
        self.robertColor = Qt.black  #設置機器人對話字體初始顏色
        self.myColor = Qt.blue  #設置輸入對話字體初始顏色
        self.setDockNestingEnabled(True) #讓主窗口支持停靠窗嵌套
        w = self.takeCentralWidget() #移除中央窗口部件,請參見第三十一章的介紹

        self.initDock()   #進行停靠窗生成及排列
說明:
  1. 構造方法中,除了常規的UI界面類的代碼外,初始化了對話文本的顏色,設置了讓主窗口支持停靠窗嵌套,最後調用initDock方法進行停靠窗生成及排列;
  2. 需要關注一下setDockNestingEnabled語句,相關屬性的含義可以參考《PyQt(Python+Qt)學習隨筆:Qt Designer中主窗口對象dockNestingEnabled屬性》。但這個屬性說明的字面說明太簡單,實際理解還是有些複雜。在這裏通過兩個截圖對比說明一下:在這裏插入圖片描述上圖是主窗口允許嵌套的場景,圖中所有有關閉和浮動標記的窗口都是QDockWidget對象,在允許嵌套情況下,“機器人發言字體顏色”設置窗和“本機輸入發言字體顏色”兩個窗口可以上下堆疊合佔一個停靠位的位置。而下圖是未設置dockNestingEnabled的,這兩個窗口就不能縱向堆疊在一起,只能選項卡式化佔用一個停靠位。
    在這裏插入圖片描述
    所以嵌套是指一個停靠位的位置堆疊或水平排列了兩個停靠窗,而這個位置正常情況下只能放置一個對應大小的停靠窗。
  3. takeCentralWidget作用是將主窗口中央區域部件從主窗口中移除,對象並沒有刪除,當中央部件沒有移除時,停靠窗只能停留在中央部件四周,移除後可以停靠到整個主窗口區域,下面截圖對比一下:在這裏插入圖片描述
    同一個程序,左邊是移除了中央部件,右邊沒有,二者的效果對比可以看出移除中央部件的效果。
    如果沒有調用takeCentralWidget移除中央部件,後續調用setCentralWidget將一個停靠窗口設置爲中央部件也可以實現類似的效果。

2.4.3、創建對話顯示框停靠窗

對話顯示框dialogDisplay 爲一個QTextEdit對象,將其作爲dialogDisplayDock停靠窗的內容部件,將其放置在主窗口中央部件區域。

		self.dialogDisplay = QtWidgets.QTextEdit()
        self.dialogDisplayDock = QtWidgets.QDockWidget("對話記錄", self)
        self.dialogDisplayDock.setWidget(self.dialogDisplay)#將對話窗作爲對話停靠窗的內容部件
        self.setCentralWidget(self.dialogDisplayDock)

2.4.4、創建輸入停靠窗

輸入部件input 爲一個QLineEdit對象,將其作爲inputDock 停靠窗的內容部件,在代碼中設置了輸入部件的寬度。由於部件是代碼創建,因此信號與槽方法的連接關係必須代碼實現,在此將輸入部件按下回車鍵作爲消息發送的信號連接到主窗口的槽方法inputEnd。

		self.input = QtWidgets.QLineEdit()
        self.input.geometry().setWidth(200)
        self.input.returnPressed.connect(self.inputEnd)
        self.inputDock = QtWidgets.QDockWidget("對話輸入(回車鍵發送):", self)
        self.inputDock.setWidget(self.input)#將輸入部件input作爲inputDock停靠窗的內容部件

2.4.5、構建字體選擇停靠窗、機器人對話文本顏色停靠窗、發言人對話文本顏色停靠窗

字體選擇停靠窗fontDock包含標題和一個設置字體的按鈕,按鈕點擊後能觸發字體選擇。

		self.fontDock = QtWidgets.QDockWidget('字體設置',self)
        fontButton = QtWidgets.QPushButton('點此設置字體',self.fontDock)
        setFontSizeColor(fontButton,QtGui.QPalette.ButtonText,Qt.red,10)#設置按鈕文字的顏色和大小
        fontButton.clicked.connect(self.getFont)
        self.fontDock.setWidget(fontButton)#將fontButton作爲fontDock停靠窗的內容部件

機器人對話文本顏色停靠窗robertFontColorDock用於設置輸入文字在對話窗中顯示的顏色、發言人對話文本顏色停靠窗myFontColorDock用於設置機器人應答文字在對話窗中顯示的顏色,二者的實現與fontDock類似,只是按鈕連接的槽方法不同,設置的按鈕顏色不同。在此不詳細介紹,大家可參考附件代碼。

2.4.6、構建暱稱設置停靠窗

暱稱設置停靠窗configDock包含內容部件configWin,configWin是一個單獨的ui設計模塊派生的類,用於設置輸入者暱稱和機器人暱稱,其ui設計界面如下:
在這裏插入圖片描述
在構建configDock時,將configWin作爲其內容部件。

2.4.7、排列停靠窗

將所有停靠窗對象及對應內容部件對象都創建後,接下來需要在QMainWindow中排列這些窗口,最終程序運行後的初始排列效果如下:在這裏插入圖片描述

要實現停靠窗的排列,需要分如下兩步進行:

2.4.7.1、將所有停靠窗按一定位置加到主窗口

按照上圖的排列,dialogDisplayDock在嘴上,輸入框在左邊,暱稱配置窗在右邊,其他在最下面,按此規則使用如下語句將停靠窗加入到主窗口:

		self.addDockWidget(QtCore.Qt.TopDockWidgetArea, self.dialogDisplayDock)
        self.addDockWidget(QtCore.Qt.LeftDockWidgetArea, self.inputDock)
        self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.configDock)
        self.addDockWidget(QtCore.Qt.BottomDockWidgetArea, self.fontDock)

        self.addDockWidget(QtCore.Qt.BottomDockWidgetArea, self.robertFontColorDock)
        self.addDockWidget(QtCore.Qt.BottomDockWidgetArea, self.myFontColorDock)
        self.configDock.setMinimumWidth(320)  #設置配置窗最小寬度
運行後效果:

在這裏插入圖片描述

2.4.7.2、使用splitDockWidget和tabifyDockWidget調整窗口位置

上圖不是我們要的效果,此時需要使用splitDockWidget來調整這些窗口的排列。首先將暱稱配置窗調整到輸入框右邊,然後將字體設置窗調整到輸入框下邊,最後將兩個顏色設置框與字體設置框進行選項卡化。使用如下代碼:

		self.splitDockWidget(self.inputDock, self.configDock, Qt.Horizontal) #暱稱配置窗調整到輸入框右邊
        self.splitDockWidget(self.inputDock,self.fontDock, Qt.Vertical) #將字體設置窗調整到輸入框下邊
        self.tabifyDockWidget(self.fontDock, self.myFontColorDock) #將輸入文字顏色設置框與字體設置框進行選項卡化
        self.tabifyDockWidget(self.fontDock, self.robertFontColorDock) #將機器人文字顏色設置框與字體設置框進行選項卡化

大家結合上章介紹的內容理解一下splitDockWidget和tabifyDockWidget的作用。

運行效果:在這裏插入圖片描述

發現達到了想要的效果。

2.4.8、實現對話窗發送消息後的響應槽方法inputEnd

在槽方法內需要設置輸入消息的字體顏色並顯示輸入信息,同時調用機器人應答方法輸出機器人應答消息。

    def inputEnd(self):
        if self.myColor: self.dialogDisplay.setTextColor(self.myColor)
        self.dialogDisplay.append(self.configWin.myName.text()+': '+ self.input.text())
        self.input.clear()
        self.robertAnswer() #輸出機器人應答消息

2.4.9、實現設置字體的槽方法getFont

getFont方法調用字體設置對話框來獲取需要設置的字體,對話框原字體作爲字體設置對話窗的初始字體。

    def getFont(self):#,visible):
        font = self.dialogDisplay.font()  #取現有字體
        font,changed = QtWidgets.QFontDialog.getFont(font,self,"字體設置")

        if changed:  self.dialogDisplay.setFont(font)

2.4.10、實現設置輸入文字或機器人應答文字顏色的槽方法getFontColor

getFontColor方法需要判斷信號發射對象是來自輸入文字顏色設置按鈕還是機器人應答消息顏色按鈕,然後根據不同取不同的初始顏色,並調用顏色選擇對話窗選擇顏色,並將顏色記錄後,將對應按鈕的文字顏色設置文新的顏色。相關代碼與設置字體類似,在此就不介紹了。

經過以上步驟,一個比較完整的人機對話簡單應用就構建完了。

廣告

老猿關於PyQt的付費專欄《使用PyQt開發圖形界面Python應用》只需要9.9元,該部分與第十五章的內容基本對應,但同樣內容在付費專欄上總體來說更詳細、案例更多。本節內容對應付費專欄的《第三十二章、使用splitDockWidget和tabifyDockWidget嵌套佈局QDockWidget的PyQt人機對話案例》。如果有興趣也願意支持老猿的讀者,歡迎購買付費專欄。

老猿Python,跟老猿學Python!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章