2023年7月4日 星期二

【Python交易程式開發現場32】使用QTableWidget顯示倉位(4) | 將倉位接受物件內之倉位資訊填入QtTableWidget

目標: 將倉位接受物件內之倉位資訊填入QtTableWidget


先熱身, 複習之前學到的重點:

Slot物件/Slot函數的設定

設定【送信員】, 【收信人】

##############################################################################
#  Qt Signal/Slot
##############################################################################

# 信号对象
class QTypeSignal(QObject):
    # 定义一个信号
    sendmsg = pyqtSignal(object)

    def __init__(self):
        super(QTypeSignal, self).__init__()  #super() 函数是用于调用父类(超类)的一个方法。

    def run(self, msg):
        # 发射信号
        self.sendmsg.emit(msg)


# 槽对象          
class QTypeSlot(QObject):
    def __init__(self):
        super(QTypeSlot, self).__init__()

        # 槽物件Slot里的槽函数
    def get(self, msg):
        #print("QSlot get msg => ")
        myWin.showMessage(msg) #Slot函數

設定【送信員】進行送信動作
    def OnNotifyQuoteLONG(self, sMarketNo, nStockidx):    #ctw # 3-【查詢】回報    
        pStock = sk.SKSTOCKLONG()
        m_nCode = skQ.SKQuoteLib_GetStockByIndexLONG(sMarketNo, nStockidx, pStock)
        strMsg = '代碼:',pStock.bstrStockNo,'--名稱:',pStock.bstrStockName,'--開盤價:',str(pStock.nOpen/math.pow(10,pStock.sDecimal)),'--最高:',\
            str(pStock.nHigh/math.pow(10,pStock.sDecimal)),'--最低:',\
            str(pStock.nLow/math.pow(10,pStock.sDecimal)),'--成交價:',str(pStock.nClose/math.pow(10,pStock.sDecimal))\
            ,'--總量:',str(pStock.nTQty)
               
        twStrMsg=twTuple_2_Str(strMsg)
        send.run(twStrMsg) #發射Signal訊號

    # --------------------------> key point 2: Tick Event
    def OnNotifyHistoryTicksLONG(self, sMarketNo, nStockidx, nPtr, lDate, lTimehms, lTimemillismicros, nBid, nAsk, nClose, nQty, nSimulate):
        # 4-【查詢歷史Tick】回報
        strMsg = "[OnNotifyHistoryTicksLONG]", nStockidx, nPtr, lDate, lTimehms, lTimemillismicros, nBid, nAsk, nClose, nQty, nSimulate
        twStrMsg=twTuple_2_Str(strMsg)
        send.run(twStrMsg)  #發射Signal訊號
        #WriteMessage(strMsg,Gobal_Tick_ListInformation)
        tw_full_time = twTimeConv(lDate, lTimehms, lTimemillismicros) #ctw
        twGlobal.twClose.Add(tw_full_time,float(nClose/100), nQty)  #ctw
        twGlobal.twKBar1M.Add(tw_full_time,float(nClose/100), nQty)  #ctw

設定【收信人】該進行的動作





自訂Signal/Slot的連接

主程式中send signal的Signal物件send


##############################################################################
# 主程式
##############################################################################

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

    send = QTypeSignal()
    slot = QTypeSlot()
   
    # 1
    print('--- 把信号绑定到槽函数 ---')
    send.sendmsg.connect(slot.get)
    #send.run()

    # 2
    #print('--- 把信号断开槽函数 ---')
    #send.sendmsg.disconnect(slot.get)
    #send.run()

    sys.exit(app.exec())  

class MyMainWindow(QMainWindow, Ui_Form):
    def __init__(self, parent=None):    
        super(MyMainWindow, self).__init__(parent)
        self.setupUi(self)
        self.pushButton.clicked.connect(self.twTest1) #ctw signal
        self.pushButton_2.clicked.connect(self.twTest2) #ctw signal
        self.pushButton_3.clicked.connect(self.twTest3) #ctw signal
        self.pushButton_4.clicked.connect(self.twTest8) #ctw signal
        self.pushButton_5.clicked.connect(self.twTest4) #ctw signal
        self.pushButton_6.clicked.connect(self.twTest5) #ctw signal      
        self.pushButton_7.clicked.connect(self.twTest6) #ctw signal
        self.pushButton_8.clicked.connect(self.twTest7) #ctw signal
        self.pushButton_9.clicked.connect(self.twTest9) #ctw signal    
        self.pushButton_10.clicked.connect(self.twTest10) #ctw signal  
        self.pushButton_11.clicked.connect(self.twTest11) #ctw signal    

    def twTest1(self):  #ctw slot function
        print("1-登入")    
        self.listWidget.addItem("1-登入")
        twLogin(ID, PW)


    def twTest11(self):  #ctw slot function
        print("11-倉位查詢")    
        self.listWidget.addItem("9-倉位查詢")
        self.listWidget.addItem("m_nCode1: " + str(twSKO3_GetAccount()))  
        self.listWidget.addItem("m_nCode2: " + str(twSKO4_GetOpenInterest(ID, ACCOUNT)))  
        self.tableWidget.setItem(1,1,
        QTableWidgetItem("倉位查詢"))
        #listWidget.addItem("m_nCode2: " + str(twSKO4_GetOpenInterest(ID, ACCOUNT)))  
        #self.listWidget.addItem("m_nCode: " + str(twDisconnect()))  

    def showMessage(self, msg):
        self.listWidget.addItem(msg)

        #global GlobalListInformation,Global_ID
        #GlobalListInformation = self.listWidget
        #Global_ID = self.labelID    


開始改碼:

call_twMain.py(修正1)

# 自訂Signal信号物件
class QTypeSignal(QObject):
    # 定义一个信号
    sendmsg = pyqtSignal(object)
    sendmsg1 = pyqtSignal(object)

    def __init__(self):
        super(QTypeSignal, self).__init__()  #super() 函数是用于调用父类(超类)的一个方法。

    def run(self, msg):  # 发射信号給QList
        self.sendmsg.emit(msg)

    def signal_to_qtable(self, msg):  # 发射信号給QList
        self.sendmsg1.emit(msg)    

# 自訂Slot槽物件          
class QTypeSlot(QObject):
    def __init__(self):
        super(QTypeSlot, self).__init__()

    # 槽对象里的槽函数
    def get(self, msg):
        #print("QSlot get msg => ")
        myWin.showMessage(msg)   #Slot函數

    def get_from_interest_signal(self, msg): # 槽对象里的槽函数
        myWin.showMessage(msg)   #Slot函數  

##############################################################################
# 主程式
##############################################################################

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

    send = QTypeSignal()
    slot = QTypeSlot()
   
    # 1
    print('--- 把信号绑定到槽函数 ---')
    send.sendmsg.connect(slot.get)
    send.sendmsg1.connect(slot.get_from_interest_signal)
    #send.run()

    # 2
    #print('--- 把信号断开槽函数 ---')
    #send.sendmsg.disconnect(slot.get)
    #send.run()


設定【送信員】進行送信動作

  def OnOpenInterest(self,bstrData):
        #self.__obj["msg"].WriteMessage(bstrData,GlobalListInformation)
        print(bstrData)
        strValues = bstrData.split(',')
        #strInterest = strValues[1] + strValues[3]
        #strValues[2]: 商品名稱
        #strValues[3]: 買賣(B/S)
        #strValues[4]: 口數
        if strValues[0] != '##':
            twGlobal.twInterest.Add(strValues[2] ,strValues[3] , strValues[4] )  #ctw
        else:  # 倉位全部接收完畢後, 將倉位填入QtTableWidget中
            send.signal_to_qtable(twTuple_2_Str(twGlobal.twInterest.GetName()))  #發射Signal訊號給QtTable顯示函式
            #pass  


call_twMain.py(修正2)

    def OnOpenInterest(self,bstrData):
        #self.__obj["msg"].WriteMessage(bstrData,GlobalListInformation)
        print(bstrData)
        strValues = bstrData.split(',')
        #strInterest = strValues[1] + strValues[3]
        #strValues[2]: 商品名稱
        #strValues[3]: 買賣(B/S)
        #strValues[4]: 口數
        if strValues[0] != '##':
            twGlobal.twInterest.Add(strValues[2] ,strValues[3] , strValues[4] )  #ctw
        else:  # 倉位全部接收完畢後, 將倉位填入QtTableWidget中
            pass  
        send.run(twStrMsg)  #發射Signal訊號給QtTable顯示函式



成功送出倉位資訊到QListWidget..




設定【收信人】該進行的動作


    def showMessage(self, msg):
        self.listWidget.addItem(msg)

        #global GlobalListInformation,Global_ID
        #GlobalListInformation = self.listWidget
        #Global_ID = self.labelID    

    def showInterest(self, msg):
        self.tableWidget.setItem(2,1,QTableWidgetItem("interest"))  


call_twMain.py(修正3)

# 自訂Slot槽物件          
class QTypeSlot(QObject):
    def __init__(self):
        super(QTypeSlot, self).__init__()

    # 槽对象里的槽函数
    def get(self, msg):
        #print("QSlot get msg => ")
        myWin.showMessage(msg)   #Slot函數

    def get_from_interest_signal(self, msg): # 槽对象里的槽函数
        #print("QSlot get msg => ")
        myWin.showInterest(msg)  #Slot函數    


成功送出訊息到QTableWidget..



call_twMain.py(修正4)

    def showInterest(self, msg):
        self.tableWidget.setItem(2,1,QTableWidgetItem(msg))  



call_twMain.py(修正5)

    def showInterest(self, msg): #自己讀取twInterestModel倉位物件
        #twGlobal.twInterest.GetName()
        for i in range(len(twGlobal.twInterest.GetName())):
            self.tableWidget.setItem(i,1,QTableWidgetItem(twGlobal.twInterest.GetName()[i]))  


call_twMain.py(修正6)

    def showInterest(self, msg): #自己讀取twInterestModel倉位物件
        #twGlobal.twInterest.GetName()
        for i in range(len(twGlobal.twInterest.GetName())):
            self.tableWidget.setItem(i,0,QTableWidgetItem(twGlobal.twInterest.GetName()[i]))      
            self.tableWidget.setItem(i,1,QTableWidgetItem(twGlobal.twInterest.GetBuySell()[i]))  
            self.tableWidget.setItem(i,2,QTableWidgetItem(twGlobal.twInterest.GetVolume()[i]))  





2023年7月3日 星期一

【Python交易程式開發現場30】在VS Code中使用Python虛擬環境之問題解決 | Comtypes和python版本的相容問題 | ModuleNotFoundError: No module named ‘comtypes.gen.SKCOMLib’

程式執行時遇到了: ModuleNotFoundError: No module named ‘comtypes.gen.SKCOMLib’


1. 參考網路解答1:(失敗收場)

問題:ModuleNotFoundError: No module named ‘comtypes.gen.SKCOMLib’

第一、原因:python 版本問題(3.8 不能)

第二、註冊問題(SKCOM.dll 要和主程式同目錄)

import comtypes.client 
comtypes.client.GetModule(os.path.split(os.path.realpath(__file__))[0] + r'\SKCOM.dll')






2. 參考網路解答2:(失敗收場)


.venv下的comtypes下沒產生gen目錄?


3. 參考網路解答3:(失敗收場)

###########################################################
# pythoncom 是安裝 pywin32 附的,如果 event 沒反應才需要用到
# 第一次使用cc.GetModule, 會在 comtypes\gen\ 下產生幾個.py檔,像是
# _75AAD71C_8F4F_4F1F_9AEE_3D41A8C9BA5E_0_1_0.py
# 如果有 dll 錯誤產生,請檢查 SKCOM.dll 路徑有沒有錯誤
# 如果發生 gen 下沒有 SKCOMLib 錯誤訊息,請將python關閉
# AttributeError: module 'comtypes.gen.SKCOMLib' has no attribute 'SKCenterLib'
# 重新啟動python後,應該就可以找到了
# 如果還是不行,請重新安裝 capital API 元件,注意 API 與python 版本要一致,
# API安裝要以管理員權限執行
# 20190506,程式碼簡化
import pythoncom, time
import comtypes.client as cc

cc.GetModule('C:\\SKCOM\\x86\\SKCOM.dll')
import comtypes.gen.SKCOMLib as sk

4. 參考網路解答4:(失敗收場)



3

I just figured out what the cryptic "SyntaxError: multiple exception types must be parenthesized" message means. All it's trying to tell you is that in the newer version of Python you're using, this syntax is no longer valid:

except COMError, err:

instead, you should be using this syntax:

except COMError(err):


5. 參考網路解答後, 自己想出兩個解法, 第一個解法:(失敗收場)

先用賤招, 將gen由原global的python310目錄中正常的comtypes中的gen搬到.venv中的comtypes中來,
結果問題只解決一半, comtypes.gen的確找到了, 但"multiple exception types must be parenthesized" 的python和comtypes版本不相容的問題仍未解決..

6. 參考網路解答後, 自己想出的第二個解法:(成功)

最後, 用pip install --upgrade comtypes 才解決問題







prog-0318

test test1 Written with StackEdit .