QTableView理论总结
- 一、概述
- 二、导航
- 三、视觉外观
- 四、坐标系统
- 五、示例代码
- 1. 性别代理
- 2. 学生信息模型
- 3. 对应视图
一、概述
QTableView实现了一个tableview 来显示model 中的元素。这个类用于提供之前由QTable类提供的标准表,但这个是使用Qt的model/view架构提供的更灵活的方法。
QTableView类是Model/View类之一,是Qt的Model/View框架的一部分。
QTableView实现了由QAbstractItemView类定义的接口,以允许它显示由QAbstractItemModel类派生的 model 提供的数据。
总的来说,model/view 的方式来查看修改数据更加的方便和容易的。
二、导航
我们可以通过鼠标点击一个单元格,或者使用箭头键来导航表格中的单元格。因为 QTableView 默认启用tabKeyNavigation,我们还可以按Tab键和Backtab键在单元格之间移动。
三、视觉外观
表格的垂直头部可以通过函数verticalHeader()获得,水平头部可以通过函数horizontalHeader()获得。可以使用rowHeight()来获得表中每一行的高度。类似地,列的宽度可以使用columnWidth()得到。由于这两个部件都是普通部件,因此可以使用它们的hide()函数隐藏它们。
可以使用hideRow()、hideColumn()、showRow()和showColumn()来隐藏和显示行和列。可以使用selectRow()和selectColumn()来选择列。表格会根据 showGrid 属性显示一个网格。就想我把这个设置为 false 之后。就没有网格线啦。
表视图中显示的项与其他项视图中的项一样,都使用标准委托进行渲染和编辑。
我们还可以用 代理的方式:用下列列表来选择性别的方式
然而,对于某些任务来说,能够在表中插入其他控件有时是有用的。
用setIndexWidget()函数为特定的索引设置窗口组件,然后用indexWidget()检索窗口组件。
默认情况下,表中的单元格不会扩展以填充可用空间。
您可以通过拉伸最后的标题部分来让单元格填充可用空间。使用 horizontalHeader() 或 verticalHeader() 访问相关的 headerview 标题对象,并设置标题的stretchLastSection属性。
要根据每一列或每一行的空间需求来分配可用空间,可以调用视图的resizeColumnsToContents()或resizeRowsToContents()函数。来实现出下面这种效果。
四、坐标系统
对于某些特殊形式的表,能够在行和列索引以及控件坐标之间进行转换是很有用的。
rowAt()函数提供了指定行的视图的y坐标;行索引可以通过rowViewportPosition()获得对应的y坐标。
columnAt()和columnViewportPosition()函数提供了x坐标和列索引之间等价的转换操作。
五、示例代码
1. 性别代理
// SexComboxDelegate.h
#ifndef SEXCOMBOXDELEGATE_H
#define SEXCOMBOXDELEGATE_H
#include <QObject>
#include <QStyledItemDelegate>
#include <QComboBox>
class SexComboxDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
SexComboxDelegate(QObject *parent = nullptr);
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,
const QModelIndex &index) const override;
void setEditorData(QWidget *editor, const QModelIndex &index) const override;
void setModelData(QWidget *editor, QAbstractItemModel *model,
const QModelIndex &index) const override;
void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option,
const QModelIndex &index) const override;
};
#endif // SEXCOMBOXDELEGATE_H
// SexComboxDelegate.cpp
#include "SexComboxDelegate.h"
SexComboxDelegate::SexComboxDelegate(QObject *parent)
{
}
QWidget *SexComboxDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
QComboBox *editor = new QComboBox(parent);
editor->addItems(QStringList{"男", "女"});
editor->setFrame(false);
return editor;
}
void SexComboxDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
QComboBox *combox = static_cast<QComboBox*>(editor);
combox->setCurrentIndex(combox->findText(index.model()->data(index, Qt::DisplayRole).toString()));
}
void SexComboxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
QComboBox *combox = static_cast<QComboBox*>(editor);
model->setData(index, combox->currentText(), Qt::EditRole);
}
void SexComboxDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
editor->setGeometry(option.rect);
}
2. 学生信息模型
// StudentModel.h
#ifndef STUDENTMODEL_H
#define STUDENTMODEL_H
#include <QAbstractTableModel>
#include <QDebug>
#include <QColor>
#include <QBrush>
#include <QFont>
class StudentModel: public QAbstractTableModel
{
Q_OBJECT
public:
StudentModel(QObject *parent = nullptr);
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
Qt::ItemFlags flags(const QModelIndex &index) const override;
void setRow(int newRow);
void setColumn(int newColumn);
void setTableHeader(QList<QString> *header);
void setTableData(QList<QList<QString>> *data);
signals:
void editCompleted(const QString &);
public slots:
void SlotUpdateTable();
private:
int row = 0;
int column = 0;
QList<QString> *m_header;
QList<QList<QString>> *m_data;
};
#endif // STUDENTMODEL_H
// StudentModel.cpp
#include "StudentModel.h"
StudentModel::StudentModel(QObject *parent) : QAbstractTableModel(parent)
{
}
int StudentModel::rowCount(const QModelIndex &parent) const
{
return row;
}
int StudentModel::columnCount(const QModelIndex &parent) const
{
return column;
}
QVariant StudentModel::data(const QModelIndex &index, int role) const
{
if(role == Qt::DisplayRole || role == Qt::EditRole)
{
return (*m_data)[index.row()][index.column()];
}
if(role == Qt::TextAlignmentRole)
{
return Qt::AlignCenter;
}
if(role == Qt::BackgroundRole && index.row() % 2 == 0)
{
return QBrush(QColor(50, 50, 50));
}
return QVariant();
}
QVariant StudentModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (role == Qt::DisplayRole && orientation == Qt::Horizontal) {
if(m_header->count() - 1 >= section)
return m_header->at(section);
}
//qDebug()<<role << "--" << Qt::BackgroundRole;
// if(role == Qt::BackgroundRole)
// {
// return QBrush(QColor(156, 233, 248));
// }
// if(role == Qt::ForegroundRole)
// {
// return QBrush(QColor(156, 233, 248));
// }
if(role == Qt::FontRole)
{
return QFont(tr("微软雅黑"),10, QFont::DemiBold);
}
return QVariant();
}
bool StudentModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
if (role == Qt::EditRole) {
if (!checkIndex(index))
return false;
//save value from editor to member m_gridData
(*m_data)[index.row()][index.column()] = value.toString();
return true;
}
return false;
}
Qt::ItemFlags StudentModel::flags(const QModelIndex &index) const
{
return Qt::ItemIsEditable | QAbstractTableModel::flags(index);
}
void StudentModel::setRow(int newRow)
{
row = newRow;
}
void StudentModel::setColumn(int newColumn)
{
column = newColumn;
}
void StudentModel::setTableHeader(QList<QString> *header)
{
m_header = header;
}
void StudentModel::setTableData(QList<QList<QString> > *data)
{
m_data = data;
}
void StudentModel::SlotUpdateTable()
{
emit dataChanged(createIndex(0, 0), createIndex(row, column), {Qt::DisplayRole});
}
3. 对应视图
// StudentWD.h
#ifndef STUDENTWD_H
#define STUDENTWD_H
#include <QWidget>
#include <Model/StudentModel.h>
#include <QFileDialog>
#include <QStandardPaths>
#include <QFile>
#include <QTextStream>
#include <Delegate/SpinBoxDelegate.h>
#include <Delegate/SexComboxDelegate.h>
namespace Ui {
class StudentWD;
}
class StudentWD : public QWidget
{
Q_OBJECT
public:
explicit StudentWD(QWidget *parent = nullptr);
~StudentWD();
private slots:
void on_ImportBtn_clicked();
private:
Ui::StudentWD *ui;
StudentModel *model;
SpinBoxDelegate *spinBoxDelegate;
SexComboxDelegate *sexBoxDeleage;
QList<QList<QString>> subject_table;
QList<QString> subject_title;
};
#endif // STUDENTWD_H
// StudentWD.cpp
#include "StudentWD.h"
#include "ui_StudentWD.h"
StudentWD::StudentWD(QWidget *parent) :
QWidget(parent),
ui(new Ui::StudentWD),
model(new StudentModel),
spinBoxDelegate(new SpinBoxDelegate),
sexBoxDeleage(new SexComboxDelegate)
{
ui->setupUi(this);
ui->tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
}
StudentWD::~StudentWD()
{
delete ui;
}
void StudentWD::on_ImportBtn_clicked()
{
QString fileName = QFileDialog::getOpenFileName(this,
tr("打开 csv 文件"), QStandardPaths::writableLocation(QStandardPaths::DesktopLocation), tr("Txt Files (*.txt *.csv *.*)"));
subject_table.clear();
subject_title.clear();
if(!fileName.isNull() && !fileName.isEmpty())
{
QFile file(fileName);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
return;
int i = 0;
QTextStream in(&file);
in.setCodec("UTF-8");
while (!file.atEnd()) {
QString line = file.readLine();
if(i == 0)
{
subject_title = line.split(",", QString::SkipEmptyParts);
subject_title.last() = subject_title.last().trimmed();
i++;
continue;
}
subject_table.append(line.split(",", QString::SkipEmptyParts));
subject_table.last().last() = subject_table.last().last().trimmed();
}
ui->Total_Subject_SB->setValue(subject_title.count());
ui->Total_People_SB->setValue(subject_table.count());
model->setColumn(subject_title.count());
model->setRow(subject_table.count());
model->setTableData(& subject_table);
model->setTableHeader(& subject_title);
ui->tableView->setModel(model);
ui->tableView->setItemDelegateForColumn(0, spinBoxDelegate);
ui->tableView->setShowGrid(true);
ui->tableView->setItemDelegateForColumn(1, sexBoxDeleage);
for (int i = 2; i < subject_table.count(); ++i) {
ui->tableView->setItemDelegateForColumn(i, spinBoxDelegate);
}
ui->tableView->horizontalHeader()->setSectionResizeMode(4, QHeaderView::ResizeToContents);
}
}
对应的ui文件