[英]PyQt5 Radio Button Tab Stop Dysfunction
我有一些程序使用帶有單選按鈕組的對話框。 最初使用 setChecked(True) 指定按鈕時的預期行為是為其組分配制表位。 這就是它在 Windows API 中的工作原理。 但似乎制表位總是轉到組中的第一個按鈕(即使它沒有被選中),直到您通過鼠標單擊或箭頭鍵手動重新選擇預期的按鈕。 您可以在指定按鈕上使用 setFocus(True),但這只能用於一組按鈕。 Windows 10 和 Ubuntu 使用 PyQt5 版本 5.12 和 5.15 會發生這種情況。 我嘗試了 Qt 文檔中列出的各種單選按鈕焦點相關功能,但均未成功。
這個問題是 2 年前提出的(53645767/radio-button-tab-sequencing),沒有明確解釋如何設置制表位或它不是一個選項的答案。
我從 Web 教程改編了這個腳本。 對於這兩個組,我使用 setChecked(True) 初始化組中的第二個按鈕,並在第一組中的按鈕上使用 setFocus(True)。 使用“Tab”循環會按預期在第一組的第二個按鈕處顯示制表位,但它會保留在第二組的第一個(未選中)按鈕上,直到您單擊第二個按鈕或使用箭頭鍵重新選擇它. 我在這里遺漏了什么還是故意的“功能”?
def init_ui(self):
self.label = QLabel('What is your favorite color?')
self.rbtn1 = QRadioButton('blue')
self.rbtn2 = QRadioButton('red')
self.label2 = QLabel("")
self.label3 = QLabel('What is your favorite element?')
self.rbtn3 = QRadioButton('bolognium')
self.rbtn4 = QRadioButton('unobtainium')
self.label4 = QLabel("")
self.btngroup1 = QButtonGroup()
self.btngroup2 = QButtonGroup()
self.btngroup1.addButton(self.rbtn1)
self.btngroup1.addButton(self.rbtn2)
self.btngroup2.addButton(self.rbtn3)
self.btngroup2.addButton(self.rbtn4)
self.rbtn1.toggled.connect(self.onClickedColor)
self.rbtn2.toggled.connect(self.onClickedColor)
self.rbtn3.toggled.connect(self.onClickedElement)
self.rbtn4.toggled.connect(self.onClickedElement)
layout = QVBoxLayout()
layout.addWidget(self.label)
layout.addWidget(self.rbtn1)
layout.addWidget(self.rbtn2)
layout.addWidget(self.label2)
layout.addWidget(self.label3)
layout.addWidget(self.rbtn3)
layout.addWidget(self.rbtn4)
layout.addWidget(self.label4)
self.setGeometry(200, 200, 300, 300)
self.setLayout(layout)
self.rbtn2.setChecked(True)
self.rbtn2.setFocus(True)
self.rbtn4.setChecked(True)
self.show()
def onClickedColor(self):
radioBtn = self.sender()
if radioBtn.isChecked():
self.label2.setText("Your favorite color is " + radioBtn.text())
def onClickedElement(self):
radioBtn = self.sender()
if radioBtn.isChecked():
self.label4.setText("Your favorite element is " + radioBtn.text())
這似乎是一個錯誤(順便說一句,你鏈接的問題只顯示了類似的行為,但考慮到它是關於 HTML 我相信它是不相關的)。
不幸的是,“自動對焦”管理非常復雜,並且基於多個方面:創建順序、父級、焦點策略、小部件的 position 和系統行為。
一個可能的(和“hacky”)解決方案可能是覆蓋focusNextPrevChild()
。
訣竅是獲取當前焦點小部件並循環通過其自己的nextFocusInChain
和previousInFocusChain
(通過檢查其焦點策略並遞歸直到找到有效策略),然后確保小部件包含在按鈕組中。
請注意,以下是一個非常原始的實現,您可能需要進一步測試才能使其正常工作並確保不會發生錯誤/遞歸問題。
def focusNextPrevChild(self, isNext):
if isNext:
func = 'nextInFocusChain'
reason = Qt.TabFocusReason
else:
func = 'previousInFocusChain'
reason = Qt.BacktabFocusReason
current = self.focusWidget()
other = getattr(current, func)()
while True:
while not other.focusPolicy():
other = getattr(other, func)()
if isinstance(other, QRadioButton):
for group in self.btngroup1, self.btngroup2:
if other in group.buttons():
checked = group.checkedButton()
if checked == current and not isNext:
continue
if checked:
checked.setFocus(reason)
else:
other.setFocus(reason)
return True
break
return super().focusNextPrevChild(isNext)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.