注射泵開發(fā)--二(App應(yīng)用)

功能需求

需求

分解需求

  • 初始化
  • 排空

界面布局

布局
  • 將界面ui文件編譯為py文件
    • 利用pyuic5工具進(jìn)行财岔,pyuic5 -o ui_xxx.py xxx.ui
    • 編譯后的ui_xxx.py文件實(shí)際上是一個(gè)數(shù)據(jù)類
    • 在該類里有創(chuàng)建窗口控件的代碼和控件的屬性配置數(shù)據(jù)

提升控件

  • 現(xiàn)有的控件不足以表示注射泵的狀態(tài)
  • 需要自定義控件时鸵,Qt提供了promote(提升)操作


    image.png

    image.png
  • 這樣就會(huì)有一個(gè)提升類Injector,這個(gè)控件就會(huì)是Injector的實(shí)例
  • 在Python中實(shí)現(xiàn)這個(gè)類

資源

  • 界面上需要用到一些圖片等資源
  • 這些資源在QT中有專門的resource系統(tǒng)
  • 創(chuàng)建一個(gè)qrc文件戈次,在文件中描述需要引用的資源
<RCC>
    <qresource prefix="/res">

    <file alias="v0">input.fw.png</file>
    <file alias="v120">ManualPurge.fw.png</file>
    <file alias="v240">output.fw.png</file>
    <file alias="inj">planger.fw.png</file>
    
    <file>megarobo.ico</file>
    </qresource>
</RCC>
  • 這個(gè)資源文件也需要被編譯為py數(shù)據(jù)文件
    • pyrcc5 -o xxx.py xxx.qrc
  • 對(duì)資源項(xiàng)目可以取個(gè)別名,便于在程序中通過狀態(tài)碼來得到資源數(shù)據(jù)
  • 幾張圖片,分別表示注釋器和閥門的3種狀態(tài)趁餐,從而組合出注射泵的工作狀態(tài)


    planger.fw.png
ManualPurge.fw.png
output.fw.png
input.fw.png

技術(shù)棧

  • pyQt
  • mega studio

引入包

  • 系統(tǒng)包
  • pyQt相關(guān)包
  • injector模塊:自定義的注射泵狀態(tài)控件
  • 界面模塊:利用QtDesigner設(shè)計(jì)的form
    • 界面模塊需要利用pyuic5.exe進(jìn)行編譯散怖,轉(zhuǎn)換為py數(shù)據(jù)文件
  • 資源模塊:
    • 利用pyrcc5進(jìn)行編譯
    • 資源中含有一些圖片和圖片的別名
  • mrq.inj2
    • 這是MEGAROBO對(duì)注射泵的Python封裝
import sys

import time
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

import injector
import ui_mrx_inj2
import qrc_mrx_inj2

import mrq.inj2

創(chuàng)建窗口類

class mrxInj2( QWidget, ui_mrx_inj2.Ui_Form ):
    def __init__( self, parent = None):

創(chuàng)建設(shè)備

def onConnect( self ):
        self.mInj2 = mrq.inj2.Inj2( self.edtDevice.text() )
        self.labIdn.setText( self.mInj2.IDN )  

        self.validateUi()

事件驅(qū)動(dòng)

  • 事件發(fā)生后菇绵,調(diào)用設(shè)備的相關(guān)方法進(jìn)行響應(yīng)
  • 為按鈕添加消息處理函數(shù)
  • 例如“閥門”切換到“吸入”狀態(tài)
  • 控制電機(jī)轉(zhuǎn)動(dòng)
def onLeft( self ):
        if ( self.mValve == 0 ):
            pass
        elif ( self.mValve == 120 ):
            self.mInj2.rotate( 0,0, self.mValveSepAngle, self.mValveSepTime )
            self.setValve( 0 )                        
        else:
            self.mInj2.rotate( 0,0, -self.mValveSepAngle, self.mValveSepTime )
            self.setValve( 0 )

建立事件和響應(yīng)的聯(lián)系

def buildConnection( self ):

        self.btnValveCcw.clicked.connect( self.onLeft )

創(chuàng)建界面,啟動(dòng)消息循環(huán)

    app = QApplication( sys.argv )

    inj2 = mrxInj2()
    inj2.show()

    app.exec_()

漂亮一點(diǎn)

  • 為界面添加風(fēng)格樣式
 fo = open("./mega.qss", "r")
        dat = fo.read()
        fo.close()
        app.setStyleSheet( dat )
添加風(fēng)格

代碼

#! coding:utf-8

import sys

import time
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

import injector
import ui_mrx_inj2
import qrc_mrx_inj2

import mrq.inj2

class mrxInj2( QWidget, ui_mrx_inj2.Ui_Form ):
    def __init__( self, parent = None):
        super( mrxInj2, self ).__init__( parent )
        self.setupUi( self )

        self.buildConnection()

        self.setWindowIcon( QIcon(":/res/megarobo.ico") )

        self.init()

        # members            
        self.mInj2 = None

        self.mInjMax = 60

        self.mValveSepAngle = 120       # sep angle
        self.mValveSepTime = 0.5

        self.validateUi()

        self.setInj( 0 )
        self.setValve( 0 )

    def buildConnection( self ):
        self.btnValveCw.clicked.connect( self.onRight )
        self.btnValveCcw.clicked.connect( self.onLeft )
        self.btnManualPurge.clicked.connect( self.onManualPurg )

        self.btnSuction.clicked.connect( self.onSuction )
        self.btnInjection.clicked.connect( self.onInjection )

        self.btnConnect.clicked.connect( self.onConnect )
        self.btnDisconnect.clicked.connect( self.onDisconnect )

        self.btnCenter.clicked.connect( self.onCenter )
        self.btnPurging.clicked.connect( self.onPurging )
  
        # self.sldInj.valueChanged.connect( self.onInjValue )

    # right
    # 0      240      120
    # \      \  /      /
    #  \      \/      /
    #  |              |
    #  |              |
    #  0      120     240 
    def onRight( self ):
        if ( self.mValve == 0 ):
            self.mInj2.rotate( 0,0, self.mValveSepAngle, self.mValveSepTime )
            self.setValve( 240 )
        elif ( self.mValve == 120 ):
            self.mInj2.rotate( 0,0, -self.mValveSepAngle, self.mValveSepTime )
            self.setValve( 240 )                        
        else:
            pass

    # left
    def onLeft( self ):
        if ( self.mValve == 0 ):
            pass
        elif ( self.mValve == 120 ):
            self.mInj2.rotate( 0,0, self.mValveSepAngle, self.mValveSepTime )
            self.setValve( 0 )                        
        else:
            self.mInj2.rotate( 0,0, -self.mValveSepAngle, self.mValveSepTime )
            self.setValve( 0 )

    # manual purge
    def onManualPurg(self):
        if ( self.mValve == 0 ):
            self.mInj2.rotate( 0,0, -self.mValveSepAngle, self.mValveSepTime )
            self.setValve( 120 )                                        
        elif ( self.mValve == 240 ):
            self.mInj2.rotate( 0,0, self.mValveSepAngle, self.mValveSepTime )
            self.setValve( 120 )                                        
        else:
            pass

    def onSuction( self ):
        dLen = self.mInjMax - self.mInj 

        if ( dLen > self.spinSucLen.value() ):
            dLen = self.spinSucLen.value()
        else:
            pass             

        self.mInj2.line( 0,0, dLen, self.spinSucTime.value() )
        self.setInj( dLen + self.mInj )

    def onInjection( self ):
        if ( self.mInj > self.spinInjLen.value() ):
            dLen = self.spinInjLen.value()
        else:
            dLen = self.mInj 

        self.mInj2.line( 0,0, -dLen, self.spinInjTime.value() )
        self.setInj( self.mInj - dLen )

    def onConnect( self ):
        self.mInj2 = mrq.inj2.Inj2( self.edtDevice.text() )
        self.labIdn.setText( self.mInj2.IDN )  

        self.validateUi()

    def onDisconnect( self ):
        self.mInj2.close()
        self.mInj2 = None

        self.validateUi()    

    def onCenter( self ):
        self.mInj2.center()   
        self.init()

    def init( self ):
        self.setInj( 0 )
        self.setValve( 0 )

    # valve
    def setValve( self, deg ):
        self.mValve = deg
        self.widgetInj.setAngleIndex( deg )

    def setInj( self, depth ):
        self.lcdInj.display( depth )
        self.mInj = depth
        self.widgetInj.setLen( depth )

    def validateUi( self ):
        if ( self.mInj2 == None ):
            bValidate = False
        else:
            bValidate = True

        self.spinSucTime.setEnabled( bValidate )
        self.spinSucLen.setEnabled( bValidate )

        self.spinInjTime.setEnabled( bValidate )
        self.spinInjLen.setEnabled( bValidate )
        self.spinPurgCnt.setEnabled( bValidate )
        
        self.btnValveCcw.setEnabled( bValidate )
        self.btnValveCw.setEnabled( bValidate )
        self.btnManualPurge.setEnabled( bValidate )
        self.btnSuction.setEnabled( bValidate )
        self.btnInjection.setEnabled( bValidate )

        self.btnConnect.setEnabled( not bValidate )
        self.btnDisconnect.setEnabled( bValidate )

        self.btnCenter.setEnabled( bValidate )
        self.btnPurging.setEnabled( bValidate )

    def cbProcess( self ):
        QApplication.processEvents()

    def onPurging( self):
        #! program
        self.mInj2.purge( 0, 0, 
                          self.mValveSepAngle,
                          self.spinPurgeLength.value(), 
                          self.spinPurgeTime.value() )            
        self.mInj2.waitIdle( 0, 0, 60, self.cbProcess )

        #! call 
        # for i in range( 1, self.spinPurgCnt.value() ):
        loopCnt = self.spinPurgCnt.value() - 1
        if ( loopCnt > 0 ):
            self.mInj2.call( 0, 0, loopCnt )
            self.mInj2.waitIdle( 0, 0, loopCnt * self.spinPurgeTime.value() * 2, self.cbProcess )

if __name__ == "__main__":
    app = QApplication( sys.argv )

    try:
        fo = open("./mega.qss", "r")
        dat = fo.read()
        fo.close()
        app.setStyleSheet( dat )
    except IOError as e:
        print( "fail to load qss")
        pass         

    inj2 = mrxInj2()
    inj2.show()

    app.exec_()
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末镇眷,一起剝皮案震驚了整個(gè)濱河市咬最,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌欠动,老刑警劉巖永乌,帶你破解...
    沈念sama閱讀 207,248評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異具伍,居然都是意外死亡翅雏,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門人芽,熙熙樓的掌柜王于貴愁眉苦臉地迎上來望几,“玉大人,你說我怎么就攤上這事萤厅¢夏ǎ” “怎么了?”我有些...
    開封第一講書人閱讀 153,443評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵惕味,是天一觀的道長楼誓。 經(jīng)常有香客問我,道長名挥,這世上最難降的妖魔是什么疟羹? 我笑而不...
    開封第一講書人閱讀 55,475評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上阁猜,老公的妹妹穿的比我還像新娘丸逸。我一直安慰自己,他們只是感情好剃袍,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評(píng)論 5 374
  • 文/花漫 我一把揭開白布黄刚。 她就那樣靜靜地躺著,像睡著了一般民效。 火紅的嫁衣襯著肌膚如雪憔维。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,185評(píng)論 1 284
  • 那天畏邢,我揣著相機(jī)與錄音业扒,去河邊找鬼。 笑死舒萎,一個(gè)胖子當(dāng)著我的面吹牛程储,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播臂寝,決...
    沈念sama閱讀 38,451評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼章鲤,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了咆贬?” 一聲冷哼從身側(cè)響起败徊,我...
    開封第一講書人閱讀 37,112評(píng)論 0 261
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎掏缎,沒想到半個(gè)月后皱蹦,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,609評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡眷蜈,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評(píng)論 2 325
  • 正文 我和宋清朗相戀三年沪哺,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片酌儒。...
    茶點(diǎn)故事閱讀 38,163評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡凤粗,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出今豆,到底是詐尸還是另有隱情,我是刑警寧澤柔袁,帶...
    沈念sama閱讀 33,803評(píng)論 4 323
  • 正文 年R本政府宣布呆躲,位于F島的核電站,受9級(jí)特大地震影響捶索,放射性物質(zhì)發(fā)生泄漏插掂。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望辅甥。 院中可真熱鬧酝润,春花似錦、人聲如沸璃弄。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽夏块。三九已至疏咐,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間脐供,已是汗流浹背浑塞。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評(píng)論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留政己,地道東北人酌壕。 一個(gè)月前我還...
    沈念sama閱讀 45,636評(píng)論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像歇由,于是被迫代替她去往敵國和親卵牍。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理印蓖,服務(wù)發(fā)現(xiàn)辽慕,斷路器,智...
    卡卡羅2017閱讀 134,601評(píng)論 18 139
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,527評(píng)論 25 707
  • 國家電網(wǎng)公司企業(yè)標(biāo)準(zhǔn)(Q/GDW)- 面向?qū)ο蟮挠秒娦畔?shù)據(jù)交換協(xié)議 - 報(bào)批稿:20170802 前言: 排版 ...
    庭說閱讀 10,871評(píng)論 6 13
  • 1.ios高性能編程 (1).內(nèi)層 最小的內(nèi)層平均值和峰值(2).耗電量 高效的算法和數(shù)據(jù)結(jié)構(gòu)(3).初始化時(shí)...
    歐辰_OSR閱讀 29,321評(píng)論 8 265
  • 嘆赦肃,物是人非何足掛念溅蛉;往日之事猶如莊生夢蝶,難辨真假他宛,奈何船侧,輕聲喚,浮生若夢厅各,快些醒來镜撩!—Lily
    Lilylylyly閱讀 172評(píng)論 0 0