QTableView

阅读数:38 评论数:0

跳转到新版页面

分类

C/C++

正文

一、概述

QTableView 是 Qt 中一个功能强大的表格显示控件,它依赖于模型-视图-委托(Model-View-Delegate)架构。QTableView 提供了灵活的数据展示和编辑功能,适用于复杂的数据表格展示需求。

二、基本使用步骤

1、创建并配置 QTableView

2、创建并配置数据模型(如 QStandardItemModel)。

3、将数据模型设置为 QTableView 的模型。

4、(可选)自定义视图外观和行为。

示例

#include <QApplication>
#include <QTableView>
#include <QStandardItemModel>

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);

    // 创建 QTableView 实例
    QTableView tableView;
    tableView.setWindowTitle("QTableView Example");

    // 创建模型
    QStandardItemModel model(5, 3); // 5行3列
    model.setHorizontalHeaderLabels({"Column 1", "Column 2", "Column 3"});

    // 填充数据
    for (int row = 0; row < 5; ++row) {
        for (int col = 0; col < 3; ++col) {
            QStandardItem *item = new QStandardItem(QString("Item %1,%2").arg(row).arg(col));
            model.setItem(row, col, item);
        }
    }

    // 将模型设置为 QTableView 的模型
    tableView.setModel(&model);

    // 显示 QTableView
    tableView.show();

    return app.exec();
}

三、自定义外观

1、设置列宽

tableView.setColumnWidth(0, 150); // 设置第一列宽度为150像素

2、设置选择模式

tableView.setSelectionMode(QAbstractItemView::SingleSelection); // 仅允许单选
tableView.setSelectionBehavior(QAbstractItemView::SelectRows);  // 选择整行
tableWidget.setSelectionMode(QTableWidget::MultiSelection); // 多行选择

设置行选中的背景色和字体颜色

    // 设置选中行的背景色和字体颜色
    tableView.setStyleSheet("QTableView::item:selected { background-color: #3399FF; color: white; }");

3、隐藏网格线

tableView.setShowGrid(false);

4、设置排序功能

tableView.setSortingEnabled(true);

5、自定义委托

你可以自定义委托来控制单元格的显示和编辑行为。以下是一个简单的示例,使用 QStyledItemDelegate 来自定义单元格的显示:

class CustomDelegate : public QStyledItemDelegate {
public:
    CustomDelegate(QObject *parent = nullptr) : QStyledItemDelegate(parent) {}

    void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override {
        // 自定义绘制代码
        painter->save();
        painter->setPen(Qt::blue);
        painter->drawText(option.rect, Qt::AlignCenter, index.data().toString());
        painter->restore();
    }
};

// 使用自定义委托
tableView.setItemDelegate(new CustomDelegate(&tableView));

6、隐藏行号(如果不需要默认的行号)

tableView.verticalHeader()->setVisible(false);  // 隐藏默认行号

7、设置表头样式

tableView.setStyleSheet(
        "QHeaderView::section {"
        "   background-color: #4CAF50;"   // 表头背景色
        "   color: white;"                // 表头字体颜色
        "   font-size: 14px;"             // 表头字体大小
        "   font-weight: bold;"           // 表头字体加粗
        "   height: 30px;"                // 表头高度
        "   border: none;"                // 表头去掉边框
        "}"
        "QTableView::item:selected {"
        "   background-color: #FF9800;"   // 选中行背景色
        "   color: white;"                // 选中行字体颜色
        "}"
    );

8、默认选中第一行

// 设置整行选择
    tableView.setSelectionBehavior(QTableView::SelectRows);

    // 设置单行选择模式
    tableView.setSelectionMode(QTableView::SingleSelection);

    // 默认选中第一行
    QModelIndex firstIndex = model.index(0, 0);  // 获取第一行的第一个单元格的索引
    tableView.setCurrentIndex(firstIndex);       // 设置当前选中的索引
    tableView.selectRow(0);          

四、QStandardItemModel

QStandardItemModel 是一种数据模型,用于存储和管理二维表格数据。与许多其他 Qt 对象不同,QStandardItemModel 的构造函数不需要指定父对象(parent)。这是因为数据模型通常由视图(如 QTableViewQTreeView 等)持有,而视图本身会负责管理模型的生命周期。

void loadModelFromFile(QStandardItemModel *model, const QString &fileName) {
    QFile file(fileName);
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
        qWarning("Cannot open file for reading");
        return;
    }

    QTextStream in(&file);
    bool isFirstLine = true;

    while (!in.atEnd()) {
        QString line = in.readLine();
        QStringList fields = line.split(',');

        if (isFirstLine) {
            // 设置表头
            model->setHorizontalHeaderLabels(fields);
            isFirstLine = false;
        } else {
            // 添加数据行
            QList<QStandardItem *> items;
            for (const QString &field : fields) {
                items.append(new QStandardItem(field.trimmed()));
            }
            model->appendRow(items);
        }
    }

    file.close();
}
#include <QApplication>
#include <QTableView>
#include <QStandardItemModel>
#include <QFile>
#include <QTextStream>
#include <QDebug>

void saveModelToFile(QStandardItemModel *model, const QString &fileName) {
    QFile file(fileName);
    if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
        qWarning("Cannot open file for writing");
        return;
    }

    QTextStream out(&file);

    // 写入表头
    QStringList headerLabels;
    for (int col = 0; col < model->columnCount(); ++col) {
        headerLabels << model->headerData(col, Qt::Horizontal).toString();
    }
    out << headerLabels.join(",") << "\n";

    // 写入数据行
    for (int row = 0; row < model->rowCount(); ++row) {
        QStringList rowValues;
        for (int col = 0; col < model->columnCount(); ++col) {
            QStandardItem *item = model->item(row, col);
            if (item) {
                rowValues << item->text();
            } else {
                rowValues << "";
            }
        }
        out << rowValues.join(",") << "\n";
    }

    file.close();
}

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);

    // 创建 QTableView 和 QStandardItemModel
    QTableView tableView;
    QStandardItemModel model(5, 3); // 5 行 3 列

    // 填充一些示例数据
    for (int row = 0; row < 5; ++row) {
        for (int col = 0; col < 3; ++col) {
            QStandardItem *item = new QStandardItem(QString("Item %1,%2").arg(row).arg(col));
            model.setItem(row, col, item);
        }
    }

    tableView.setModel(&model);
    tableView.show();

    // 保存模型数据到文件
    QString fileName = "output.csv"; // 请替换为你的文件路径
    saveModelToFile(&model, fileName);

    return app.exec();
}

五、实现搜索功能

QTableView 中实现搜索功能可以通过过滤模型(如 QSortFilterProxyModel)来实现。QSortFilterProxyModel 可以过滤和排序数据,并将结果显示在 QTableView 中。

#include <QApplication>
#include <QTableView>
#include <QStandardItemModel>
#include <QSortFilterProxyModel>
#include <QLineEdit>
#include <QVBoxLayout>
#include <QWidget>
#include <QHeaderView>

class MainWindow : public QWidget {
    Q_OBJECT
public:
    MainWindow(QWidget *parent = nullptr) : QWidget(parent) {
        QVBoxLayout *layout = new QVBoxLayout(this);

        // 创建 QTableView 和 QStandardItemModel
        QTableView *tableView = new QTableView(this);
        QStandardItemModel *model = new QStandardItemModel(5, 4, this); // 5 行 4 列

        // 填充一些示例数据
        for (int row = 0; row < 5; ++row) {
            for (int col = 0; col < 4; ++col) {
                QStandardItem *item = new QStandardItem(QString("Item %1,%2").arg(row).arg(col));
                model->setItem(row, col, item);
            }
        }

        // 创建 QSortFilterProxyModel
        QSortFilterProxyModel *proxyModel = new QSortFilterProxyModel(this);
        proxyModel->setSourceModel(model);
        proxyModel->setFilterKeyColumn(-1); // -1 表示所有列都进行过滤

        tableView->setModel(proxyModel);

        // 创建 QLineEdit 用于输入搜索关键字
        QLineEdit *searchLineEdit = new QLineEdit(this);
        searchLineEdit->setPlaceholderText("Search...");

        // 连接 QLineEdit 的文本变化信号到过滤模型的过滤器
        connect(searchLineEdit, &QLineEdit::textChanged, proxyModel, &QSortFilterProxyModel::setFilterWildcard);

        layout->addWidget(searchLineEdit);
        layout->addWidget(tableView);

        setLayout(layout);
        setWindowTitle("QTableView Search Example");
        resize(600, 400);
    }
};

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);

    MainWindow mainWindow;
    mainWindow.show();

    return app.exec();
}

#include "main.moc"

六、最后一列为按钮列

#include <QStyledItemDelegate>
#include <QApplication>
#include <QMouseEvent>
#include <QPainter>

class MultiButtonDelegate : public QStyledItemDelegate {
    Q_OBJECT
public:
    MultiButtonDelegate(QObject *parent = nullptr) : QStyledItemDelegate(parent) {}

    void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override {
        if (index.column() == index.model()->columnCount() - 1) {
            int buttonWidth = option.rect.width() / 3;
            QStyleOptionButton buttonOption1;
            buttonOption1.rect = option.rect.adjusted(0, 0, -2 * buttonWidth, 0);
            buttonOption1.text = "Button 1";
            buttonOption1.state = QStyle::State_Enabled;

            QStyleOptionButton buttonOption2;
            buttonOption2.rect = option.rect.adjusted(buttonWidth, 0, -buttonWidth, 0);
            buttonOption2.text = "Button 2";
            buttonOption2.state = QStyle::State_Enabled;

            QStyleOptionButton buttonOption3;
            buttonOption3.rect = option.rect.adjusted(2 * buttonWidth, 0, 0, 0);
            buttonOption3.text = "Button 3";
            buttonOption3.state = QStyle::State_Enabled;

            QApplication::style()->drawControl(QStyle::CE_PushButton, &buttonOption1, painter);
            QApplication::style()->drawControl(QStyle::CE_PushButton, &buttonOption2, painter);
            QApplication::style()->drawControl(QStyle::CE_PushButton, &buttonOption3, painter);
        } else {
            QStyledItemDelegate::paint(painter, option, index);
        }
    }

    bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index) override {
        if (event->type() == QEvent::MouseButtonPress) {
            QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
            if (index.column() == index.model()->columnCount() - 1) {
                int buttonWidth = option.rect.width() / 3;
                QRect buttonRect1 = option.rect.adjusted(0, 0, -2 * buttonWidth, 0);
                QRect buttonRect2 = option.rect.adjusted(buttonWidth, 0, -buttonWidth, 0);
                QRect buttonRect3 = option.rect.adjusted(2 * buttonWidth, 0, 0, 0);

                if (buttonRect1.contains(mouseEvent->pos())) {
                    emit button1Clicked(index);
                } else if (buttonRect2.contains(mouseEvent->pos())) {
                    emit button2Clicked(index);
                } else if (buttonRect3.contains(mouseEvent->pos())) {
                    emit button3Clicked(index);
                }
            }
        }
        return QStyledItemDelegate::editorEvent(event, model, option, index);
    }

signals:
    void button1Clicked(const QModelIndex &index) const;
    void button2Clicked(const QModelIndex &index) const;
    void button3Clicked(const QModelIndex &index) const;
};



相关推荐

一、概述 QT是一个跨平台的C++库,主要用来开发图形界面(GUI)程序,它支持多种操作系统 ,如Windows、Linux、Android、ios、gnx、vxworks。 官网:https://w

一、预览 通过窗体-预览 或者 ctrl+R打开预览。 可以使用不同的内置风格、新式表、设备皮肤进行预览。在应用程序可以通过调用QApplication::setStyleSheet()来加载样式表实

代码编辑: Ctrl + Space: 激活代码补全 Ctrl + /: 注释/取消注释当前行或选定代码 Ctrl + I: 自动缩进选定代码 Ctrl + Shift + U: 转换选定文本为大写

在 Qt 中,输出变量值通常是用于调试目的,你可以使用多种方法来打印或显示变量的值。以下是一些常见的方法: 1、使用 qDebug: qDebug 是 Qt 中用于输出调试信息的宏。它可以将输出发送到

在 Qt 中全局加载一个 TTF 字体文件并使用它,你可以在程序初始化时期,比如在 main 函数中加载字体。以下是加载全局字体的步骤: 加载字体文件:使用 QFontDatabase::addAp

一、对于窗口 (QMainWindow, QDialog, 等): 1、move() 方法: 使用 move() 方法可以将窗口移动到屏幕上的指定位置。 QMainWindow *window = n

Qt框架中使用new关键字创建的对象通常需要手动释放,但是Qt提供了一种父子关系机制,可以自动管理对象的内存。当你使用new创建一个对象并将其分配给一个父QObject时,这个对象将会在父对象被销毁时

在Qt中,border-radius 在样式表中不会对顶层窗口生效。顶层窗口是指没有父窗口的窗口,通常是您的应用程序的主窗口或者独立的弹出窗口。由于安全性和平台兼容性的原因,很多样式表中的属性在顶层窗

在Qt中,connect函数用于连接信号和槽。从Qt 5开始,你可以使用C++11的lambda表达式作为槽函数,这样可以使你的代码更加简洁,尤其是当你想要对信号进行一些简单的处理时,而不想去定义一个

1. 定义全局常量 全局常量可以在一个头文件中使用 const 关键字或 #define 预处理器来定义: // constants.h #ifndef CONSTANTS_H #define CO