[英]How to get the state of Qcheckbox that is present inside the QGroupbox in PyQt
[英]PyQt5 QGroupBox with QCheckBox - dismiss auto disable
我想使用一個可檢查的 QGroupBox,但是當 QGroupBox 復選框未選中時,我不會禁用 QGroupBox 的內容小部件。
checked : bool 該屬性保存是否選中組框
如果組框是可勾選的,它會顯示一個復選框。 如果選中該復選框,則啟用組框的子項; 否則,孩子將被禁用並且用戶無法訪問。
默認情況下,還會選中可檢查的組框。
我想在 QGroupBox 標題欄中有一個復選框,但我不希望應用上述功能。
復選框邏輯將是全選,全選,因此當復選框未選中時,用戶可以修改內部 QGroupBox 復選框元素。
我想保留如下所示的界面 ui:
也許我必須使用帶有 QPaintEvent 或 QSS 樣式表的 QFrame,但我不是這方面的專家。
編輯:我也想三態為QGroupBox復選框,如果可能的。
編輯2:我試試這個代碼:
self.main_self.ui_visible_player_list_fields_window.groupBox.changeEvent(QtCore.QEvent.EnabledChange).connect(lambda event:event.ignore())
但它有錯誤。
self.main_self.ui_visible_player_list_fields_window.groupBox.changeEvent(QtCore.QEvent.EnabledChange).connect(lambda event:event.ignore())
TypeError: changeEvent(self, QEvent): argument 1 has unexpected type 'Type'
編輯:我認為以下代碼將解決問題:
class Custom_QGroupBox(QtWidgets.QGroupBox):
def __init__(self, parent=None):
super(Custom_QGroupBox, self).__init__(parent)
def changeEvent(self, event):
if event.type() == QtCore.QEvent.EnabledChange:
self.blockSignals(True)
self.setEnabled(True)
event.ignore()
self.blockSignals(False)
else:
return super(Custom_QGroupBox, self).changeEvent(event)
但它沒有:(
我添加這個代碼:
self.main_self.ui_visible_player_list_fields_window.groupBox.blockSignals(True)
self.main_self.ui_visible_player_list_fields_window.groupBox.setEnabled(True)
for child_widget in self.main_self.ui_visible_player_list_fields_window.groupBox.children():
try:
child_widget.setEnabled(True)
except:
pass
self.main_self.ui_visible_player_list_fields_window.groupBox.blockSignals(False)
在切換方法中,是child_widget_checkbox.stateChanged.connect
方法,它可以工作。
唯一要完全回答這個問題的是 QGroupBox 的三態。
UI 元素有一些已知的約定,用戶已經習慣了它們並期望對眾所周知的元素類型執行“操作”會導致同樣已知的結果。
雖然分組框更像是一種邊緣情況,但 Qt 的默認行為遵循約定:切換復選框會導致切換其內容的啟用狀態。
由於 UI 元素應始終嘗試遵循約定並使用戶操作的可能結果盡可能可預測,因此更好的解決方案是添加一組“頂級”按鈕,將所有框設置為選中或未選中(“全部檢查”和“不檢查”)。
首先, changeEvent
不是信號,所以你不能嘗試“連接”它(總是在 Qt 文檔中尋找函數類型,如果它是一個信號,除了它的定義之外,它還會有一個[signal]
符號)。
它是一個事件處理程序,它需要一個事件實例作為參數,而不是一個類型。
然后,切換組框的復選框會更改其子項的狀態,而不是組框的狀態,因此在切換時您永遠不會收到EnabledChange
事件。
如果您考慮一下,這很明顯:如果在切換復選框時整個組框被禁用,您將永遠無法再次單擊以啟用它,因為默認情況下禁用的小部件的輸入事件將被忽略,並且標題和復選框都將也顯示為禁用。
有多種可能的解決方案,包括子類化 QFrame 並繪制復選框和標題,但使其符合當前樣式將非常(並且不必要地)困難。
最佳選擇通常是對默認行為進行較少更改的選擇。
在這種情況下,我的建議是做兩件事:
toggled
信號並覆蓋默認行為的作用(恢復啟用狀態,除非為該小部件明確設置);paintEvent
並更改用於樣式和畫家的QStyleOptionGroupBox state
; 由於狀態是為組框內部定義的,我們需要覆蓋它的值: initStyleOption()
在復選框(理論上)被選中時添加選項的狀態標志State_On
,或者在未選中時添加State_Off
(因此,子部件是否是否啟用),但我們必須根據復選框狀態設置選項狀態。 為了做到這一點,我們必須選中所有復選框並驗證是否所有復選框都被選中,其中任何一個被選中,或者沒有。
from PyQt5 import QtCore, QtWidgets
class Custom_QGroupBox(QtWidgets.QGroupBox):
checkAllIfAny = True
def __init__(self, *args, **kwargs):
super(Custom_QGroupBox, self).__init__(*args, **kwargs)
self.setCheckable(True)
self.checkBoxes = []
self.toggled.connect(self.toggleCheckBoxes)
def addCheckBox(self, cb):
self.checkBoxes.append(cb)
cb.toggled.connect(self.update)
cb.destroyed.connect(lambda: self.removeCheckBox(cb))
def removeCheckBox(self, cb):
try:
self.checkBoxes.remove(cb)
cb.toggled.disconnect(self.update)
except:
pass
def allStates(self):
return [cb.isChecked() for cb in self.checkBoxes]
def toggleCheckBoxes(self):
if self.checkAllIfAny:
state = not all(self.allStates())
else:
state = not any(self.allStates())
for widget in self.children():
if not widget.isWidgetType():
continue
if not widget.testAttribute(QtCore.Qt.WA_ForceDisabled):
# restore the enabled state in order to override the default
# behavior of setChecked(False); previous explicit calls for
# setEnabled(False) on the target widget will be ignored
widget.setEnabled(True)
if widget in self.checkBoxes:
widget.setChecked(state)
def paintEvent(self, event):
opt = QtWidgets.QStyleOptionGroupBox()
self.initStyleOption(opt)
states = self.allStates()
if all(states):
# force the "checked" state
opt.state |= QtWidgets.QStyle.State_On
opt.state &= ~QtWidgets.QStyle.State_Off
else:
# force the "not checked" state
opt.state &= ~QtWidgets.QStyle.State_On
if any(states):
# force the "not unchecked" state and set the tristate mode
opt.state &= ~QtWidgets.QStyle.State_Off
opt.state |= QtWidgets.QStyle.State_NoChange
else:
# force the "unchecked" state
opt.state |= QtWidgets.QStyle.State_Off
painter = QtWidgets.QStylePainter(self)
painter.drawComplexControl(QtWidgets.QStyle.CC_GroupBox, opt)
app = QtWidgets.QApplication([])
groupBox = Custom_QGroupBox('Group options')
layout = QtWidgets.QGridLayout(groupBox)
o = 0
for c in range(2):
for r in range(4):
o += 1
cb = QtWidgets.QCheckBox('Option {}'.format(o))
groupBox.addCheckBox(cb)
layout.addWidget(cb, r, c)
groupBox.show()
app.exec_()
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.