Pyqt4 Model View - Adding Slider , CheckBox Line E

2019-03-03 19:20发布

问题:

I am working on a ui as shown in the image below.

In the First columns i have a Check Box, Second columns i have a Slider, Third just text

the slider value applied to a function. the result will be shown in the third column.

I am not not able to see the slider not the checkbox

Output is shown in the image

Code:

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_())

UI:

回答1:

The models serve to keep information, do not keep the view. If you want to customize the view you should use delegates. By default if you save it in the CheckStateRole role, a checkbox will be created, if you save in the DisplayRole it will be displayed as text, so even if you save the widgets what is shown is the __str__ that shows the memory address.

What you should do is just save the data, that is, the bool, the value and the text, and then create a delegate by creating an editor in the second column and make it persistent.

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_())