QDataWidgetMapper;将 TableWidget 映射到模型

2024-05-18

我没有找到任何文档显示 QDataWidgetMapper 实际上适用于哪些小部件,也没有找到任何使用 QTableWidget 进行映射的实现。

它绝对适用于 QLineEdit 和 QComboBoxes,它们是输入小部件,但是是否可以映射到 QTableWidget?

目标是在添加到 QUndostack 时使用 QUndoStack 撤消/重做每个小部件中的文本更改。我希望能够撤消/重做 QTableWidget 以及 QLineEdits 和 QComboBoxes 中的项目的文本更改。

from PyQt5 import QtCore, QtGui, QtWidgets
import sys

class CommandTextEdit(QtWidgets.QUndoCommand):
    def __init__(self, window, index, oldText, newText, description):
        super(CommandTextEdit,self).__init__()
        self.index = index
        self.window = window
        self.oldText = oldText
        self.newText = newText

    def redo(self):
        self.index.model().itemDataChanged.disconnect(self.window.itemDataChangedSlot)
        self.index.model().setData(self.index, self.newText, QtCore.Qt.EditRole)
        self.index.model().itemDataChanged.connect(self.window.itemDataChangedSlot)

    def undo(self):
        self.index.model().itemDataChanged.disconnect(self.window.itemDataChangedSlot)
        self.index.model().setData(self.index, self.oldText, QtCore.Qt.EditRole)
        self.index.model().itemDataChanged.connect(self.window.itemDataChangedSlot)

class Model(QtCore.QAbstractListModel):
    itemDataChanged = QtCore.pyqtSignal(object,object, object, object)
    def __init__(self, text = [], parent = None):
        super(Model,self).__init__(parent)
        self._text = text

    def rowCount(self,parent=QtCore.QModelIndex()):
        return len(self._text)

    def data(self,index,role):
        row = index.row()
        if role == QtCore.Qt.EditRole:
            return self._text[row]

        if role == QtCore.Qt.DisplayRole:
            value = self._text[row]
            return self._text[row]

    def model(self):
        return self

    def flags(self, index):
        return QtCore.Qt.ItemIsEditable |QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable

    def setData(self, index, value, role = QtCore.Qt.UserRole + 1):
        if index.isValid():
           if role == QtCore.Qt.EditRole:
                oldValue = self.data(index,role)
                self._text[index.row()] = value
                self.dataChanged.emit(index, index)
                if oldValue != value:
                    self.itemDataChanged.emit(index, oldValue, value, role)
                return True
        return False

class Window(QtWidgets.QMainWindow):
    def __init__(self, parent = None):
        super(Window,self).__init__(parent)
        self.setCentralWidget(QtWidgets.QWidget(self))
        self.setWindowTitle('Widget Mapping GUI')
        mainlayout = QtWidgets.QVBoxLayout()
        #Information for widgets
        items = ["","H","N","M"]
        #LineEdit1
        self.labelLineEdit1 = QtWidgets.QLabel()
        self.labelLineEdit1.setText('LineEdit1')
        self.LineEdit1 = QtWidgets.QLineEdit()
        firstBox = QtWidgets.QHBoxLayout()
        firstBox.addWidget(self.labelLineEdit1)
        firstBox.addWidget(self.LineEdit1)
        #LineEdit2
        self.labelLineEdit2 = QtWidgets.QLabel()
        self.labelLineEdit2.setText('LineEdit2')
        self.LineEdit2 = QtWidgets.QLineEdit()
        secondBox = QtWidgets.QHBoxLayout()
        secondBox.addWidget(self.labelLineEdit2)
        secondBox.addWidget(self.LineEdit2)
        #ComboBox1
        self.labelComboBox1 = QtWidgets.QLabel()
        self.labelComboBox1.setText('ComboBox1')
        self.ComboBox1 = QtWidgets.QComboBox()
        self.ComboBox1.addItems(items)

        thirdBox = QtWidgets.QHBoxLayout()
        thirdBox.addWidget(self.labelComboBox1)
        thirdBox.addWidget(self.ComboBox1)
        #ComboBox2
        self.labelComboBox2 = QtWidgets.QLabel()
        self.labelComboBox2.setText('ComboBox2')
        self.ComboBox2 = QtWidgets.QComboBox()
        self.ComboBox2.addItems(items)

        fourthBox = QtWidgets.QHBoxLayout()
        fourthBox.addWidget(self.labelComboBox2)
        fourthBox.addWidget(self.ComboBox2)
        #TableWidget
        self.TableWidget = QtWidgets.QTableWidget(5,1)
        #Set header labels
        self.TableWidget.setHorizontalHeaderLabels(["Dimensions"])
        self.TableWidget.setVerticalHeaderLabels(["A","B","C","D","E"])
        self.TableWidget.setItem(0,1,QtWidgets.QTableWidgetItem('1'))

        fifthBox = QtWidgets.QVBoxLayout()
        fifthBox.addWidget(self.TableWidget)
        #Add Layouts
        mainlayout.addLayout(firstBox)
        mainlayout.addLayout(secondBox)
        mainlayout.addLayout(thirdBox)
        mainlayout.addLayout(fourthBox)
        mainlayout.addLayout(fifthBox)
        self.centralWidget().setLayout(mainlayout)
        #Model
        self.mapper = None
        self.model = Model(['','','','',''])
        self.setModel(self.model)
        #QUndoStack
        self.undoStack = QtWidgets.QUndoStack()
        self.stackView = QtWidgets.QUndoView(self.undoStack)
        self.stackView.setWindowTitle('StackView')
        self.stackView.show()
        #Run init methods
        self.createActions()
        self.makeConnections()
        self.listViewMethod()

    def createActions(self):
        self.UndoAct = QtWidgets.QAction("Undo", self)
        self.UndoAct.setShortcut(QtGui.QKeySequence.Undo)
        self.UndoAct.triggered.connect(self.undoStack.undo)
        self.RedoAct = QtWidgets.QAction("Redo", self)
        self.RedoAct.setShortcut(QtGui.QKeySequence.Redo)
        self.RedoAct.triggered.connect(self.undoStack.redo)
        self.toolbar = self.addToolBar('Exit')
        self.toolbar.addAction(self.UndoAct)
        self.toolbar.addAction(self.RedoAct)

    def listViewMethod(self):
        self.listView = QtWidgets.QListView()
        self.listView.setModel(self.model)
        self.listView.setWindowTitle('ListView')
        self.listView.show()

    def makeConnections(self):
        self.model.itemDataChanged.connect(self.itemDataChangedSlot)

    def setModel(self, model):
        self.mapper = QtWidgets.QDataWidgetMapper(self)
        self.mapper.setOrientation(QtCore.Qt.Vertical)
        self.mapper.setModel(self.model)
        self.mapper.addMapping(self.LineEdit1, 0)
        self.mapper.addMapping(self.LineEdit2, 1)
        self.mapper.addMapping(self.ComboBox1, 2)
        self.mapper.addMapping(self.ComboBox2, 3)
        self.mapper.addMapping(self.TableWidget,4)
        self.mapper.toFirst()

    def itemDataChangedSlot(self, index, oldValue, value, role):
        if role == QtCore.Qt.EditRole:
            command = CommandTextEdit(self, index, oldValue, value, "Text changed from '{0}' to '{1}'".format(oldValue, value))
            self.undoStack.push(command)

def main():
    app = QtWidgets.QApplication(sys.argv)
    window = Window()
    window.show()
    sys.exit(app.exec_())



if __name__ == '__main__':
    main()


映射 a 的项目QTableWidget,我用了setCellWidget方法使用自定义 QLineEdit 类将每个单元格映射到模型。

更新的代码:

from PyQt5 import QtCore, QtGui, QtWidgets
import sys

#implemented stylesheets for QLineEdit to imitate a QTableWidgetItem 
class CustomLineEdit(QtWidgets.QLineEdit):
    def __init__(self):
        super(CustomLineEdit,self).__init__()
        self.setReadOnly(True)
        self.setFrame(False)
        self.setStyleSheet("QLineEdit { border: none; } \n" \
                           "QLineEdit::focus {background-color: #3daee9;} \n"\
                           "QLineEdit::focus::pressed {background-color: none;} \n"\
                           "QLineEdit::hover {background-color: #3daee9;}"
                            )
    def mouseDoubleClickEvent(self,event):
        self.setReadOnly(False)
        self.setStyleSheet("QLineEdit { border: none; \nbackground-color: none;} \n" \
                            )

    def focusOutEvent(self,event):
        self.setReadOnly(True)
        self.setStyleSheet("QLineEdit { border: none; } \n" \
                           "QLineEdit::focus {background-color: #3daee9;} \n"\
                           "QLineEdit::focus::pressed {background-color: none;} \n"\
                           "QLineEdit::hover {background-color: #3daee9;}"
                            )

class CommandTextEdit(QtWidgets.QUndoCommand):
    def __init__(self, window, index, oldText, newText, description):
        super(CommandTextEdit,self).__init__()
        self.index = index
        self.window = window
        self.oldText = oldText
        self.newText = newText

    def redo(self):
        self.index.model().itemDataChanged.disconnect(self.window.itemDataChangedSlot)
        self.index.model().setData(self.index, self.newText, QtCore.Qt.EditRole)
        self.index.model().itemDataChanged.connect(self.window.itemDataChangedSlot)

    def undo(self):
        self.index.model().itemDataChanged.disconnect(self.window.itemDataChangedSlot)
        self.index.model().setData(self.index, self.oldText, QtCore.Qt.EditRole)
        self.index.model().itemDataChanged.connect(self.window.itemDataChangedSlot)

class Model(QtCore.QAbstractListModel):
    itemDataChanged = QtCore.pyqtSignal(object,object, object, object)
    def __init__(self, text = [], parent = None):
        super(Model,self).__init__(parent)
        self._text = text

    def rowCount(self,parent=QtCore.QModelIndex()):
        return len(self._text)

    def data(self,index,role):
        row = index.row()
        if role == QtCore.Qt.EditRole:
            return self._text[row]

        if role == QtCore.Qt.DisplayRole:
            value = self._text[row]
            return self._text[row]

    def model(self):
        return self

    def flags(self, index):
        return QtCore.Qt.ItemIsEditable |QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable

    def setData(self, index, value, role = QtCore.Qt.UserRole + 1):
        if index.isValid():
           if role == QtCore.Qt.EditRole:
                oldValue = self.data(index,role)
                self._text[index.row()] = value
                self.dataChanged.emit(index, index)
                if oldValue != value:
                    self.itemDataChanged.emit(index, oldValue, value, role)
                return True
        return False

class Window(QtWidgets.QMainWindow):
    def __init__(self, parent = None):
        super(Window,self).__init__(parent)
        self.setCentralWidget(QtWidgets.QWidget(self))
        self.setWindowTitle('Widget Mapping GUI')
        mainlayout = QtWidgets.QVBoxLayout()
        #Information for widgets
        items = ["","H","N","M"]
        #LineEdit1
        self.labelLineEdit1 = QtWidgets.QLabel()
        self.labelLineEdit1.setText('LineEdit1')
        self.LineEdit1 = QtWidgets.QLineEdit()
        firstBox = QtWidgets.QHBoxLayout()
        firstBox.addWidget(self.labelLineEdit1)
        firstBox.addWidget(self.LineEdit1)
        #LineEdit2
        self.labelLineEdit2 = QtWidgets.QLabel()
        self.labelLineEdit2.setText('LineEdit2')
        self.LineEdit2 = QtWidgets.QLineEdit()
        secondBox = QtWidgets.QHBoxLayout()
        secondBox.addWidget(self.labelLineEdit2)
        secondBox.addWidget(self.LineEdit2)
        #ComboBox1
        self.labelComboBox1 = QtWidgets.QLabel()
        self.labelComboBox1.setText('ComboBox1')
        self.ComboBox1 = QtWidgets.QComboBox()
        self.ComboBox1.addItems(items)

        thirdBox = QtWidgets.QHBoxLayout()
        thirdBox.addWidget(self.labelComboBox1)
        thirdBox.addWidget(self.ComboBox1)
        #ComboBox2
        self.labelComboBox2 = QtWidgets.QLabel()
        self.labelComboBox2.setText('ComboBox2')
        self.ComboBox2 = QtWidgets.QComboBox()
        self.ComboBox2.addItems(items)

        fourthBox = QtWidgets.QHBoxLayout()
        fourthBox.addWidget(self.labelComboBox2)
        fourthBox.addWidget(self.ComboBox2)
        #TableWidget
        self.TableWidget = QtWidgets.QTableWidget(5,1)
        #Set header labels
        self.TableWidget.setHorizontalHeaderLabels(["Dimensions"])
        self.TableWidget.setVerticalHeaderLabels(["A","B","C","D","E"])
        self.TableWidget.setCellWidget(0,0,CustomLineEdit())
        self.TableWidget.setCellWidget(1,0,CustomLineEdit())
        self.TableWidget.setCellWidget(2,0,CustomLineEdit())
        self.TableWidget.setCellWidget(3,0,CustomLineEdit())
        self.TableWidget.setCellWidget(4,0,CustomLineEdit())
        self.TableWidget.setItem(1,0,QtWidgets.QTableWidgetItem('1'))
        fifthBox = QtWidgets.QVBoxLayout()
        fifthBox.addWidget(self.TableWidget)
        #Add Layouts
        mainlayout.addLayout(firstBox)
        mainlayout.addLayout(secondBox)
        mainlayout.addLayout(thirdBox)
        mainlayout.addLayout(fourthBox)
        mainlayout.addLayout(fifthBox)
        self.centralWidget().setLayout(mainlayout)
        #Model
        self.mapper = None
        self.model = Model(['' for i in range(9)])
        self.setModel(self.model)
        #QUndoStack
        self.undoStack = QtWidgets.QUndoStack()
        self.stackView = QtWidgets.QUndoView(self.undoStack)
        self.stackView.setWindowTitle('StackView')
        self.stackView.show()
        #Run init methods
        self.createActions()
        self.makeConnections()
        self.listViewMethod()

    def createActions(self):
        self.UndoAct = QtWidgets.QAction("Undo", self)
        self.UndoAct.setShortcut(QtGui.QKeySequence.Undo)
        self.UndoAct.triggered.connect(self.undoStack.undo)
        self.RedoAct = QtWidgets.QAction("Redo", self)
        self.RedoAct.setShortcut(QtGui.QKeySequence.Redo)
        self.RedoAct.triggered.connect(self.undoStack.redo)
        self.toolbar = self.addToolBar('Exit')
        self.toolbar.addAction(self.UndoAct)
        self.toolbar.addAction(self.RedoAct)


    def listViewMethod(self):
        self.listView = QtWidgets.QListView()
        self.listView.setModel(self.model)
        self.listView.setWindowTitle('ListView')
        self.listView.show()

    def makeConnections(self):
        self.model.itemDataChanged.connect(self.itemDataChangedSlot)

    def setModel(self, model):
        self.mapper = QtWidgets.QDataWidgetMapper(self)
        self.mapper.setOrientation(QtCore.Qt.Vertical)
        self.mapper.setModel(self.model)
        self.mapper.addMapping(self.LineEdit1, 0)
        self.mapper.addMapping(self.LineEdit2, 1)
        self.mapper.addMapping(self.ComboBox1, 2)
        self.mapper.addMapping(self.ComboBox2, 3)
        self.mapper.addMapping(self.TableWidget.cellWidget(0,0), 4)
        self.mapper.addMapping(self.TableWidget.cellWidget(1,0), 5)
        self.mapper.addMapping(self.TableWidget.cellWidget(2,0), 6)
        self.mapper.addMapping(self.TableWidget.cellWidget(3,0), 7)
        self.mapper.addMapping(self.TableWidget.cellWidget(4,0), 8)
        self.mapper.toFirst()

    def itemDataChangedSlot(self, index, oldValue, value, role):
        if role == QtCore.Qt.EditRole:
            command = CommandTextEdit(self, index, oldValue, value, "Text changed from '{0}' to '{1}'".format(oldValue, value))
            self.undoStack.push(command)

def main():

    app = QtWidgets.QApplication(sys.argv)
    window = Window()
    window.show()
    sys.exit(app.exec_())



if __name__ == '__main__':
    main()
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

QDataWidgetMapper;将 TableWidget 映射到模型 的相关文章

随机推荐

  • Angular 模态对话框最佳实践

    与不具有动态内容的对话框相比 创建具有动态内容的模式对话框的最佳实践是什么 例如 我们有一些模式表单接受表单元素列表 并具有提交 取消功能 此外 还有一些模式对话框仅显示确认 确定类型的操作 我见过很多人说对话框应该是传递到控制器的服务 但
  • 在线运行 Facebook FQL

    我可以在网络浏览器中的哪里在线运行 FQL 查询 我可以在网络浏览器中的哪里在线运行 FQL 查询 在 Facebook 开发者中图形浏览器 https developers facebook com tools explorer工具 采用
  • 如何从 C# 中的两个列表中获取唯一对象?

    我有两个列表对象 例如 list1 id 101 name one id 102 name two id 103 name three list2 id 111 name one id 112 name two id 114 name fo
  • R、Rcpp 与 Armadillo 中矩阵 rowSums() 与 colSums() 的效率

    背景 来自 R 编程 我正在扩展到 C C 形式的编译代码Rcpp 作为循环交换 以及一般的 C C 效果的实践练习 我实现了 R 的等效项rowSums and colSums 矩阵的函数Rcpp 我知道它们以 Rcpp 糖的形式存在 并
  • 检查一个数字是 int 还是 float

    在perl中 我想检查给定变量是否包含浮点数 为了检查我正在使用的 my Var 0 02 Floating point number if int Var Var floating point number 但上面的代码对于 0 0 不起
  • 我点击的号码没有出现在反应项目的屏幕上

    当我尝试在屏幕中呈现点击的数字时 该数字没有出现 但它确实可以在控制台中显示 我不知道如何修复它应该在屏幕上 号码 旁边应用的号码 import render from testing library react import React
  • 防止 Spring Boot 注册 Spring Security 过滤器之一

    我想禁用安全链中的 Spring Security 过滤器之一 我已经看到了防止 Spring Boot 注册 servlet 过滤器 https stackoverflow com questions 28421966 prevent s
  • 什么是适合 Rails 3 的测试框架?

    去年我一直在使用 Ruby On Rails 但是 无法进行单元测试 现在我必须编写单元测试代码 哪个测试框架好 为什么 有这方面的好的教程吗 我的系统配置 Ruby 1 9 2 Rails 3 Ubuntu 10 第一个技巧是 尝试升级到
  • Clojure:只能从尾部位置重复

    我正在尝试递归地反转列表 但是我得到了Can only recur from tail position运行时 这到底意味着什么 如何改进我的代码才能使其正常工作 defn recursive reverse coll loop coll
  • 如何在Web网格的列中编写IF条件

    我在 WEB GRID 列中创建 if 条件时遇到错误 所以 请帮助改进我的代码并解决我的问题 grid Column Status format item gt
  • 迭代 bash 脚本中的变量名称

    我需要在一堆文件上运行一个脚本 这些文件的路径被分配给train1 train2 train20 我想 为什么不使用 bash 脚本使其自动执行呢 所以我做了类似的事情 train1 path to first file train2 pa
  • 未处理的异常:A 产品在处置后使用

    我在用着MultiProvider我收到此错误 Unhandled Exception A Products was used after being disposed Once you have called dispose on a P
  • 在 C 项目中使用 C++ 文件

    只是出于好奇 有没有办法在 C 项目中使用 C 文件 对于文件 我的意思是能够从头文件和库访问函数 并在您自己的项目中使用它们来解决已经解决的问题 是的 如果你小心的话 混合 C 和 C 是可能的 具体细节取决于您使用的编译器等 C FAQ
  • Rails 4:将数据库导出到 YAML

    使用 Rails 2 3 可以使用几个插件之一将数据库轻松导出 转储 到 YAML 请参阅将数据库表导出到 YAML 文件的最佳方法 https stackoverflow com questions 490507 best way to
  • 如何在 R 中合并同名列表中的数据框?

    我有一个包含很多数据框的列表 如果它们具有相同的名称 我想合并它们 即合并所有具有相同名称 a 和 b 的数据框 像这样 a lt aaaaa b lt bbbbb c lt ccccc g lt list df1 lt data fram
  • 在 Vim 中,为什么用 'j' 表示向下,用 'k' 表示向上?

    我使用 Vim 已经很多年了 但从未真正考虑过它 我的一个朋友问这是为什么 他指出在我们的文化中 左键通常映射到上 而右键映射到下 使 Vim 键向后 我知道它们位于主排 这意味着您不必将手指移动到任何地方即可击中它们 但这完全是不同的点
  • 抑制 Jenkins 文件中的管道输出

    当我在詹金斯上运行构建时 它总是在执行詹金斯步骤时打印管道 控制台当前输出 Build context CI clean app clean BUILD SUCCESSFUL in 22s 2 actionable tasks 2 exec
  • 下载 csv 文件 node.js

    我正在使用 node js 构建一个应用程序并尝试将数据下载为 csv 文件 我正在使用 json2csv https www npmjs com package json2csv https www npmjs com package j
  • Tensorflow 中的图像叠加图像卷积

    假设我有两组图像 A 和 B 每个图像都是 11X5x5x3 其中 11 是示例数量 5x5x3 是图像尺寸 Tensorflow 中是否有一种简单的方法可以对 A i 中的每个图像应用 B i 上的卷积 即 B i 扮演过滤器角色 A i
  • QDataWidgetMapper;将 TableWidget 映射到模型

    我没有找到任何文档显示 QDataWidgetMapper 实际上适用于哪些小部件 也没有找到任何使用 QTableWidget 进行映射的实现 它绝对适用于 QLineEdit 和 QComboBoxes 它们是输入小部件 但是是否可以映