PyQt5如何实现赛事结果QWidget窗口在双显示器上同时显示
实现双屏同步显示赛事成绩窗口的解决方案
需求梳理
- 开发场景:赛事成绩展示应用,通过串口或TCP端口读取解码器捕获的骑手冲线时间,解码后展示个人用时与总排名,骑手冲线间隔不超过30秒
- 展示要求:成绩通过QMainWindow内嵌的QTableView展示,需要同时在主控端显示器和外接展示屏上完全同步显示,主控端无法直接查看外接屏幕内容
实现思路
原代码仅实例化了一个窗口放在外接屏,要实现双屏同步无需重复编写界面逻辑,只要共用同一份数据源即可保证两边内容完全同步,无需额外做镜像渲染,性能足够满足30秒间隔的刷新需求。
修改后可直接运行的代码
from PyQt5 import QtCore from PyQt5.QtWidgets import QGridLayout,QWidget, QApplication, QPushButton,QTableView,QMainWindow from PyQt5.QtCore import QAbstractTableModel, Qt import sys # 全局共用的成绩数据模型,所有窗口绑定同一个模型保证数据同步刷新 class ResultTableModel(QAbstractTableModel): def __init__(self, parent=None): super().__init__(parent) self.header = ["排名", "骑手姓名", "用时"] self.data_list = [] def rowCount(self, parent): return len(self.data_list) def columnCount(self, parent): return len(self.header) def data(self, index, role): if not index.isValid(): return None if role == Qt.DisplayRole: return self.data_list[index.row()][index.column()] return None def headerData(self, section, orientation, role): if orientation == Qt.Horizontal and role == Qt.DisplayRole: return self.header[section] return None # 新增成绩方法,调用后所有绑定该模型的窗口会自动同步更新 def add_result(self, rank, name, time): self.beginInsertRows(QtCore.QModelIndex(), len(self.data_list), len(self.data_list)) self.data_list.append([rank, name, time]) self.endInsertRows() class ShowResultsWindow(QMainWindow): def __init__(self, display_monitor, model, is_fullscreen=False, parent=None): super().__init__(parent) self.resize(600,600) # 移动窗口到指定显示器 monitor = QApplication.desktop().screenGeometry(display_monitor) self.move(monitor.left(), monitor.top()) if is_fullscreen: self.showFullScreen() # 绑定共用的成绩模型 self.result_model = model self.create_GUI() def create_GUI(self): central_widget=QWidget() layout=QGridLayout(central_widget) self.setCentralWidget(central_widget) # 表格视图绑定共用模型 result_table = QTableView() result_table.setModel(self.result_model) # 可根据需求调整表格样式、列宽等 result_table.horizontalHeader().setStretchLastSection(True) layout.addWidget(result_table, 0, 0, 1, 2) # 测试按钮,模拟新增骑手成绩,实际使用替换为串口/TCP读取逻辑 pb_add = QPushButton('模拟新增冲线成绩') pb_add.clicked.connect(self.add_test_result) layout.addWidget(pb_add,1,0) def add_test_result(self): new_rank = len(self.result_model.data_list) + 1 self.result_model.add_result(new_rank, f"骑手{new_rank}", f"{120 + new_rank * 2.5:.2f}秒") if __name__ == "__main__": app = QApplication(sys.argv) screen_count = len(app.screens()) print('检测到的显示器数量: ', screen_count) # 实例化全局唯一的成绩数据模型 global_result_model = ResultTableModel() # 主控端窗口,放在0号显示器,默认不用全屏方便操作 control_window = ShowResultsWindow(display_monitor=0, model=global_result_model, is_fullscreen=False) control_window.show() # 存在第二块显示器时启动外接展示窗口,放在1号显示器,全屏展示 if screen_count >=2: display_window = ShowResultsWindow(display_monitor=1, model=global_result_model, is_fullscreen=True) display_window.show() sys.exit(app.exec_())
方案优势
- 两边内容完全同步,共用同一份数据源,只要数据更新两边会同时刷新,无显示延迟
- 界面逻辑只需要维护一份,后续修改展示样式、表格规则只需要改一次代码
- 外接屏默认全屏展示,主控端窗口可自由调整大小,适配操作和展示两种场景的需求
内容的提问来源于stack exchange,提问作者RBenet
相关产品推荐
相关产品推荐

