python – PyQt:自定义属性的QDataWidgetMapper映射

python – PyQt:自定义属性的QDataWidgetMapper映射,第1张

概述在PyQt中,我想使用QAbstractItemModel和QDataWidgetMapper将小部件映射到模型数据. 对于QLineEdit,它工作正常,但我想在QButtonGroup(填充了几个QRadioButton)和模型之间进行映射. 因此我将QGroupBox子类化并添加了一个自定义属性selectedOption: class ButtonGroupWidget(QGroupBox 在PyQt中,我想使用qabstractitemmodel和QDataWidgetMapper将小部件映射到模型数据.
对于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映射所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1197371.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-03
下一篇 2022-06-03

发表评论

登录后才能评论

评论列表(0条)

保存