0. 廢話不是CS專業(yè),從來沒做過界面,入職就被分配了寫一個(gè)上位機(jī)的工作。幸虧讀master的時(shí)候被操練得盲目自信不怕困難,說干就干。邊學(xué)邊寫用Matlab寫了個(gè)很爛的上位機(jī),一旦啟動(dòng)阻塞電腦其他所有動(dòng)作…… 但是也算能用了,空閑了幾天,這時(shí)候有了新需求,那么就趁機(jī)學(xué)一下Qt吧。開始的時(shí)候,決定用PyQt 5 + Python 3,因?yàn)楦杏X比C++開發(fā)速度快。新需求完成后,就決定繼續(xù)把舊的功能移植過來了,最后……又做了一個(gè)很爛的上位機(jī)?!昂軤€”主要是性能問題,后面再細(xì)說。 請(qǐng)多指教。 1. 開發(fā)環(huán)境1.1 Python 3筆者也不知道Python 2用來開發(fā)會(huì)怎樣,選Python 3一是因?yàn)榭吹絇ython 2將停止維護(hù)還是什么的,二是用Vim的時(shí)候不少插件要Python 3支持。筆者是在Windows 7上開發(fā),安裝Python 3之后,就可以用pip安裝需要的包了,比如說最主要的PyQt 5。中途從Python 3.5換到3.6,因?yàn)楦铝薞im,結(jié)果是并無影響,至少是在這個(gè)項(xiàng)目涉及到的范圍內(nèi)沒有影響。 1.2 PyQt 5不需要安裝Qt 5。一開始以為使用PyQt 5要先安裝Qt 5,后來在另外一臺(tái)電腦上搭環(huán)境的時(shí)候嘗試了一下,發(fā)現(xiàn)并不需要。開始用的時(shí)候是PyQt/Qt 5.9,寫這篇文章的時(shí)候是5.10了。PyQt 5相對(duì)于4,很多類都被移動(dòng)了,目前來說網(wǎng)上的PyQt 5的教程比4的少很多,雖然可以參考著來開發(fā),但是import的時(shí)候就要小心了,要去PyQt 5的網(wǎng)站或Qt官網(wǎng)查看一下。 1.3 Vim既然提到了,就稍微說一下,并不是要引戰(zhàn)。筆者是學(xué)ROS的時(shí)候突然想起有這么個(gè)編輯器,懷著一顆好奇心就入坑了,花了一個(gè)星期入門——“入門”的意思是知道:wq等等。筆者腦子不好使,.h和.c(pp)分開看不行,界面和邏輯分開看也不行,也嘗試過學(xué)習(xí)Emacs之類,無奈再也沒有這么多時(shí)間了,所以一直用Vim。另外通過配置vimrc也可以直接在Vim中通過快捷鍵運(yùn)行Python代碼。 Vim用了快3年,配置上基本滿足當(dāng)前需求了,不能說是高端配置。先挖個(gè)坑,后面補(bǔ)一篇指南,比如語法檢查插件ALE我就搞了很久。 2. 開始2.1 入門資料還是先上點(diǎn)入門資料吧。 (1) First Programs in PyQt 5 - 建議先看這個(gè)。 (2) 《Matplotlib for Python Developers》的Chapter No. 6 - 第6章講的是怎么把matplotlib的坐標(biāo)嵌入到PyQt中去,但例子用的都是PyQt 4,需要讀者自行移植。其他matplotlib的內(nèi)容,筆者都是通過其官方文檔及Stack Overflow學(xué)習(xí)的。 2.2 main.py也許主文件為其他命名也可以,但是筆者的主文件就是一鍋粥,以main概括就是了;里面是各個(gè)面板的實(shí)例化,以及最重要的——整個(gè)程序的實(shí)例化。這里要用到的是:
PyQt 4的界面有很多種風(fēng)格可選,但是PyQt 5中刪減了。可通過setStyle函數(shù)來設(shè)置:
2.3 界面2.3.1 窗口:QMainWindow, QWidgets在看過的教程里,似乎主窗口都要用到QMainWindow:
用的時(shí)候并沒有深究為什么一定要用QMainWindow,后來其他部件全都是用QWidget。 QWidget用法和以上代碼差不多,就改個(gè)類名。主要用來做了一些從主窗口分離出去的小面板,例如嵌入了matplotlib的面板。 2.3.2 窗口屬性筆者寫的軟件只定義了窗口初始大小和位置,以及圖標(biāo):
2.3.3 創(chuàng)建組件先把用到的組件列一下:
(1) 1至3行是用來嵌入matplotlib的,QSizePolicy的用法,筆者也是對(duì)著教程依樣畫葫蘆:
(2) 14行的QStyleFactory是與8行的QDial配合用的,筆者用QDial簡單封裝了一個(gè)羅盤,但是QDial的指針樣式在PyQt 5里默認(rèn)是一個(gè)圓點(diǎn),需要用QStyleFactory強(qiáng)制顯示為針狀(只列出部分代碼,其他屬性請(qǐng)自行設(shè)置):
(3) 第6行QCheckBox:很直接,用于勾選某些選項(xiàng) (4) 第7行QComboBox:用于創(chuàng)建下拉菜單
addItem的第一個(gè)參數(shù)為菜單顯示的字符串,第二個(gè)參數(shù)為item里對(duì)應(yīng)的數(shù)據(jù),可通過itemData來獲取,例如,在上述例子的前提下,以下語句為True:
(5) 第9行QGroupBox:就是在窗口里的一個(gè)小區(qū)域,視覺上將一些關(guān)系緊密組件放在一起,可以為這個(gè)group設(shè)置一個(gè)名字。QGroupBox在面板的QGridLayout上用addWidget從(0,0)開始擺放后,組內(nèi)要另外定義QGridLayout,從(0,0)開始擺放組件。其他細(xì)節(jié)請(qǐng)自行參考官方文檔。 (6) 第10、11行配合使用:QLabel即創(chuàng)建標(biāo)簽,通常用來標(biāo)記QLineEdit里顯示的數(shù)據(jù)是什么東西。QLineEdit中,用setText來設(shè)置要顯示的數(shù)據(jù),同時(shí)可用setReadOnly防止數(shù)據(jù)被誤改;如果是作為輸入框,用getText然后轉(zhuǎn)換數(shù)據(jù)類型。其他細(xì)節(jié)請(qǐng)自行參考官方文檔。 (7) 第12行QProgressBar:用來當(dāng)作電池顯示條。隨便鼓搗自己想要的功能,其中還用到一個(gè)網(wǎng)站(uiGradient)提供的漸變色配色方案。 (8) 第13行QPushButton:創(chuàng)建按鈕,可用setCheckable(True)來使得按鈕可以保持按下(Checked)的狀態(tài)。 2.3.4 組件布局筆者只用了QGridLayout,因?yàn)楦杏X這個(gè)布局便于安排組件。雖然冥冥中感覺QVBoxLayout和QHBoxLayout能夠讓界面在resize的過程中使組件的位置保持得更好(如使用addStrecth等,若有誤懇請(qǐng)讀者賜教),但由于并不是產(chǎn)品級(jí)的軟件,所以什么方便快捷就用什么了。QGridLayout中的setRowStrecth和setColumnStretch只是用來對(duì)齊不同QBoxGroup中的組件,但效果也并不完美。 原理上,setRowStrecth和setColumnStretch可以用來調(diào)整不同組件所占空間的大小,但是筆者直接用addWidget來調(diào)整了:
|
|