Python Pyqt4模型视图-在表格模型中添加滑块、复选框行编辑
我正在处理一个ui,如下图所示 在 第一列我有一个复选框, 第二列我有一个滑块, 第三个就是文本 应用于函数的滑块值。结果将显示在第三列中 我看不到滑块而不是复选框 输出如图所示 代码: 用户界面:Python Pyqt4模型视图-在表格模型中添加滑块、复选框行编辑,python,tableview,pyqt4,model-view,Python,Tableview,Pyqt4,Model View,我正在处理一个ui,如下图所示 在 第一列我有一个复选框, 第二列我有一个滑块, 第三个就是文本 应用于函数的滑块值。结果将显示在第三列中 我看不到滑块而不是复选框 输出如图所示 代码: 用户界面: 模型用来保存信息,而不是保存视图。如果要自定义视图,应使用代理。默认情况下,如果您将其保存在CheckStateRole角色中,将创建一个复选框,如果您保存在DisplayRole中,它将显示为文本,因此即使您保存小部件,也会显示显示内存地址的_str 您应该做的只是保存数据,即bool、值和文本,
模型用来保存信息,而不是保存视图。如果要自定义视图,应使用代理。默认情况下,如果您将其保存在CheckStateRole角色中,将创建一个复选框,如果您保存在DisplayRole中,它将显示为文本,因此即使您保存小部件,也会显示显示内存地址的_str 您应该做的只是保存数据,即bool、值和文本,然后通过在第二列中创建一个编辑器来创建一个委托,并使其持久化
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。如果您想获得第一个滑块中显示的内容,我们必须使用数据方法,但这需要QModelIndex,为此我们使用:printmodel.datamodel.index0,1或printmodel.index0,1.dataif i link sliders and checkbox to database。如果要根据复选框和滑块值进行更新,我应该将update语句放在setData中,还是创建一个新方法来进行更新。。最好的方法是什么?@PramitSawant您希望通过视图更新数据库吗?这就是为什么您不使用QSqlQueryModel或QSqlTableModel的原因,这更容易,因为您意识到视图独立于模型,在我的解决方案中,我修复了错误非常严重的模型,并添加了委托以生成视图。是的。。。我将从数据库中加载复选框和滑块值。一个滑块值的更改可能会反映所有其他滑块和复选框。因此,任何滑块更改都需要更新视图。我可以保留一个按钮来更新数据库视图中的值。您是否有任何链接或文档参考以获取有关学员的更多信息?
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_())