from PyQt5.QtCore import QTimer from PyQt5.QtWidgets import QTabWidget, QScrollArea, QWidget, QVBoxLayout, QHBoxLayout, QFrame, QSizePolicy from LSZXPagesLibrary.circular_counter import CircularProgress from LSZXPagesLibrary.consensus import * class CircularRunningTable: def __init__(self, columns_num=5, rows_num=2): super().__init__() self.rows_num = rows_num self.columns_num = columns_num # 人员id索引表 self.person_list = {} # 人员id排名表 self.rank_list = [] # 控件索引表(保存人员ID对应的控件)提供直接从人员id索引至label的功能 self.labels_lookup_table = {} # 切换选择盘 self.scroll_area = self._init_scroll_area_widget() # 绘制切换转盘 self.layout = QVBoxLayout() self.layout.addWidget(self.scroll_area) self.layout.setContentsMargins(10, 10, 10, 10) # 定时更新 self.timer = QTimer() self.timer.timeout.connect(self.update_realtime_screen) self.timer.start(300) # 设置更新间隔为300ms def pause(self): self.timer.stop() def resume(self): self.timer.start(300) def set_person(self, _person_list): self.person_list.clear() self.labels_lookup_table.clear() for _person_mes in _person_list: name = _person_mes[NAME] _id = _person_mes[ID] self.person_list[_id] = _person_mes # 初始化图标对象 label_widget = CircularProgress() label_widget.set_data( percentage=0, second=0, state="未起始", name=name, hr="-- ", bo="-- ", rank=1 ) self.labels_lookup_table[_id] = label_widget def update_realtime_screen(self): # 保存当前滚动位置 scroll_pos = self.scroll_area.verticalScrollBar().value() # 按照表格内容绘制人员框 column_num = self.columns_num row_num = self.rows_num scroll_widget = QWidget() realtime_layout = QVBoxLayout(scroll_widget) scroll_widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) row_layout = QHBoxLayout() count = 0 for _id in self.rank_list.copy(): label_widget = self.labels_lookup_table[_id] row_layout.addWidget(label_widget) if (count + 1) % column_num == 0: realtime_layout.addLayout(row_layout) row_layout = QHBoxLayout() count += 1 # 补充剩余的人员信息,并绘制留白。 if row_layout.count() > 0: for _ in range(column_num - row_layout.count()): # 空白框 empty_box = QLabel() empty_box.setFrameShape(QFrame.Box) empty_box.setLineWidth(0) row_layout.addWidget(empty_box) realtime_layout.addLayout(row_layout) if realtime_layout.count() < row_num: for _ in range(row_num - realtime_layout.count()): # 空白框 empty_box = QLabel() empty_box.setFrameShape(QFrame.Box) empty_box.setLineWidth(0) # 增加到布局中 row_layout = QHBoxLayout() row_layout.addWidget(empty_box) realtime_layout.addLayout(row_layout) self.scroll_area.setWidget(scroll_widget) # 恢复滚动位置 self.scroll_area.verticalScrollBar().setValue(scroll_pos) def update_person(self, _person_list): # 更新排名表 self.rank_list = [ person[ID] for person in sorted(_person_list, key=lambda x: (-x[ROUND], x[TOTAL_TIME], x[ID])) ] # 绘制每一条人员信息 for _person_mes in _person_list: name = _person_mes[NAME] _id = _person_mes[ID] rank = _person_mes[RANK] second = _person_mes[TOTAL_TIME] hr = _person_mes[HR] bo = _person_mes[BO] state = _person_mes[FINISH_MES] percentage = _person_mes[PERCENTAGE] _round = _person_mes[ROUND] # 更新数据 label_widget = self.labels_lookup_table[_id] label_widget.set_data( percentage=percentage, second=second, state=state, name=name, hr=hr, bo=bo, rank=rank, round=_round ) def get_layout(self): return self.layout @staticmethod def _init_scroll_area_widget(): scroll_area = QScrollArea() scroll_area.setWidgetResizable(True) scroll_area.setStyleSheet("border:none") return scroll_area