主界面的Tick显示在订阅数过多的情况下,刷新压力过大,严重会造成界面卡死。为了解决这个问题,做了分页刷新的功能。
把原来的tick显示改为tab显示,显示时只刷新当中选中的tab页。
talk is cheap, show code:

1、在vnpy->trader->ui->widget增加TabTickMonitor类,作为每个tab页的实际内容承载,其实主要就去掉了原TickMonitor的EventTick事件响应

class TabTickMonitor(BaseMonitor):
"""
Monitor for tick data.
"""
data_key = "vt_symbol"
sorting = True

headers = {
    "symbol": {"display": "代码", "cell": BaseCell, "update": False},
    "exchange": {"display": "交易所", "cell": EnumCell, "update": False},
    "name": {"display": "名称", "cell": BaseCell, "update": True},
    "last_price": {"display": "最新价", "cell": BaseCell, "update": True},
    "volume": {"display": "成交量", "cell": BaseCell, "update": True},
    "open_price": {"display": "开盘价", "cell": BaseCell, "update": True},
    "high_price": {"display": "最高价", "cell": BaseCell, "update": True},
    "low_price": {"display": "最低价", "cell": BaseCell, "update": True},
    "bid_price_1": {"display": "买1价", "cell": BidCell, "update": True},
    "bid_volume_1": {"display": "买1量", "cell": BidCell, "update": True},
    "ask_price_1": {"display": "卖1价", "cell": AskCell, "update": True},
    "ask_volume_1": {"display": "卖1量", "cell": AskCell, "update": True},
    "datetime": {"display": "时间", "cell": TimeCell, "update": True},
    "gateway_name": {"display": "接口", "cell": BaseCell, "update": False},
}

def __init__(self, main_engine: MainEngine, event_engine:EventEngine, tab_name:str):
    super().__init__(main_engine, event_engine)
    self.tab_name = tab_name
    self.bind_tick_signal()

def bind_tick_signal(self):
    self.signal.connect(self.process_event)
    self.event_engine.register(self.event_type, self.signal.emit)

def update_tick_event(self, event):
    self.signal.emit(event)

2、增加PortionTickMonitor作为Tab页控件,承载所有表格,同时作为tick事件的入口,选择当前的Tab页进行刷新。达到TAB_SYMBOL_COUNT指定的合约数量后自动添加新的tab页

class PortionTickMonitor(QtWidgets.QTabWidget):
"""

"""
signal: QtCore.pyqtSignal = QtCore.pyqtSignal(Event)
TAB_SYMBOL_COUNT = 20

def __init__(self, main_engine: MainEngine, event_engine: EventEngine):
    super().__init__()
    self.main_engine = main_engine
    self.event_engine = event_engine
    self.tab_widget_list: List[TabTickMonitor] = []
    self.tab_widget_dict: Dict[str, TabTickMonitor] = {}
    self.symbol_tab_map: Dict[str, TabTickMonitor] = {}
    self.tab_symbol_count: Dict[TabTickMonitor, int] = defaultdict(int)
    self.current_widget = None
    self.register_event()

def register_event(self):
    self.signal.connect(self.process_tick_event)
    self.event_engine.register(EVENT_TICK, self.signal.emit)
    self.currentChanged.connect(self.on_tab_changed)

def process_tick_event(self, event):
    tick_data = event.data
    tab_widget: TabTickMonitor = self.symbol_tab_map.get(tick_data.vt_symbol, None)
    if not tab_widget:
        new_tab = self.get_last_tab()
        self.symbol_tab_map[tick_data.vt_symbol] = new_tab
        self.tab_symbol_count[new_tab] += 1
        new_tab.update_tick_event(event)
    elif tab_widget == self.current_widget:
        tab_widget.update_tick_event(event)

def get_last_tab(self):
    if self.tab_widget_list:
        last_widget = self.tab_widget_list[-1]
        if self.tab_symbol_count[last_widget] < self.TAB_SYMBOL_COUNT:
            return last_widget
        else:
            return self.get_new_tab()
    else:
        return self.get_new_tab()

def get_new_tab(self):
    new_tab_name = f"{len(self.tab_widget_list)}"
    new_tab = TabTickMonitor(self.main_engine, self.event_engine, new_tab_name)
    self.tab_widget_list.append(new_tab)
    self.addTab(new_tab, new_tab_name)
    self.tab_widget_dict[new_tab_name] = new_tab
    if len(self.tab_widget_list) == 1:
        self.current_widget = new_tab
    return new_tab

def on_tab_changed(self, i):
    self.current_widget = self.tab_widget_list[i]

3、把vnpy->trader->ui->main_window下面初始化docker时的TickMonitor改为PortionTickMonitor即可
def init_dock(self) -> None:
""""""
tick_widget, tick_dock = self.create_dock(
PortionTickMonitor, "行情", QtCore.Qt.RightDockWidgetArea
)

4、其他的额外的import请自行添加

后记:这个只是实现了按顺序和数量分页,如果实现按品种或板块的分页,可以在这个框架的基础上自行修改