最近对某位老哥的《Qt 自定义委托--实现批量升级UI》进行了学习以及一些补充
-
Qt模型视图采用类MVC框架,那什么是MVC框架?
-
M--模型:负责组织数据
-
V--试图:负责显示数据
-
C--控制:负责用户输入
-
模型视图中的委托:①委托是视图中处理用户输入的部件。②视图可以设置委托对象用于用户输入。③委托对象负责创建和显示用户输入上下文
整体实现结果:
UI界面的配置:
其中整体控件布局 垂直layout中,且水平策略:Expanding 垂直策略:Expanding, 其他控件最小长度,最小高度设置下,这样在拉伸窗口时整体控件大小可均匀的拉伸。
源码:
/*************************mainwindow.h**********************************/
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void on_allCheckBox_clicked();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
/********************************mainwindow.cpp***************************/
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "qricetableview.h"
#include "QTimer"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
setWindowTitle(tr("水火汪"));
struct QRiceTableView::tableItemInfo info;
info.name = tr("RiceChen");
info.age = tr("18");
info.work = tr("程序员");
ui->tableView->QRiceTableAddItem(0, &info);
info.name = tr("米饭");
info.age = tr("20");
info.work = tr("公务员");
ui->tableView->QRiceTableAddItem(1, &info);
QTimer * timer = new QTimer(this);
connect(timer,&QTimer::timeout,[=](){
static int Progress1 = 0;
static int Progress2 = 0;
ui->tableView->QRiceTableSetProgress(0, Progress1);
ui->tableView->QRiceTableSetProgress(1, Progress2);
Progress1 += 1;
Progress2 += 2;
if(Progress1 > 100)
{
Progress1 = 0;
}
if(Progress2 > 100)
{
Progress2 = 0;
}
});
timer->start(1000);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_allCheckBox_clicked()
{
for(int row = 0; row < ui->tableView->QRiceTableGetRow(); row++)
{
if(ui->allCheckBox->checkState() == Qt::Checked)
{
ui->tableView->QRiceTableSetSelect(row, true);
}
else
{
ui->tableView->QRiceTableSetSelect(row, false);
}
}
}
/******************************qricebuttondelegate.h**********************/
#ifndef QRICEBUTTONDELEGATE_H
#define QRICEBUTTONDELEGATE_H
#include <QItemDelegate>
class QRiceButtonDelegate : public QItemDelegate
{
Q_OBJECT
public:
explicit QRiceButtonDelegate(QObject *parent = nullptr);
~QRiceButtonDelegate();
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index);
signals:
private:
void showMsg(QString str);
private:
typedef QMap<QModelIndex, QStyleOptionButton* > collButtons;
collButtons buttonDelegate;
};
#endif // QRICEBUTTONDELEGATE_H
/*************************************qricebuttondelegate.cpp**************/
#include "qricebuttondelegate.h"
#include <qevent.h>
#include <QPainter>
#include <QApplication>
#include <QMessageBox>
QRiceButtonDelegate::QRiceButtonDelegate(QObject *parent)
: QItemDelegate(parent)
{
}
QRiceButtonDelegate::~QRiceButtonDelegate()
{
}
void QRiceButtonDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
QStyleOptionButton *buttonStyle = buttonDelegate.value(index);
if(!buttonStyle)
{
buttonStyle = new QStyleOptionButton(); // 创建按钮项样式
buttonStyle->text = "Update"; // 设置按钮中显示的内容
buttonStyle->state |= QStyle::State_Enabled; // 设置按钮中的状态
(const_cast<QRiceButtonDelegate *>(this))->buttonDelegate.insert(index, buttonStyle);
}
buttonStyle->rect = option.rect.adjusted(4, 4, -4, -4); //设置按钮的大小
painter->save();
if (option.state & QStyle::State_Selected) {
painter->fillRect(option.rect, option.palette.highlight());
}
painter->restore();
QApplication::style()->drawControl(QStyle::CE_PushButton, buttonStyle, painter); //绘制
}
bool QRiceButtonDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index)
{
Q_UNUSED(model);
Q_UNUSED(option);
QMouseEvent *mouseEvent = (QMouseEvent *)event;
if(event->type() == QEvent::MouseButtonPress) // 按钮按下,设置按钮的状态
{
if(buttonDelegate.contains(index))
{
QStyleOptionButton *buttonStyle = buttonDelegate.value(index);
if(buttonStyle->rect.contains(mouseEvent->x(), mouseEvent->y()))
{
buttonStyle->state |= QStyle::State_Sunken;
}
}
}
if(event->type() == QEvent::MouseButtonRelease) // 按钮松开,设置按钮的状态
{
if(buttonDelegate.contains(index))
{
QStyleOptionButton *buttonStyle = buttonDelegate.value(index);
if(buttonStyle->rect.contains(mouseEvent->x(), mouseEvent->y()))
{
buttonStyle->state &= (~QStyle::State_Sunken);
showMsg(tr("btn1 column %1").arg(index.row())); // 松开弹出消息框,显示对应行号
}
}
}
return true;
}
void QRiceButtonDelegate::showMsg(QString str)
{
QMessageBox msg;
msg.setText(str);
msg.exec();
}
#ifndef QRICECHECKBOXDELEGATE_H
#define QRICECHECKBOXDELEGATE_H
#include <QItemDelegate>
class QRiceCheckBoxDelegate : public QItemDelegate
{
Q_OBJECT
public:
explicit QRiceCheckBoxDelegate(QObject *parent = nullptr);
~QRiceCheckBoxDelegate();
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index);
signals:
};
#endif // QRICECHECKBOXDELEGATE_H
#include "qricecheckboxdelegate.h"
#include <QApplication>
#include <QMouseEvent>
#include <QPainter>
#include <QStyleOption>
#include <QDebug>
QRiceCheckBoxDelegate::QRiceCheckBoxDelegate(QObject *parent)
: QItemDelegate(parent)
{
}
QRiceCheckBoxDelegate::~QRiceCheckBoxDelegate()
{
}
void QRiceCheckBoxDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
if(QVariant::Bool == index.data(Qt::DisplayRole).type()) //如果数据类型为bool型,才绘制单选宽
{
QStyleOptionButton checkBox;
checkBox.state = index.data().toBool() ? QStyle::State_On : QStyle::State_Off; //绘制后的默认状态
checkBox.state |= QStyle::State_Enabled;
checkBox.rect = option.rect;
checkBox.rect.setX(option.rect.x() + option.rect.width()/2 - 6); //设置在表格中的显示位置
QApplication::style()->drawControl(QStyle::CE_CheckBox, &checkBox, painter); // 绘制
}
else
{
QItemDelegate::paint(painter, option, index);
}
}
bool QRiceCheckBoxDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index)
{
bool ret = true;
if(QVariant::Bool == index.data().type())
{
QMouseEvent* mouse = dynamic_cast<QMouseEvent*>(event);
if( (NULL != mouse) && (QEvent::MouseButtonPress == mouse->type()) && (option.rect.contains(mouse->pos())) )
{
model->setData(index, !index.data().toBool(), Qt::DisplayRole); // 更新模型数据
}
}
else
{
ret = QItemDelegate::editorEvent(event, model, option, index);
}
return ret;
}
#ifndef QRICEPROGRESSBARDELEGATE_H
#define QRICEPROGRESSBARDELEGATE_H
#include <QItemDelegate>
class QRiceProgressBarDelegate : public QItemDelegate
{
Q_OBJECT
public:
explicit QRiceProgressBarDelegate(QObject *parent = nullptr);
~QRiceProgressBarDelegate();
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index);
signals:
};
#endif // QRICEPROGRESSBARDELEGATE_H
#include "qriceprogressbardelegate.h"
#include <QApplication>
QRiceProgressBarDelegate::QRiceProgressBarDelegate(QObject *parent)
: QItemDelegate(parent)
{
}
QRiceProgressBarDelegate::~QRiceProgressBarDelegate()
{
}
void QRiceProgressBarDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
int progress = index.data(Qt::DisplayRole).toInt();
QStyleOptionProgressBar progressBar;
progressBar.minimum = 0; //设置进度条最小值
progressBar.maximum = 100; //设置进度条最大值
progressBar.progress = progress; //设置绘制后的数值
progressBar.rect = option.rect.adjusted(4, 4, -4, -4); //设置进度条的大小
progressBar.textVisible = true; //设置进度条显示数值
progressBar.textAlignment = Qt::AlignCenter; //设置进度条数值显示位置
progressBar.text = QString("%1%").arg(progress); //设置进度条数值显示
QApplication::style()->drawControl(QStyle::CE_ProgressBar, &progressBar, painter); // 绘制
}
bool QRiceProgressBarDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index)
{
bool ret = true;
if(QEvent::MouseButtonDblClick != event->type())
{
ret = QItemDelegate::editorEvent(event, model, option, index);
}
return ret;
}
#ifndef QRICETABLEVIEW_H
#define QRICETABLEVIEW_H
#include <QTableView>
#include <QStandardItemModel>
#include "qricecheckboxdelegate.h"
#include "qriceprogressbardelegate.h"
#include "qricebuttondelegate.h"
class QRiceTableView : public QTableView
{
Q_OBJECT
public:
struct tableItemInfo
{
QString name;
QString age;
QString work;
};
public:
explicit QRiceTableView(QWidget *parent = nullptr);
~QRiceTableView();
signals:
public:
int QRiceTableGetRow(void);
int QRiceTableGetColumn(void);
void QRiceTableAddItem(int row, struct tableItemInfo *info);
void QRiceTableSetProgress(int row, int Progress);
void QRiceTableSetSelect(int row, bool select);
bool QRiceTableGetSelect(int row);
QString QRiceTableGetString(int row, int column);
private:
QStandardItemModel *tableItemModel;
QRiceCheckBoxDelegate *tableCheckBoxDelegate;
QRiceProgressBarDelegate *tableProgressBarDelegate;
QRiceButtonDelegate *tableButtonDelegate;
};
#endif // QRICETABLEVIEW_H
#include "qricetableview.h"
#include <QObject>
#include <QTableView>
#include <QApplication>
#include <QHeaderView>
QRiceTableView::QRiceTableView(QWidget *parent)
: QTableView(parent)
{
horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
tableItemModel = new QStandardItemModel();
setModel(tableItemModel);
tableCheckBoxDelegate = new QRiceCheckBoxDelegate(this);
setItemDelegate(tableCheckBoxDelegate);
tableProgressBarDelegate = new QRiceProgressBarDelegate(this);
setItemDelegateForColumn(4, tableProgressBarDelegate);
tableButtonDelegate = new QRiceButtonDelegate(this);
setItemDelegateForColumn(5, tableButtonDelegate);
QStringList tableHeaders;
tableHeaders << tr("Select") <<tr("Name") << tr("Age") << tr("Work") << tr("Progress") << tr("Update");
tableItemModel->setHorizontalHeaderLabels(tableHeaders);
}
QRiceTableView::~QRiceTableView()
{
}
int QRiceTableView::QRiceTableGetRow(void)
{
return tableItemModel->rowCount();
}
int QRiceTableView::QRiceTableGetColumn(void)
{
return tableItemModel->columnCount();
}
void QRiceTableView::QRiceTableAddItem(int row, struct tableItemInfo *info)
{
QStandardItem* otaDeviceListStandardItem = tableItemModel->invisibleRootItem();
QStandardItem *checkBox = new QStandardItem();
QStandardItem *name = new QStandardItem();
QStandardItem *age = new QStandardItem();
QStandardItem *work = new QStandardItem();
checkBox->setData(false, Qt::DisplayRole);
name->setData(info->name, Qt::DisplayRole);
age->setData(info->age, Qt::DisplayRole);
work->setData(info->work, Qt::DisplayRole);
otaDeviceListStandardItem->setChild(row, 0, checkBox);
otaDeviceListStandardItem->setChild(row, 1, name);
otaDeviceListStandardItem->setChild(row, 2, age);
otaDeviceListStandardItem->setChild(row, 3, work);
}
void QRiceTableView::QRiceTableSetProgress(int row, int Progress)
{
if(row < tableItemModel->rowCount())
{
QModelIndex index = tableItemModel->index(row, 4);
tableItemModel->setData(index, Progress, Qt::DisplayRole);
}
}
void QRiceTableView::QRiceTableSetSelect(int row, bool select)
{
if(row < tableItemModel->rowCount())
{
QModelIndex index = tableItemModel->index(row, 0);
tableItemModel->setData(index, select, Qt::DisplayRole);
}
}
bool QRiceTableView::QRiceTableGetSelect(int row)
{
if(row < tableItemModel->rowCount())
{
QModelIndex index = tableItemModel->index(row, 0);
return index.data(Qt::DisplayRole).toBool();
}
return false;
}
QString QRiceTableView::QRiceTableGetString(int row, int column)
{
if(row < tableItemModel->rowCount()
&& column > 0 && column < (tableItemModel->columnCount() - 2))
{
QModelIndex index = tableItemModel->index(row, column);
return index.data(Qt::DisplayRole).toString();
}
return "";
}
整体代码结构:
其中QRiceTableView的类需要提升,在ui界面上tabview控件点击提升窗口部件
QtCreator:中文乱码解决:在pro文件增加下面一行。