簡體   English   中英

PyQt5 單選按鈕制表符停止功能障礙

[英]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()

訣竅是獲取當前焦點小部件並循環通過其自己的nextFocusInChainpreviousInFocusChain (通過檢查其焦點策略並遞歸直到找到有效策略),然后確保小部件包含在按鈕組中。

請注意,以下是一個非常原始的實現,您可能需要進一步測試才能使其正常工作並確保不會發生錯誤/遞歸問題。

    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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM