一、QTableWidget
1、简介
QTableWidget是QT中的表格组件类,一般用来展示多行多列的数据,是QT中使用较多的控件之一。QTableWidgetItem用来表示表格中的一个单元格,整个表格都需要用逐个单元格构建起来。
2、QTableWidget常用方法
2.1、设置表格的行数与列数
// 设置表格列数
void QTableWidget::setColumnCount(int columns)
// 设置表格行数
void QTableWidget::setRowCount(int rows)
// 获取表格列数
int QTableWidget::columnCount() const
// 获取表格行数
int QTableWidget::rowCount() const
2.2、添加单元格
// 添加单元格
void QTableWidget::setItem(int row, int column, QTableWidgetItem *item)
// 合并单元格
void QTableView::setSpan(int row, int column, int rowSpanCount, int columnSpanCount)
// 清除单元格(包含表头)
void QTableWidget::clear()
// 清除单元格内容(不包含表头)
void QTableWidget::clearContents()
2.3、表头设置
/**************************** 水平表头设置 *****************************/
// 设置表头单元格
void QTableWidget::setHorizontalHeaderItem(int column, QTableWidgetItem *item)
// 设置表头显示的文本信息
void QTableWidget::setHorizontalHeaderLabels(const QStringList &labels)
// 获取表头单元格
QTableWidgetItem* QTableWidget::horizontalHeaderItem(int column) const
/**************************** 垂直表头设置 *****************************/
// 设置表头单元格
void QTableWidget::setVerticalHeaderItem(int row, QTableWidgetItem *item)
// 设置表头显示的文本信息
void QTableWidget::setVerticalHeaderLabels(const QStringList &labels)
// 获取表头单元格
QTableWidgetItem* QTableWidget::verticalHeaderItem(int row) const
2.4、设置行表头、列表头是否显示
/**************************** 行表头视图 *****************************/
// 获取行表头视图
QHeaderView *QTableView::horizontalHeader()
// 隐藏行表头
virtual void QWidget::setVisible(bool visible)
/**************************** 列表头视图 *****************************/
// 获取列表头视图
QHeaderView *QTableView::verticalHeader()
// 隐藏列表头
virtual void QWidget::setVisible(bool visible)
2.5、设置选择行为
void QAbstractItemView::setSelectionBehavior(QAbstractItemView::SelectionBehavior behavior)
enum QAbstractItemView::SelectionBehavior | 功能 |
---|---|
QAbstractItemView::SelectItems | 选中单个单元格 |
QAbstractItemView::SelectRows | 行选中 |
QAbstractItemView::SelectColumns | 列选中 |
2.6、设置单元格控件
QTableWidget不仅允许把文字加到单元格,还允许把控件也放到单元格中
// 获取单元格控件
QWidget *QTableWidget::cellWidget(int row, int column)
// 设置单元格控件
void QTableWidget::setCellWidget(int row, int column, QWidget *widget)
2.7、信号
下面是QTableWidget常用的信号,如下:
// 当item对应的data发生变化时,触发下面的信号
void QTableWidget::cellChanged(int row, int column)
// 双击单元格触发下面的信号
void QTableWidget::cellDoubleClicked(int row, int column)
3、QTableWidget代理
3.1、设置代理
可以给QTableWidget设置代理,通过代理能够自定义数据条目(item)的显示和编辑方式,QTableWidget提供的设置代理相关的方法如下:
// 给表格设置代理
void QAbstractItemView::setItemDelegate(QAbstractItemDelegate *delegate)
// 给列设置代理
void QAbstractItemView::setItemDelegateForColumn(int column, QAbstractItemDelegate *delegate)
// 给行设置代理
void QAbstractItemView::setItemDelegateForRow(int row, QAbstractItemDelegate *delegate)
注意 :只能给行、列、表格设置代理,不能给单个单元格设置代理
下面是Demo的截图,具体源码可以参考3.3
3.2、设置模型数据
QTableWidget默认使用的模型是QStandardItemModel,QTableWidget的每个单元格是一个QTableWidgetItem对象、Item、Delegate、Model三者间的数据交互关系如下:
文章来源:https://www.toymoban.com/news/detail-547228.html
// QModelIndex提供的获取模型的方法
const QAbstractItemModel *QModelIndex::model() const
// QTableWidgetItem提供的操作数据的方法
QVariant QTableWidgetItem::data(int role) const
void QTableWidgetItem::setData(int role, const QVariant &value)
// QAbstractItemModel提供的操作数据的方法
QVariant QAbstractItemModel::data(const QModelIndex &index, int role = Qt::DisplayRole) const
bool QAbstractItemModel::setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole)
注意:调用QTableWidgetItem::setData设置的数据,最终是设置到Model里面了,这一点Demo里面的onCliecked槽函数有验证文章来源地址https://www.toymoban.com/news/detail-547228.html
3.3、代理触发时机
3.4、示例
// qcustomwidget.h
#ifndef QCUSTOMWIDGET_H
#define QCUSTOMWIDGET_H
#include <QWidget>
#include <QTableWidget>
#include <QStyledItemDelegate>
#include <QObject>
#include <QPushButton>
struct RowData
{
QString name;
QString age;
QString sex;
QString number;
};
class LineEditDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
explicit LineEditDelegate(QObject* parent = nullptr);
~LineEditDelegate();
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;
private:
QTableWidget *m_pTableWidget;
};
class ComboBoxDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
explicit ComboBoxDelegate(QObject* parent = nullptr);
~ComboBoxDelegate();
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;
private:
QTableWidget *m_pTableWidget;
};
// 之所以要继承QTableWidget,是因为QTableWidget::indexFromItem方法是Protected,外面无法访问,继承QTableWidget,可以重新提供一个接口GetIndexFromItem
// 根据item获取对应的QModelIndex
// 主要是为了验证一个问题点:调用item->setData,会影响QTableWidget对应的model,即:item->setData设置的数据,会直接设置到model里面
class QMyTableWidget : public QTableWidget
{
Q_OBJECT
public:
QMyTableWidget(QWidget *parent = 0);
QMyTableWidget(int rows, int columns, QWidget *parent = Q_NULLPTR);
QModelIndex GetIndexFromItem(QTableWidgetItem *item) const;
};
class QCustomWidget : public QWidget
{
Q_OBJECT
public:
QCustomWidget(QWidget *parent = 0);
~QCustomWidget();
public:
void Init();
private:
// 创建控件
void CreateWidgets();
// 给控件添加布局
void CreateLayout();
// 初始化表格样式
void InitTableStyle();
// 初始化表格内容
void InitTableContent();
// 初始化表格显示的数据
void InitTableData();
// 初始化表格代理
void InitTableDelegate();
public slots:
void OnCliecked();
void OnCellChanged(int row, int column);
void OnCellDoubleClicked(int row, int column);
private:
QMyTableWidget *m_pTableWidget;
QPushButton *m_pPushButton;
std::vector<RowData> m_rowData;
};
#endif // QCUSTOMWIDGET_H
// qcustomwidget.cpp
#include "qcustomwidget.h"
#include <QStringList>
#include <QHeaderView>
#include <QHBoxLayout>
#include <QComboBox>
#include <QLineEdit>
#include <QMetaObject>
#include <QPushButton>
#include <QDebug>
const int MAX_COLUMN_SIZE = 4;
/**************************************************************************/
/* LineEditDelegate 代理 */
/**************************************************************************/
LineEditDelegate::LineEditDelegate(QObject* parent) : QStyledItemDelegate(parent)
{
m_pTableWidget = qobject_cast<QTableWidget*>(parent);
}
LineEditDelegate::~LineEditDelegate()
{
}
QWidget* LineEditDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
QLineEdit *editor = new QLineEdit(parent);
return editor;
}
void LineEditDelegate::setEditorData(QWidget* editor, const QModelIndex& index) const
{
QString text = index.model()->data(index, Qt::UserRole).toString();
double value = floor((text.toDouble() * pow(10, 3) + 0.5)) / pow(10, 3);
// 单元格设置修改的值时,会修改Qt::EditRole角色存储的数据,通过下面的打印可以很清楚地证明这一点
QString strText = QString::number(value, 'f', 3);
m_pTableWidget->item(index.row(), index.column())->setText(strText);
qDebug() << "setEditorData data(Qt::EditRole) = " << m_pTableWidget->item(index.row(), index.column())->data(Qt::EditRole);
qDebug() << "setEditorData data(Qt::UserRole) = " << m_pTableWidget->item(index.row(), index.column())->data(Qt::UserRole);
QLineEdit* pLineEdit = qobject_cast<QLineEdit*>(editor);
pLineEdit->setText(text);
}
void LineEditDelegate::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const
{
QLineEdit* pLineEdit = qobject_cast<QLineEdit*>(editor);
QString text = pLineEdit->text();
model->setData(index, text, Qt::UserRole);
}
/**************************************************************************/
/* ComboBoxDelegate 代理 */
/**************************************************************************/
ComboBoxDelegate::ComboBoxDelegate(QObject* parent) : QStyledItemDelegate(parent)
{
m_pTableWidget = qobject_cast<QTableWidget*>(parent);
}
ComboBoxDelegate::~ComboBoxDelegate()
{
}
QWidget* ComboBoxDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
QComboBox *editor = new QComboBox(parent);
editor->addItem(QString::fromLocal8Bit("男"));
editor->addItem(QString::fromLocal8Bit("女"));
editor->setCurrentIndex(0);
return editor;
}
void ComboBoxDelegate::setEditorData(QWidget* editor, const QModelIndex& index) const
{
QComboBox* pComboBox = qobject_cast<QComboBox*>(editor);
QString text = index.model()->data(index, Qt::EditRole).toString();
int nIndex = pComboBox->findText(text);
pComboBox->setCurrentIndex(nIndex);
return;
}
void ComboBoxDelegate::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const
{
QComboBox* pComboBox = qobject_cast<QComboBox*>(editor);
QString text = pComboBox->currentText();
model->setData(index, text, Qt::EditRole);
}
/**************************************************************************/
/* QMyTableWidget 类实现 */
/**************************************************************************/
QMyTableWidget::QMyTableWidget(QWidget *parent) : QTableWidget(parent)
{
}
QMyTableWidget::QMyTableWidget(int rows, int columns, QWidget *parent) : QTableWidget(rows, columns, parent)
{
}
QModelIndex QMyTableWidget::GetIndexFromItem(QTableWidgetItem *item) const
{
return indexFromItem(item);
}
/**************************************************************************/
/* QCustomWidget 类实现 */
/**************************************************************************/
void QCustomWidget::OnCliecked()
{
// QTableWidgetItem *item = m_pTableWidget->item(1, 1);
// item->setData(Qt::EditRole, QVariant(QString("123")));
// QModelIndex index = m_pTableWidget->GetIndexFromItem(item);
// QVariant data = index.model()->data(index, Qt::EditRole);
// qDebug() << data.toString();
}
QCustomWidget::QCustomWidget(QWidget *parent) : QWidget(parent)
{
// 设置QWidget对应的背景色
setStyleSheet("background-color:yellow;");
Init();
}
QCustomWidget::~QCustomWidget()
{
qDebug() << "QCustomWidget Destroy";
}
void QCustomWidget::Init()
{
CreateWidgets();
CreateLayout();
InitTableData();
InitTableContent();
InitTableStyle();
InitTableDelegate();
connect(m_pPushButton, SIGNAL(clicked()), this, SLOT(OnCliecked()));
connect(m_pTableWidget, SIGNAL(cellChanged(int, int)), this, SLOT(OnCellChanged(int, int)));
connect(m_pTableWidget, SIGNAL(cellDoubleClicked(int, int)), this, SLOT(OnCellDoubleClicked(int, int)));
}
void QCustomWidget::InitTableStyle()
{
// 设置表格占满父窗口
m_pTableWidget->setAutoFillBackground(true);
// 设置表格行选中
// m_pTableWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
// 表格大小自适应父窗口变化
m_pTableWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
// 设置每列的宽度自适应窗口变化
m_pTableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
// 设置行表头不能被选中
m_pTableWidget->horizontalHeader()->setSelectionMode(QAbstractItemView::NoSelection);
// 隐藏列表头
m_pTableWidget->verticalHeader()->hide();
// 设置不显示表格线
// m_pTableWidget->setShowGrid(false);
// 设置右键下拉菜单样式
m_pTableWidget->setContextMenuPolicy(Qt::CustomContextMenu);
}
void QCustomWidget::InitTableData()
{
RowData data1 = {QString("Jams"), QString("20"), QString::fromLocal8Bit("男"), QString("123456789")};
RowData data2 = {QString("Messi"), QString("20"), QString::fromLocal8Bit("男"), QString("123456789")};
RowData data3 = {QString("Luccy"), QString("20"), QString::fromLocal8Bit("男"), QString("123456789")};
m_rowData.push_back(data1);
m_rowData.push_back(data2);
m_rowData.push_back(data3);
}
void QCustomWidget::InitTableContent()
{
for (int row = 0; row < m_rowData.size(); row ++)
{
// 注意:如果不设置行数,表格的内容显示不出来
m_pTableWidget->setRowCount(m_pTableWidget->rowCount() + 1);
for (int col = 0; col < MAX_COLUMN_SIZE; col ++)
{
QTableWidgetItem* pTableWidgetItemItem = new QTableWidgetItem;
switch(col)
{
case 0:
pTableWidgetItemItem->setText(m_rowData[row].name);
break;
case 1:
pTableWidgetItemItem->setText(m_rowData[row].age);
break;
case 2:
pTableWidgetItemItem->setText(m_rowData[row].sex);
break;
case 3:
pTableWidgetItemItem->setText(m_rowData[row].number);
break;
default:
break;
}
m_pTableWidget->setItem(row, col, pTableWidgetItemItem);
}
}
}
void QCustomWidget::InitTableDelegate()
{
m_pTableWidget->setItemDelegateForColumn(1, new LineEditDelegate(m_pTableWidget));
m_pTableWidget->setItemDelegateForColumn(2, new ComboBoxDelegate(m_pTableWidget));
}
void QCustomWidget::CreateWidgets()
{
// 创建按键
m_pPushButton = new QPushButton(QString::fromLocal8Bit("调试"), this);
m_pPushButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
// 创建QTableWidget
m_pTableWidget = new QMyTableWidget(0, 4, this);
// 设置表头
QStringList labels;
labels << QString::fromLocal8Bit("姓名");
labels << QString::fromLocal8Bit("年龄");
labels << QString::fromLocal8Bit("性别");
labels << QString::fromLocal8Bit("手机号");
m_pTableWidget->setHorizontalHeaderLabels(labels);
}
void QCustomWidget::CreateLayout()
{
QVBoxLayout *pLayout = new QVBoxLayout();
pLayout->addWidget(m_pTableWidget);
pLayout->addWidget(m_pPushButton);
setLayout(pLayout);
}
void QCustomWidget::OnCellChanged(int row, int column)
{
qDebug() << "CellChanged row = " << row << ", column = " << column;
}
void QCustomWidget::OnCellDoubleClicked(int row, int column)
{
qDebug() << "CellDoubleClicked row = " << row << ", column = " << column;
}
到了这里,关于Qt编程基础 | 第六章-窗体 | 6.3、QTableWidget的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!