对于QlineEdit,它工作正常,但我想在QbuttonGroup(填充了几个qradiobutton)和模型之间进行映射.
因此我将qgroupbox子类化并添加了一个自定义属性selectedOption:
@H_301_10@
@H_301_10@
class buttonGroupWidget(qgroupbox): def __init__(self,parent=None): super(buttonGroupWidget,self).__init__(parent) self._selectedOption = -1 self.buttonGroup = QbuttonGroup() self.layoutGroupBox = QVBoxLayout(self) def addRadiobutton(self,optionText,optionID): print(optionText) radiobutton = qradiobutton(optionText) radiobutton.clicked.connect(self.updateOptionSelected) self.layoutGroupBox.addWidget(radiobutton) self.buttonGroup.addbutton(radiobutton,optionID) def updateOptionSelected(self): print(self.buttonGroup.checkedID()) # for test purpose self.selectedOption = self.buttonGroup.checkedID() print(self._selectedOption) # for test purpose def getSelectedOption(self): print("get selectedOption is called") return self._selectedOption def setSelectedOption(self,selectedOption): print("set selectedOption is called") self._selectedOption = selectedOption self.buttonGroup.button(selectedOption).setChecked(True) selectedOption = pyqtProperty(int,getSelectedOption,setSelectedOption)
在主窗口小部件中,我创建了一个buttonGroupWidget的实例:@H_301_10@
@H_301_10@
class MainWidget(QWidget): def __init__(self,parent=None): super(MainWindow,self).__init__(parent) ... # insert a button group Widget self.buttonGroupWidget1 = buttonGroupWidget(self) self.buttonGroupWidget1.setTitle("Select option") self.buttonGroupWidget1.addRadiobutton("Option 1",1) self.buttonGroupWidget1.addRadiobutton("Option 2",2) self.buttonGroupWidget1.addRadiobutton("Option 3",3) ... # Create the data model and map the model to the Widgets. self._model = DataModel() ... self._dataMapper = QDataWidgetMapper() self._dataMapper.setModel(self._model) ... # mapPing to custom property self._dataMapper.addMapPing(self.buttonGroupWidget1,1,"selectedOption")
完整代码(工作最小示例)如下.
我的问题如下:
如果模型已更改(例如,您在完整代码中看到的lineEdit),则调用setSelectedOption方法并将self._selectedOption设置为当前值并更新radiobuttons.
但如果我点击另一个radiobutton,我不知道如何更新模型.@H_301_10@
是否有像QWidget的数据更改事件,这将更新模型?@H_301_10@
有没有更好的方法将qabstractitemmodel映射到具有多个radiobuttons的GroupBox?@H_301_10@
完整代码(最小的例子,用Python 3.4和PyQt 5.4测试):@H_301_10@
@H_301_10@
import sysfrom PyQt5.QtWidgets import QWidget,QlineEdit,qradiobutton,QbuttonGroup,QApplication,QVBoxLayout,qgroupbox,QTreeVIEw,QDataWidgetMapperfrom PyQt5.QtCore import qabstractitemmodel,QModelindex,Qt,pyqtProperty"""Base class to provIDe some nodes fro a treeAt the moment each node contains two members: name and option"""class Node(object): def __init__(self,name,parent=None): self._name = name self._children = [] self._parent = parent self._option = 2 if parent is not None: parent.addChild(self) def name(self): return self._name def setname(self,name): self._name = name def option(self): return self._option def setoption(self,option): self._option = option def addChild(self,child): self._children.append(child) def insertChild(self,position,child): if position < 0 or position > len(self._children): return False self._children.insert(position,child) child._parent = self return True def removeChild(self,position): if position < 0 or position > len(self._children): return False child = self._children.pop(position) child._parent = None return True def child(self,row): return self._children[row] def childCount(self): return len(self._children) def parent(self): return self._parent def row(self): if self._parent is not None: return self._parent._children.index(self) def __repr__(self): return self.log()class buttonGroupWidget(qgroupbox): def __init__(self,setSelectedOption)class DataModel(qabstractitemmodel): def __init__(self,parent=None): super(DataModel,self).__init__(parent) self._rootNode = Node("Root Node") childNode1 = Node("Child 1",self._rootNode) childNode2 = Node("Child 2",self._rootNode) childNode3 = Node("Child 3",self._rootNode) def __eq__(self,other): return self.__dict__ == other.__dict__ def isNull(self): nullObject = DataModel() if self.__eq__(nullObject): return True else: return False def rowCount(self,parent): if not parent.isValID(): parentNode = self._rootNode else: parentNode = parent.internalPointer() return parentNode.childCount() def columnCount(self,parent): return 1 def data(self,index,role): if not index.isValID(): return None node = index.internalPointer() if role == Qt.displayRole or role == Qt.EditRole: if index.column() == 0: return node.name() if index.column() == 1: return node.option() def setData(self,value,role=Qt.EditRole): if index.isValID(): node = index.internalPointer() if role == Qt.EditRole: if index.column() == 0: node.setname(value) if index.column() == 1: node.setoption(value) self.dataChanged.emit(index,index) return True return False def headerData(self,section,orIEntation,role): if role == Qt.displayRole: if section == 0: return "Select Child" def flags(self,index): return Qt.ItemIsEnabled | Qt.ItemIsSelectable | Qt.ItemIsEditable def parent(self,index): node = index.internalPointer() parentNode = node.parent() if parentNode == self._rootNode: return QModelindex() return self.createIndex(parentNode.row(),parentNode) def index(self,row,column,parent): if not parent.isValID(): parentNode = self._rootNode else: parentNode = parent.internalPointer() childItem = parentNode.child(row) if childItem: return self.createIndex(row,childItem) else: return QModelindex() def getNode(self,index): if index.isValID(): node = index.internalPointer() if node: return node return self._rootNodeclass MainWidget(QWidget): def __init__(self,self).__init__(parent) # define tree vIEw self.treeVIEw = QTreeVIEw(self) # insert line edit self.lineEdit1 = QlineEdit(self) self.lineEdit2 = QlineEdit(self) # insert a button group Widget self.buttonGroupWidget1 = buttonGroupWidget(self) self.buttonGroupWidget1.setTitle("Select option") self.buttonGroupWidget1.addRadiobutton("Option 1",3) layoutMain = QVBoxLayout(self) layoutMain.addWidget(self.treeVIEw) layoutMain.addWidget(self.lineEdit1) layoutMain.addWidget(self.lineEdit2) layoutMain.addWidget(self.buttonGroupWidget1) # Create the data model and map the model to the Widgets. self._model = DataModel() self.treeVIEw.setModel(self._model) self._dataMapper = QDataWidgetMapper() self._dataMapper.setModel(self._model) # the mapPing works fine for line edits and combo Boxes self._dataMapper.addMapPing(self.lineEdit1,0) self._dataMapper.addMapPing(self.lineEdit2,1) # mapPing to custom property self._dataMapper.addMapPing(self.buttonGroupWidget1,"selectedOption") self.treeVIEw.selectionModel().currentChanged.connect(self.setSelection) def setSelection(self,current): parent = current.parent() self._dataMapper.setRootIndex(parent) self._dataMapper.setCurrentModelindex(current) def main(): app = QApplication(sys.argv) form = MainWidget() form.show() app.exec_()main()解决方法 当单选按钮选项更改时,模型将更新,但仅在按下return或enter时才会更新.
@H_301_10@
原因是数据映射器使用item-delegate来通知模型的更改,而item-delegate会在映射的每个Widget上安装事件过滤器.但事件过滤器仅监视按键和焦点更改,而不是鼠标单击,并且在任何情况下,它都无法接收来自子窗口小部件的事件.@H_301_10@
解决此限制的一种温和的Hackish方法是在单击单选按钮时模拟适当的按键:@H_301_10@
@H_301_10@
def updateOptionSelected(self): self.selectedOption = self.buttonGroup.checkedID() QApplication.postEvent( self,QKeyEvent(QEvent.KeyPress,Qt.Key_Enter,Qt.NoModifIEr))总结
以上是内存溢出为你收集整理的python – PyQt:自定义属性的QDataWidgetMapper映射全部内容,希望文章能够帮你解决python – PyQt:自定义属性的QDataWidgetMapper映射所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)