【问题标题】:How do I change the variable of this class如何更改此类的变量
【发布时间】:2021-12-06 13:14:37
【问题描述】:

我是 python 的新手,来自 Java,我想更新初始化类中的变量
这是我的完整代码

import datetime import time import threading

from tkinter import * from ibapi.client import EClient, TickAttribBidAsk from ibapi.wrapper import EWrapper, TickTypeEnum from ibapi.contract import Contract


class TestApp(EWrapper, EClient):

    def __init__(self):
        EClient.__init__(self, self)

    def tickPrice(self, reqId, tickType, price, attrib):
        print("Tick price. Ticker Id:", reqId, "tickType:", TickTypeEnum.to_str(tickType), "Price:", price, end=' ')

    def tickByTickBidAsk(self, reqId: int, time: int, bidPrice: float, askPrice: float, bidSize: int, askSize: int, tickAttribBidAsk: TickAttribBidAsk):
        print(bidPrice)
        tkinterApp.price1 = bidPrice


class Application:

    def runTest(self):
        app = TestApp()
        app.connect("127.0.0.1", 7497, 0)
        contract = Contract()
        contract.symbol = "PROG"
        contract.secType = "STK"
        contract.currency = "USD"
        contract.exchange = "SMART"
        contract.primaryExchange = "NASDAQ"

        time.sleep(1)

        app.reqMarketDataType(1)

        app.reqTickByTickData(19003, contract, "BidAsk", 0, True)

        app.run()

    def __init__(self):
        t = threading.Thread(target=self.runTest)
        t.start()
        self.runTest()


class TkinterClass:
    ibkrConnection = Application()
    root = Tk()
    root.title("test")
    root.grid_columnconfigure((0, 1), weight=1)
    titleTicker = Label(root, text="TICKER", bg='black', fg='white', width=100)
    titleRating = Label(root, text="PRICE", bg='black', fg='white', width=100)
    ticker1 = Label(root, text="PROG", bg='black', fg='white', width=100)
    
    price1 = Label(root, text=0, bg='black', fg='white', width=100) # To be changed with every tick
    
    titleTicker.grid(row=1, column=1)
    titleRating.grid(row=1, column=2)
    ticker1.grid(row=2, column=1)
    price1.grid(row=2, column=2)
    root.mainloop()


tkinterApp = TkinterClass()

def tickByTickBidAsk 是一个回调函数,每~2 秒调用一次 我想更新TkinterClass 类中的price1 变量,但是当我尝试执行我的代码时,tkinterApp.price1 = bidPrice 行给了我一个名称错误:TkinterClass is not defined

这可能是我知道的一个菜鸟错误:)

【问题讨论】:

  • 我不确定我是否明白你在做什么。但是你没有初始化 price1。因此,在 TkinterClass 的 init 中设置 price1 ,您可以通过 tkinterApp.price1 访问它
  • tkinterApp = TkinterClass() 行永远不会执行。 TkinterClass 类中有一堆静态代码,但没有方法。 root.mainloop() 不返回。
  • 你不能像这样在同一行组合import 命令。

标签: python python-3.x callback python-class tws


【解决方案1】:

如果你这样做可能会有所帮助:

class TkinterClass:
    def __init__(self):
        self.ibkrConnection = Application()
        self.root = Tk()
        self.root.title("test")
        self.root.grid_columnconfigure((0, 1), weight=1)
        self.titleTicker = Label(root, text="TICKER", bg='black', fg='white', width=100)
        self.titleRating = Label(root, text="PRICE", bg='black', fg='white', width=100)
        self.ticker1 = Label(root, text="PROG", bg='black', fg='white', width=100)
        self.price1 = Label(root, text=0, bg='black', fg='white', width=100) # To be changed with every tick
        self.titleTicker.grid(row=1, column=1)
        self.titleRating.grid(row=1, column=2)
        self.ticker1.grid(row=2, column=1)
        self.price1.grid(row=2, column=2)
    def run(self):
        self.root.mainloop()

tkinterApp = TkinterClass()
tkinterApp.run()

但是,仍然存在问题:

  1. 用数值覆盖tkinterApp.price1 Label

要设置标签,请使用:tkinterApp.price1.config(str(value)) 或使用tkinter StringVar 来存储price1 文本,并将StringVar 用作Label 值。

  1. 在两个线程中直接使用tkinterApp.price1 变量

如果您在后台线程中处理 Tk 变量,Tk 可能会不高兴。我建议在前台线程中运行某种计时器并轮询在后台更新的变量,因此您只需从前台更新 Tk 变量。

使用root.after(ms, callback) 在前台安排回调(在调用root.mainloop() 之前)。

我认为在读取另一个线程中更新的 Python 值时不需要threading.Lock,但可以肯定的是,在更新和访问逻辑周围添加lock()/unlock() 会更安全。

【讨论】:

    【解决方案2】:

    几年前我玩过 tk,这就是我构建代码的方式。我制作了一个 tkinter 窗口并从 tkinter 类连接到 TWS。

    from tkinter import *
    import threading
    
    from ibapi import wrapper
    from ibapi.client import EClient
    from ibapi.utils import iswrapper #just for decorator
    from ibapi.common import *
    from ibapi.ticktype import *
    from ibapi.contract import Contract
    
    class TkWdow():
        def __init__(self):
            root = Tk()
            frame = Frame(root)
            frame.pack()
            button = Button(frame, text="START", fg="green", command=self.start)
            button.pack(side=LEFT)
            button = Button(frame, text="ReqData", command=self.reqData)
            button.pack(side=LEFT)
            button = Button(frame, text="QUIT", fg="red", command=self.quit)
            button.pack(side=LEFT)
            self.output = Text(root, height=50, width=100)
            self.output.pack(side=BOTTOM)
            self.log("This is where output goes")
            root.mainloop()
            #root.destroy()
    
        def start(self):
            self.client = TestApp(self)
            self.log("starting")
            self.client.connect("127.0.0.1", 7497, clientId=123)
            thread = threading.Thread(target = self.client.run)
            thread.start()
            
        def log(self, *args):
            for s in args:
                self.output.insert(END, str(s) + " ")
                
            self.output.insert(END, "\n")    
                    
        def quit(self):
            self.log("quitting")
            self.client.disconnect()
            
        def reqData(self):
            self.log("reqData")
            cont = Contract()
            cont.symbol = "cl"
            cont.secType = "FUT"
            cont.currency = "USD"
            cont.exchange = "nymex"
            cont.lastTradeDateOrContractMonth = "202112"
            self.client.reqMktData(1, cont, "233", False, False, None)
            
        def cancelMktData(self, reqId:TickerId):
            super().cancelMktData(reqId)
            self.log('sub cancel')
            
        
    class TestApp(wrapper.EWrapper, EClient):        
        
        def __init__(self, wdow):
            self.wdow = wdow
            wrapper.EWrapper.__init__(self)
            EClient.__init__(self, wrapper=self)
            
        @iswrapper
        def nextValidId(self, orderId:int):
            self.wdow.log("setting nextValidOrderId: " , orderId)
            self.nextValidOrderId = orderId
    
        @iswrapper
        def error(self, reqId:TickerId, errorCode:int, errorString:str):
            self.wdow.log("Error. Id: " , reqId, " Code: " , errorCode , " Msg: " , errorString)
    
        @iswrapper
        def tickString(self, reqId:TickerId, tickType:TickType, value:str):
            if tickType == TickTypeEnum.RT_VOLUME:
                self.wdow.log(value)#price,size,time
    
    
    #if __name__ == "__main__":            
    TkWdow()
    

    【讨论】:

      猜你喜欢
      • 2019-12-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多