如何使用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关联每个索引,然后使用QStandarItemtext()方法获取文本。

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 中的行大小?

如何从函数传递 QStandardItemModel?

qt - 如何对 qstandarditemmodel 进行永久排序

关于QStandardItemModel