如何使用qstandarditemmodel获取qtableview中的数据
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何使用qstandarditemmodel获取qtableview中的数据相关的知识,希望对你有一定的参考价值。
参考技术A 类QabstractItemModel,QabstractListModel,QAbstractTableModel不保存数据,用户需要从这些类派生出子类,并在子类中定义某种数据结构来保存数据。与此不同,类QStandardItemModel负责保存数据,每个数据项被表示为类QStandardItem的对象。我们首先阐述如何使用类QStandardItem保存一个数据项,再阐述如何使用类QStandardItemModel将这些数据项组织起来,形成列表、表格或者树,以供其他视图类显示。理论参考:http://book.51cto.com/art/201207/347880.htm
关键是QAbstractItemView.setItemDelegateForColumn函数,可以设置进度条代理。
其中QAbstractItemView的函数特别多,QStandardItem的函数也特别多。
int main( int argc, char **argv )
QApplication app( argc, argv );
QTableView table;
QStandardItemModel model( 10, 2 );
for( int r=0; r<10; ++r )
QStandardItem *item = new QStandardItem( QString("Row %1").arg(r+1) );
model.setItem( r, 0, item );
model.setItem( r, 1, new QStandardItem( QString::number((r*30)%100 )) );
table.setModel( &model ); // 正常设置模型,没有任何特殊之处
BarDelegate delegate;
table.setItemDelegateForColumn( 1, &delegate ); // 设置第一列为代理
table.show();
return app.exec();
除了调用父类构造函数,还要覆盖两个纯虚函数paint和sizeHint
class BarDelegate : public QAbstractItemDelegate
public:
BarDelegate( QObject *parent = 0 );
// 覆盖两个函数就可以显示进度条
void paint( QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index ) const;
QSize sizeHint( const QStyleOptionViewItem &option, const QModelIndex &index ) const;
;
具体每一步的解释:
BarDelegate::BarDelegate( QObject *parent ) : QAbstractItemDelegate( parent )
void BarDelegate::paint( QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index ) const
if( option.state & QStyle::State_Selected )
painter->fillRect( option.rect, option.palette.highlight() );
// 数据是存储在QStandardItemModel的QStandardItem,会自动根据当前行进行匹配(我认为)
int value = index.model()->data( index, Qt::DisplayRole ).toInt(); // 这句,取得当前行的数据
qDebug() << value;
double factor = double(value)/100.0; // 计算比例因子
painter->save(); // 保存旧画板(我认为)
// 进度条背景色
if( factor > 0.8 )
painter->setBrush( Qt::red ); // 超过0.8画纯红色
factor = 1;
else
painter->setBrush( QColor( 0, int(factor*255), 255-int(factor*255) ) ); // 否则颜色依次变淡
painter->setPen( Qt::black ); // 画笔颜色(这里没用到,我认为)
// 前面都是准备工作,这里才是真正画进度条
painter->drawRect( option.rect.x()+2, option.rect.y()+2, int(factor*(option.rect.width()-5)), option.rect.height()-5 );
painter->restore(); // 恢复新画板(我认为)
QSize BarDelegate::sizeHint( const QStyleOptionViewItem &option, const QModelIndex &index ) const
return QSize( 45, 15 ); // 随便改,不影响(我认为)本回答被提问者采纳
使用 QStandardItemModel 在 QListView 中获取选定的索引
【中文标题】使用 QStandardItemModel 在 QListView 中获取选定的索引【英文标题】:Get selected index in QListView using QStandardItemModel 【发布时间】:2018-08-27 13:29:31 【问题描述】:我正在使用以下代码创建 QListView 和 QStandardItemModel:
self.listView = QtWidgets.QListView(self.groupBox2)
self.listView.setGeometry(QtCore.QRect(200, 20, 400, 220))
self.entry = QtGui.QStandardItemModel()
我正在使用类似于以下内容的循环中添加项目:
self.item1 = QtGui.QStandardItem("Itemname1")
self.entry.appendRow(self.item1)
self.item2 = QtGui.QStandardItem("Itemname2")
self.entry.appendRow(self.item2)
如果知道列表中的 0 代表“Itemname1”,1 代表“Itemname2”等,如何将这些项目分配给列表?
另外,如何将 QListView 中的项目设置为选中?
setSelected()
似乎不存在 QStandardItemModel
【问题讨论】:
【参考方案1】:QStandardItemModel
是一个模型,因此您可以将QAbstractItemModel
的所有方法用作告诉我们行数的rowCount()
,因此您可以遍历它们并使用item()
方法得到QStandarItem
关联每个索引,然后使用QStandarItem
的text()
方法获取文本。
l = [self.entry.item(i).text() for i in range(self.entry.rowCount())]
print(l)
另一方面,如果您想选择从QAbstractItemView
继承的视图元素,如本例中的QListView
,您必须使用与将使用@987654332 方法获得的视图关联的QItemSelectionModel
@。 QItemSelectionModel
有几种方法以不同的方式选择和取消选择,在这种情况下,您必须使用方法 select 并传递标志 QItemSelectionModel::Select
。另一方面,默认情况下,视图可以选择单个元素,如果要选择更多元素,则必须使用 setSelectionMode()
方法并将标志 QAbstractItemView::MultiSelection
传递给它。
例子:
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Widget, self).__init__(parent)
lay = QtWidgets.QVBoxLayout(self)
button = QtWidgets.QPushButton("to list")
button.clicked.connect(self.modelToList)
self.listView = QtWidgets.QListView()
lay.addWidget(button)
lay.addWidget(self.listView)
self.entry = QtGui.QStandardItemModel()
self.listView.setModel(self.entry)
for text in ("Itemname1", "Itemname2", "Itemname3", "Itemname4"):
it = QtGui.QStandardItem(text)
self.entry.appendRow(it)
self.listView.setSelectionMode(QtWidgets.QAbstractItemView.MultiSelection)
sm = self.listView.selectionModel()
for item in (self.entry.item(1), self.entry.item(2)):
index = self.entry.indexFromItem(item)
sm.select(index, QtCore.QItemSelectionModel.Select)
def modelToList(self):
l = [self.entry.item(i).text() for i in range(self.entry.rowCount())]
print(l)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
w = Widget()
w.show()
sys.exit(app.exec_())
如果您只想选择一个项目,那么您必须使用setCurrentIndex()
,因为它在内部调用selectionModel()
的select()
方法。
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from random import randint
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Widget, self).__init__(parent)
lay = QtWidgets.QVBoxLayout(self)
button = QtWidgets.QPushButton("to list")
button.clicked.connect(self.modelToList)
self.listView = QtWidgets.QListView()
lay.addWidget(button)
lay.addWidget(self.listView)
self.entry = QtGui.QStandardItemModel()
self.listView.setModel(self.entry)
for text in ("Itemname1", "Itemname2", "Itemname3", "Itemname4"):
it = QtGui.QStandardItem(text)
self.entry.appendRow(it)
item = self.entry.item(randint(0, self.entry.rowCount()-1))
self.listView.setCurrentIndex(self.entry.indexFromItem(item))
def modelToList(self):
l = [self.entry.item(i).text() for i in range(self.entry.rowCount())]
print(l)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
w = Widget()
w.show()
sys.exit(app.exec_())
【讨论】:
【参考方案2】:试试看:
import sys
from PyQt5 import QtWidgets, QtGui, QtCore
from PyQt5.QtGui import QBrush, QColor
class Widget(QtWidgets.QWidget):
def __init__(self):
super().__init__()
lay = QtWidgets.QVBoxLayout(self)
self.listView = QtWidgets.QListView()
self.label = QtWidgets.QLabel("Please Select item in the QListView")
lay.addWidget(self.listView)
lay.addWidget(self.label)
self.entry = QtGui.QStandardItemModel()
self.listView.setModel(self.entry)
self.listView.clicked[QtCore.QModelIndex].connect(self.on_clicked)
# When you receive the signal, you call QtGui.QStandardItemModel.itemFromIndex()
# on the given model index to get a pointer to the item
for text in ["Itemname1", "Itemname2", "Itemname3", "Itemname4"]:
it = QtGui.QStandardItem(text)
self.entry.appendRow(it)
self.itemOld = QtGui.QStandardItem("text")
def on_clicked(self, index):
item = self.entry.itemFromIndex(index)
self.label.setText("on_clicked: itemIndex=``, itemText=``"
"".format(item.index().row(), item.text()))
item.setForeground(QBrush(QColor(255, 0, 0)))
self.itemOld.setForeground(QBrush(QColor(0, 0, 0)))
self.itemOld = item
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
w = Widget()
w.show()
sys.exit(app.exec_())
【讨论】:
以上是关于如何使用qstandarditemmodel获取qtableview中的数据的主要内容,如果未能解决你的问题,请参考以下文章
Qt入门教程数据模型篇 QStandardItemModel标准项目模型
有没有办法将 QTableView 模型转换为 QStandardItemModel
如何调整 QTreeView 和 QStandardItemModel 中的行大小?