问题
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_())
来源:https://stackoverflow.com/questions/52699852/pyqt4-model-view-adding-slider-checkbox-line-edit-in-table-model