【问题标题】:Pyqt4 Model View - Adding Slider , CheckBox Line Edit in Table modelPyqt4 模型视图 - 在表格模型中添加滑块、复选框线编辑
【发布时间】:2018-10-08 10:03:20
【问题描述】:

我正在开发如下图所示的用户界面。

在 第一列我有一个复选框, 第二列我有一个滑块, 第三只是文本

应用于函数的滑块值。结果将显示在第三列。

我看不到滑块而不是复选框

输出如图所示

代码:

from PyQt4 import QtGui, QtCore, uic
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *


class PaletteTableModel(QtCore.QAbstractTableModel):
    def __init__(self, colors = [[]], parent = None):
        QtCore.QAbstractTableModel.__init__(self, parent)
        self.__colors = colors
    def rowCount(self, parent):
        return len(self.__colors)  
    def columnCount(self, parent):
        return len(self.__colors[0])
    def flags(self, index):
        if not index.isValid():
            return None
        if index.column() == 0:
            return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsUserCheckable
        else:
            return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable

    def data(self, index, role):        
        row = index.row()
        col = index.column()
        if role == QtCore.Qt.DisplayRole:
            return '{0}'.format(self.__colors[row][col])
        elif role == Qt.CheckStateRole and col==0:
            return QPersistentModelIndex(index)
        else:
            return None
    def setData(self, index, value, role=Qt.EditRole):
        if not index.isValid():
            return False
        if role == Qt.CheckStateRole:
            if index.column() == 0:
                if self.__colors[index.row()][index.column()].isChecked():
                    return QtCore.Qt.Checked
                else:
                    return QtCore.Qt.Unchecked   

if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    app.setStyle("plastique")

    tableView = QtGui.QTableView()
    tableView.show()

    row = 6
    col = 3
    table_data = []
    for row in range(row):
        data = [None,None,None]
        #Checkbox
        c1 = QCheckBox("c"+str(row))
        c1.setChecked(True)
        data[0] = c1

        #slider
        s1 = QSlider(Qt.Horizontal)
        s1.setMinimum(10)
        s1.setMaximum(30)
        s1.setValue(20)
        data[1] = s1   

        #text
        data[2] = 'TEST'
        table_data.append(data)


    model = PaletteTableModel(table_data)    
    tableView.setModel(model)

    sys.exit(app.exec_())

用户界面:

【问题讨论】:

    标签: python tableview pyqt4 model-view


    【解决方案1】:

    模型用于保存信息,而不是保存视图。如果要自定义视图,则应使用委托。默认情况下,如果您将其保存在CheckStateRole 角色中,则会创建一个复选框,如果您将其保存在DisplayRole 中,它将显示为文本,因此即使您保存小部件,显示的也是__str__显示内存地址。

    你应该做的只是保存数据,即bool、value和text,然后通过在第二列中创建一个编辑器来创建一个delegate并使其持久化。

    import sys
    from PyQt4 import QtCore, QtGui
    
    
    class PaletteTableModel(QtCore.QAbstractTableModel):
        def __init__(self, cols=3,colors = [], parent = None):
            super(PaletteTableModel, self).__init__(parent)
            self.__colors = colors
            self.__cols = cols
    
        def rowCount(self, parent=QtCore.QModelIndex()):
            return len(self.__colors)  
    
        def columnCount(self, parent=QtCore.QModelIndex()):
            if parent.isValid():
                return 0
            return self.__cols
    
        def appendRow(self, data):
            self.beginInsertRows(QtCore.QModelIndex(), self.rowCount(), self.rowCount())
            self.__colors.append(data[:])
            self.endInsertRows()
    
        def flags(self, index):
            fl = QtCore.Qt.NoItemFlags
            if index.isValid():
                fl |= QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEditable
                if index.column() == 0:
                    fl |= QtCore.Qt.ItemIsUserCheckable
            return fl
    
        def data(self, index, role=QtCore.Qt.DisplayRole):        
            if not index.isValid():
                return None
            row = index.row()
            col = index.column()
            if 0 <= row < self.rowCount() and 0<= col < self.columnCount():
                if role  == QtCore.Qt.DisplayRole and 0 < col < self.columnCount():
                    return self.__colors[row][col]
                elif role == QtCore.Qt.CheckStateRole and col == 0:
                    return QtCore.Qt.Checked if self.__colors[row][0] else QtCore.Qt.Unchecked
            return None
    
        def setData(self, index, value, role=QtCore.Qt.EditRole):
            if not index.isValid():
                return False
            row = index.row()
            col = index.column()
            if role == QtCore.Qt.CheckStateRole and col == 0:
                self.__colors[row][col] = value == QtCore.Qt.Checked
                return True
            elif role in (QtCore.Qt.DisplayRole, QtCore.Qt.EditRole):
                if 0 < index.column() < self.columnCount():
                    self.__colors[row][col] = value
                    return True
            return False
    
    
    class PaletteDelegate(QtGui.QStyledItemDelegate):
        def paint(self, painter, option, index):
            if index.column() == 1:
                view = option.widget
                if isinstance(view, QtGui.QTableView):
                    if not view.openPersistentEditor(index):
                        view.openPersistentEditor(index)
            else:
                super(PaletteDelegate, self).paint(painter, option, index)
    
        def createEditor(self, parent, option, index):
            if index.column() == 1:
                editor = QtGui.QSlider(parent, minimum=10, maximum=30, orientation=QtCore.Qt.Horizontal)
                editor.valueChanged.connect(self.commitEditor)
                return editor
            return super(PaletteDelegate, self).createEditor(parent, option, index)
    
        def setEditorData(self, editor, index):
            if index.column() == 1:
                val = index.data()
                if isinstance(val, QtCore.QVariant):
                    _, val = val.toInt()
                editor.setValue(val)
            else:
                super(PaletteDelegate, self).setEditorData(editor, index)
    
        def setModelData(self, editor, model, index):
            if index.column() == 1:
                model.setData(index, editor.value())
            else:
                super(PaletteDelegate, self).setModelData(editor,model, index)
    
        def commitEditor(self):
            editor = self.sender()
            self.commitData.emit(editor)
    
    
    if __name__ == '__main__':
        app = QtGui.QApplication(sys.argv)
        app.setStyle("plastique")
    
        tableView = QtGui.QTableView()
        tableView.show()
    
        row, col = 6, 3
    
        model = PaletteTableModel(cols=col, parent=tableView)
        tableView.setModel(model)
        tableView.setItemDelegate(PaletteDelegate(tableView))
    
        for r in range(row):
            data = [True, 20, 'TEST']
            model.appendRow(data)
    
        sys.exit(app.exec_())
    

    【讨论】:

    • 谢谢,如何获取 data() 和 setData() 函数中的滑块值??
    • @PramitSawant data() 用于获取模型信息,setData() 用于更新模型,是getter和setter。如果要获取第一个滑块中显示的内容,我们必须使用 data 方法,但这需要 QModelIndex,为此我们使用:print(model.data(model.index(0, 1)))print(model.index(0, 1).data())
    • 如果我将滑块和复选框链接到数据库。并且想根据 chech 框和滑块值进行更新,我应该将更新语句放在 setData() 中还是创建一个新方法来执行此操作.. 最好的方法是什么?
    • @PramitSawant 是否希望通过视图更新数据库?这就是为什么您不使用 QSqlQueryModel 或 QSqlTableModel 的原因,它更容易,因为您意识到视图独立于模型,在我的解决方案中,我修复了您的模型错误非常严重,并添加了委托来生成视图。跨度>
    • 是的...我将从数据库中加载复选框和滑块值。更改的一个滑块值可能会反映所有其他滑块和复选框。所以视图需要在任何滑块更改时更新。我可以保留一个按钮来更新数据库视图中的值。您是否有任何链接或文档参考以获取有关代表的更多信息?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-04-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-20
    相关资源
    最近更新 更多