在QVBoxLayout中查找选中的QRadioButton

2 投票
3 回答
9365 浏览
提问于 2025-04-15 18:10

我用下面的代码动态创建了一组单选按钮:

self.wPaymantType.qgbSomeSelectionGroup = QtGui.QGroupBox()
vbox = QtGui.QVBoxLayout()

for row in listOfChoices:
    radio = QtGui.QRadioButton(row)
    if bIsFirst:
        radio.setChecked(True)
        bIsFirst = False
    if len(row.name) > nMaxLen:
        nMaxLen = len(row.name)

    vbox.addWidget(radio)

self.wPaymantType.qgbSomeSelectionGroup.setLayout(vbox)

我该怎么遍历所有的单选按钮,找出哪个被选中了呢?

我试过类似这样的代码,但结果并不好:

qvbl = self.qgbSomeSelectionGroup.children()[0]

for i in range(0, qvbl.count()):
    child = qvbl.itemAt(i)
    radio = QtGui.QRadioButton(child.widget())
    if radio != None:
        if radio.isChecked():
            print "radio button num " + str(i) + " is checked"

3 个回答

0

我觉得一个更好的方法来识别哪个按钮被选中,就是使用一个叫做QButtonGroup的东西。它可以把一组按钮放在一起管理。这个东西本身不是一个可视的对象,所以它并不能替代你用来排列单选按钮的布局,但它可以让这些按钮互相排斥,也就是一次只能选一个。同时,它还可以给每个按钮分配一个整数“id”,这样你就可以知道哪个按钮被选中了,而不用一个一个去检查所有的按钮。

如果你决定使用这个方法,你的代码可能会变成这样:

self.wPaymantType.qgbSomeSelectionGroup = QtGui.QGroupBox()
vbox = QtGui.QVBoxLayout()

radioGroup = QtGui.QButtonGroup()
radioGroup.setExclusive(True)

for i,row in enumerate(listOfChoices):
    radio = QtGui.QRadioButton(row)
    radioGroup.addButton(radio, i)
    if bIsFirst:
        radio.setChecked(True)
        bIsFirst = False
    if len(row.name) > nMaxLen:
        nMaxLen = len(row.name)

    vbox.addWidget(radio)

self.wPaymantType.qgbSomeSelectionGroup.setLayout(vbox)

要识别被选中的按钮,你可以使用QButtonGroupcheckedId方法:

buttonId = radioGroup.checkedId()

或者如果你想获取按钮对象本身,可以使用checkedButton方法:

button = radioGroup.checkedButton()
4

你的代码没有做到简单明了,也没有包含所有必要的部分,所以很难帮你解决问题。不过,我还是花了一些时间,做了一个接近你想要的简单示例,并且它看起来能正常工作。下面是这个示例:

from PyQt4 import QtGui

import sys

class MainWindow(QtGui.QMainWindow):
    def __init__(self, parent=None):
      super(MainWindow, self).__init__(parent)  
      self.dowid()
      self.setCentralWidget(self.thewid) 

    def dowid(self):
      self.thewid = QtGui.QGroupBox()
      vbox = QtGui.QVBoxLayout()
      self.radiobuttons = []
      listOfChoices = 'one two three'.split()
      for i, row in enumerate(listOfChoices):
          radio = QtGui.QRadioButton(row)
          if i == 0:
              radio.setChecked(True)
          self.radiobuttons.append(radio)
          vbox.addWidget(radio)
      self.thewid.setLayout(vbox)

    def examine(self):
      for i, radio in enumerate(self.radiobuttons):
        if radio.isChecked():
            print "radio button num " + str(i) + " is checked"
        else:
            print "radio button num " + str(i) + " is NOT checked"

if __name__ == '__main__':
    app = QtGui.QApplication([])
    mainWin = MainWindow()
    mainWin.show()
    rc = app.exec_()
    mainWin.examine()

这个示例似乎能满足你的需求。关键的变化是要保留实际的Python小部件对象,而不是试图从布局的vbox中恢复它们。因为那样做似乎没有达到预期的效果,特别是在判断某个单选按钮是否被选中这一重要细节上,这当然是你问题的核心。

1

我觉得你代码不工作的原因是你在检查复选框是否被选中时的调用。

 radio = QtGui.QRadioButton(child.widget())

我想你是想把子对象转换成 QtGui.QRadioButton,但在这种情况下这样做是行不通的。相反,你应该创建一个新的控件。试试把代码改成这样:

    qvbl = self.qgbSomeSelectionGroup.layout()
    for i in range(0, qvbl.count()):
        widget = qvbl.itemAt(i).widget() 
        if (widget!=0) and (type(widget) is QtGui.QRadioButton):
            if widget.isChecked():
                print "radio button num " + str(i) + " is checked"

上面的代码应该是遍历布局对象的子对象,检查它们的类型,如果是单选按钮并且被选中,就打印“单选按钮...”。

希望这能帮到你,祝好。

撰写回答