def radioButtonTest(p): btn1 = QRadioButton("男") btn1.setChecked(True) # btn1.setCheckable(False) btn1.toggled.connect(lambda: radioButtonHandler(btn1)) btn1.setParent(p) btn1.setGeometry(10, 20, 80, 30) btn1.setShortcut("Alt+M") # 设置快捷 btn2 = QRadioButton("女") btn2.setParent(p) btn2.setGeometry(10, 60, 80, 30) btn2.setShortcut("Alt+F") # 设置快捷 # 创建分组 zu1 = QButtonGroup(p) # 创建一个按钮分组实例 # 参数2 给按钮设置一个id,不同分组的id可以重复 # 如果id为-1,则将为该按钮分配一个id。自动分配的ID保证为负数,从-2开始。 zu1.addButton(btn1, 1) # 给按钮分组实例添加按钮 zu1.addButton(btn2, 2) # 给按钮分组实例添加按钮 zu1.setExclusive(False) #是否独占 zu1.buttonToggled[int, bool].connect(zuButtonToggledHandler)
class HistogramDisplayControl(QWidget): class Layout(Enum): STACKED = 0 HORIZONTAL = 1 VERTICAL = 2 class DisplayType(Enum): GREY_SCALE = 0 RBG = 1 __LOG: Logger = LogHelper.logger("HistogramDisplayControl") limit_changed = pyqtSignal(LimitChangeEvent) limits_reset = pyqtSignal(LimitResetEvent) layout_changed = pyqtSignal(Layout) def __init__(self, parent=None): super().__init__(parent) self.__menu = None self.__plots = dict() # Use stacked layout as default self.__create_stacked_layout() def __create_horizontal_layout(self): self.__plot_layout = QHBoxLayout() self.__plot_layout.setSpacing(1) self.__plot_layout.setContentsMargins(1, 1, 1, 1) self.setLayout(self.__plot_layout) self.__current_layout = HistogramDisplayControl.Layout.HORIZONTAL def __create_vertical_layout(self): self.__plot_layout = QVBoxLayout() self.__plot_layout.setSpacing(1) self.__plot_layout.setContentsMargins(1, 1, 1, 1) self.setLayout(self.__plot_layout) self.__current_layout = HistogramDisplayControl.Layout.VERTICAL def __create_stacked_layout(self): layout = QVBoxLayout() layout.setSpacing(1) layout.setContentsMargins(1, 1, 1, 1) self.__plot_layout = QStackedLayout() self.__plot_layout.setContentsMargins(1, 1, 1, 1) self.__plot_layout.setSpacing(1) self.__tab_widget = QWidget() self.__tab_widget.setFixedHeight(20) self.__tab_widget.hide() self.__tab_layout = QHBoxLayout() self.__tab_layout.setContentsMargins(1, 1, 1, 1) self.__tab_layout.setAlignment(Qt.AlignLeft) self.__tab_layout.addSpacing(10) self.__red_button = QRadioButton("Red") self.__red_button.setStyleSheet("QRadioButton {color: red}") self.__red_button.toggled.connect(self.__handle_red_toggled) self.__tab_layout.addWidget(self.__red_button) self.__red_plot_index = None self.__green_button = QRadioButton("Green") self.__green_button.setStyleSheet("QRadioButton {color: green}") self.__green_button.toggled.connect(self.__handle_green_toggled) self.__tab_layout.addWidget(self.__green_button) self.__green_plot_index = None self.__blue_button = QRadioButton("Blue") self.__blue_button.setStyleSheet("QRadioButton {color: blue}") self.__blue_button.toggled.connect(self.__handle_blue_toggled) self.__tab_layout.addWidget(self.__blue_button) self.__tab_widget.setLayout(self.__tab_layout) self.__blue_plot_index = None layout.addWidget(self.__tab_widget) layout.addLayout(self.__plot_layout) self.setLayout(layout) self.__current_layout = HistogramDisplayControl.Layout.STACKED def __init_menu(self): self.__menu: QMenu = QMenu(self) stacked_action = QAction("Stacked", self) stacked_action.triggered.connect(self.__handle_stacked_selected) self.__menu.addAction(stacked_action) horizontal_action = QAction("Horizontal", self) horizontal_action.triggered.connect(self.__handle_horizontal_selected) self.__menu.addAction(horizontal_action) vertical_action = QAction("Vertical", self) vertical_action.triggered.connect(self.__handle_vertical_selected) self.__menu.addAction(vertical_action) self.setContextMenuPolicy(Qt.CustomContextMenu) self.customContextMenuRequested.connect( self.__handle_custom_context_menu) def __handle_custom_context_menu(self, position: QPoint): HistogramDisplayControl.__LOG.debug( "__handle_custom_context_menu called position: {0}", position) self.__menu.popup(self.mapToGlobal(position)) def __handle_stacked_selected(self): self.__swap_layout(HistogramDisplayControl.Layout.STACKED) def __handle_horizontal_selected(self): self.__swap_layout(HistogramDisplayControl.Layout.HORIZONTAL) def __handle_vertical_selected(self): self.__swap_layout(HistogramDisplayControl.Layout.VERTICAL) def __swap_layout(self, new_layout: Layout): # The plot's will have had their parent set to the layout so first # we undo that so they won't get deleted when the layout does. for band, plot in self.__plots.items(): plot.setParent(None) if self.__current_layout == HistogramDisplayControl.Layout.STACKED: self.__red_button.setParent(None) self.__green_button.setParent(None) self.__blue_button.setParent(None) self.__tab_widget.setParent(None) # Per Qt docs we need to delete the current layout before we can set a new one # And it turns out we can't delete the layout until we reassign it to another widget # who becomes it's parent, then we delete the parent. tmp = QWidget() tmp.setLayout(self.layout()) del tmp if new_layout == HistogramDisplayControl.Layout.STACKED: self.__create_stacked_layout() if new_layout == HistogramDisplayControl.Layout.HORIZONTAL: self.__create_horizontal_layout() if new_layout == HistogramDisplayControl.Layout.VERTICAL: self.__create_vertical_layout() for band, plot in self.__plots.items(): self.__plot_layout.addWidget(plot) self.__wire_band(band, plot) if new_layout != HistogramDisplayControl.Layout.STACKED: # stacked layout hides plots not displayed so set them back plot.show() self.layout_changed.emit(new_layout) def __wire_band(self, band: Band, plot: AdjustableHistogramControl): if self.__current_layout == HistogramDisplayControl.Layout.STACKED: set_checked: bool = False if self.__plot_layout.count() == 1: set_checked = True self.__tab_widget.show() if band == Band.RED: self.__red_plot_index = self.__plot_layout.indexOf(plot) self.__red_button.setChecked(set_checked) if band == Band.GREEN: self.__green_plot_index = self.__plot_layout.indexOf(plot) self.__green_button.setChecked(set_checked) if band == Band.BLUE: self.__blue_plot_index = self.__plot_layout.indexOf(plot) self.__blue_button.setChecked(set_checked) @pyqtSlot(bool) def __handle_red_toggled(self, checked: bool): if checked: HistogramDisplayControl.__LOG.debug("red toggle checked") self.__plot_layout.setCurrentIndex(self.__red_plot_index) @pyqtSlot(bool) def __handle_green_toggled(self, checked: bool): if checked: HistogramDisplayControl.__LOG.debug("green toggle checked") self.__plot_layout.setCurrentIndex(self.__green_plot_index) @pyqtSlot(bool) def __handle_blue_toggled(self, checked: bool): if checked: HistogramDisplayControl.__LOG.debug("blue toggle checked") self.__plot_layout.setCurrentIndex(self.__blue_plot_index) def add_plot(self, raw_data: HistogramPlotData, adjusted_data: HistogramPlotData, band: Band): """Expects either one band with band of Band.GREY or three bands one each of Band.RED, Band.GREEN, Band.BLUE. If these conditions are not met the code will attempt to be accommodating and won't throw and error but you might get strange results.""" plots = AdjustableHistogramControl(band) plots.set_raw_data(raw_data) plots.set_adjusted_data(adjusted_data) plots.limit_changed.connect(self.limit_changed) plots.limits_reset.connect(self.limits_reset) self.__plots[band] = plots self.__plot_layout.addWidget(plots) if self.__plot_layout.count() == 2: self.__init_menu() if band == Band.RED or band == Band.GREEN or band == Band.BLUE: self.__wire_band(band, plots) def set_adjusted_data(self, data: HistogramPlotData, band: Band): """Update the adjusted data for a Band that has already been added using add_plot""" plots: AdjustableHistogramControl = self.__plots[band] if plots is not None: plots.set_adjusted_data(data) def update_limits(self, data: HistogramPlotData, band: Band): plots: AdjustableHistogramControl = self.__plots[band] if plots is not None: plots.update_limits(data)