目前有一个项目需要定义自己的显示方式,通过搜索和查询官方文档,了解到使用QT的Model/View模式,通过继承QT自带的类可以实现想要的效果;
因此首先在QT设计师界面添加一个QTableView,并根据需要修改属性
;class customDatastructure
{
private:
bool isDownload;
QString name;
long id;
double allSize;
public:
double processScale = 0.0;
double transferSpeed = 0;
double curSize = 0;
bool isFinished = false;
bool isTransmitting = false;
public:
customDatastructure();
customDatastructure(bool isDownload, long id = 0, QString name = "", double allSize = 0);
QString objName() const;
QString objSize() const;
QString objProcSize() const;
QString objTransSpeed() const;
double objTransScale() const;
bool objIsDownload() const;
void setCurSize(double size);
void appendCurSize(double size);
void setFinished(bool is_finish);
void setTransmitting(bool is_trans);
};
#ifndef CUSTOMTABLEVIEW_H
#define CUSTOMTABLEVIEW_H
#include
#include
#include
#include "customdatastructure.h"
class customTableView : public QAbstractTableModel
{
Q_OBJECT
public: // 默认建立后自带函数
explicit customTableView(QObject* parent = nullptr);
// Header:
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
// Basic functionality:
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;
public: // 新增函数
// 数据类型,用于标识显示哪一个数据
enum
{
NameRole = 0,
InfoRole_1,
InfoRole_2,
InfoRole_3,
OperatorRole_1,
OperatorRole_2,
OperatorRole_3,
};
// 重写析构函数
~customTableView() override;
// 添加数据函数
void addData(customDatastructure*);
//
Qt::ItemFlags flags(const QModelIndex& index) const override;
private:
// 要显示的数据List
QList<customDatastructure*> m_datum;
};
#endif // CUSTOMTABLEVIEW_H
#include "customtableview.h"
customTableView::customTableView(QObject* parent)
: QAbstractTableModel(parent)
{
}
QVariant customTableView::headerData(int section, Qt::Orientation orientation, int role) const
{
// FIXME: Implement me!
if (role == Qt::SizeHintRole)
return QSize(0, 0);
return QVariant();
}
int customTableView::rowCount(const QModelIndex& parent) const
{
if (parent.isValid())
return 0;
// FIXME: Implement me!
return m_datum.count();
}
int customTableView::columnCount(const QModelIndex& parent) const
{
if (parent.isValid())
return 0;
// FIXME: Implement me!
return 7; // 返回列的个数,这里与头文件定义的枚举体类型个数一致
}
QVariant customTableView::data(const QModelIndex& index, int role) const
{
if (!index.isValid() || index.row() > m_datum.count())
{
return QVariant();
}
int nColumn = index.column();
switch(role) // 返回的数据类型
{
case Qt::FontRole: // 6
return QVariant();
case Qt::TextAlignmentRole: // 7
return QVariant();
case Qt::TextColorRole: // 9
return QColor(Qt::black);
case Qt::CheckStateRole: // 10
return QVariant();
case Qt::DecorationRole: // 1
return QVariant();
case Qt::ToolTipRole:
{
switch(nColumn)
{
case NameRole: // 0 名称
{
return tr("文件名称");
}
break;
case InfoRole_1: // 1 [已下载大小/]总大小
{
if(m_datum[index.row()]->isFinished)
return tr("总大小");
else if(m_datum[index.row()]->objIsDownload())
return tr("已下载大小/总大小");
else
return tr("已上传大小/总大小");
}
break;
case InfoRole_2: // 2 [下载速度]
{
if(m_datum[index.row()]->isFinished)
return "";
else
return tr("下载速度");
}
break;
case InfoRole_3: // 3 下载进度
{
if(m_datum[index.row()]->isFinished)
if(m_datum[index.row()]->objIsDownload())
return tr("下载完成");
else
return tr("上传完成");
else
return tr("下载进度");
}
break;
case OperatorRole_1:// 4
{
if(m_datum[index.row()]->isFinished)
return tr("打开文件");
else if(m_datum[index.row()]->isTransmitting)
return tr("暂停");
else
return tr("开始");
}
break;
case OperatorRole_2:// 5
{
if(m_datum[index.row()]->isFinished)
return tr("打开所在文件夹");
else
return tr("删除");
}
break;
case OperatorRole_3:// 6
{
if(m_datum[index.row()]->isFinished)
return tr("删除");
else
return tr("打开所在文件夹");
}
break;
}
}
break;
case Qt::DisplayRole: // 0
{
switch(nColumn)
{
case NameRole: // 0 名称
{
return m_datum[index.row()]->objName();
}
break;
case InfoRole_1: // 1 [(]已下载大小/]总大小
{
if(m_datum[index.row()]->isFinished)
return m_datum[index.row()]->objSize();
else
return m_datum[index.row()]->objProcSize();
}
break;
case InfoRole_2: // 2 [下载速度]
{
if(m_datum[index.row()]->isFinished == false)
return m_datum[index.row()]->objTransSpeed();
}
break;
case InfoRole_3: // 3 下载进度
{
if(m_datum[index.row()]->isFinished == false)
return m_datum[index.row()]->objTransScale();
}
break;
case OperatorRole_1:// 4
{
}
break;
case OperatorRole_2:// 5
{
}
break;
case OperatorRole_3:// 6
{
}
break;
}
}
case Qt::BackgroundColorRole: // 8
return QVariant();
}
// FIXME: Implement me!
return QVariant();
}
customTableView::~customTableView()
{
for(auto d : m_datum)
delete(d);
}
void customTableView::addData(customDatastructure* dataObj) // 自定义添加函数类型,需要添加两段代码
{
beginResetModel();
m_datum.push_back(dataObj);
endResetModel();
}
Qt::ItemFlags customTableView::flags(const QModelIndex& index) const
{
if (!index.isValid())
return QAbstractItemModel::flags(index);
return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
}
#include
#include
class customItemDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
customItemDelegate(QObject* parent = nullptr);
void paint(QPainter* painter, const QStyleOptionViewItem& option,
const QModelIndex& index) const override;
QSize sizeHint(const QStyleOptionViewItem& option,
const QModelIndex& index) const override;
bool editorEvent(QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option,
const QModelIndex& index) override;
}
#ifndef CUSTOMITEMDELEGATE_H
#define CUSTOMITEMDELEGATE_H
#include
#include
#include
#include
#include
#include
#include
#include
#include "customtableview.h"
// 自定义Button属性
class ItemButton
{
public:
static const int posx = 15;
static const int poxy = 5;
static const int width = 20;
static const int height = width;
enum BUTTON_STATUS
{
NONE, HOVER, PRESSED, RELEASED
};
private:
QString buttonIconName;
QScopedPointer<QPushButton> buttonWidget;
BUTTON_STATUS buttonStatus = NONE;
public:
ItemButton(QString iconName);
void paintButton(QPainter* painter, const QStyleOptionViewItem& option, const QPoint& pos );
void inline setStatusNone();
void inline setStatusHover();
void inline setStatusPressed();
void inline setStatusReleased();
static bool withinButtonRegion(const QPoint, const QStyleOptionViewItem& option);
};
// 自定义ProgressBar属性
class ItemProgressBar
{
public:
static const int left = 2;
static const int right = left;
static const int top = 6;
static const int bottom = top;
private:
QScopedPointer<QProgressBar> progressBarWidget;
public:
ItemProgressBar();
void paintQProgressBar(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index );
};
class customItemDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
customItemDelegate(QObject* parent = nullptr);
void paint(QPainter* painter, const QStyleOptionViewItem& option,
const QModelIndex& index) const override;
QSize sizeHint(const QStyleOptionViewItem& option,
const QModelIndex& index) const override;
bool editorEvent(QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option,
const QModelIndex& index) override;
private:
QScopedPointer<ItemButton> itemButton1;
QScopedPointer<ItemButton> itemButton2;
QScopedPointer<ItemButton> itemButton3;
QScopedPointer<ItemProgressBar> itemProgressBar;
QPoint mousePos;
signals:
void signals1( const QModelIndex& index);
void signals2( const QModelIndex& index);
void signals3( const QModelIndex& index);
public slots:
void showMessage1( const QModelIndex& index);
void showMessage2( const QModelIndex& index);
void showMessage3( const QModelIndex& index);
};
#endif // CUSTOMITEMDELEGATE_H
#include "customitemdelegate.h"
customItemDelegate::customItemDelegate(QObject* parent): QStyledItemDelegate(parent)
, itemButton1(new ItemButton("play"))
, itemButton2(new ItemButton("cancle"))
, itemButton3(new ItemButton("folder"))
, itemProgressBar(new ItemProgressBar())
{
connect(this, SIGNAL(signals1( const QModelIndex&)), this, SLOT(showMessage1( const QModelIndex&)));
connect(this, SIGNAL(signals2( const QModelIndex&)), this, SLOT(showMessage2( const QModelIndex&)));
connect(this, SIGNAL(signals3( const QModelIndex&)), this, SLOT(showMessage3( const QModelIndex&)));
}
void customItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
QStyleOptionViewItem viewOption(option);
initStyleOption(&viewOption, index);
if (option.state.testFlag(QStyle::State_HasFocus))
viewOption.state = viewOption.state ^ QStyle::State_HasFocus;
switch(index.column())
{
case customTableView::NameRole: // 0 名称
{
}
break;
case customTableView::InfoRole_1: // 1 [已下载大小/]总大小
{
viewOption.displayAlignment = Qt::AlignCenter;
}
break;
case customTableView::InfoRole_2: // 2 [下载速度]
{
viewOption.displayAlignment = Qt::AlignCenter;
}
break;
case customTableView::InfoRole_3: // 3 下载进度
{
itemProgressBar->paintQProgressBar(painter, option, index);
viewOption.text = "";
}
break;
case customTableView::OperatorRole_1:// 4
{
itemButton1->paintButton(painter, option, mousePos);
}
break;
case customTableView::OperatorRole_2:// 5
{
itemButton2->paintButton(painter, option, mousePos);
}
break;
case customTableView::OperatorRole_3:// 6
{
itemButton3->paintButton(painter, option, mousePos);
}
break;
default:
{
}
}
QStyledItemDelegate::paint(painter, viewOption, index);
}
QSize customItemDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const
{
switch(index.column())
{
case customTableView::NameRole: // 0 名称
case customTableView::InfoRole_1: // 1 [(]已下载大小/]总大小
case customTableView::InfoRole_2: // 2 [下载速度]
{
return QSize(100, 30);
}
break;
case customTableView::InfoRole_3: // 3 下载进度
{
return QSize(200, 30);
}
break;
case customTableView::OperatorRole_1:// 4
case customTableView::OperatorRole_2:// 5
case customTableView::OperatorRole_3:// 6
{
return QSize(50, 30);
}
break;
}
return QStyledItemDelegate::sizeHint(option, index);
}
bool customItemDelegate::editorEvent(QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index)
{
QMouseEvent* pEvent = static_cast<QMouseEvent*> (event);
mousePos = pEvent->pos();
if (ItemButton::withinButtonRegion(mousePos, option))
{
switch (event->type())
{
case QEvent::MouseMove:
{
switch(index.column())
{
case customTableView::OperatorRole_1:// 4
{
itemButton1->setStatusHover();
}
break;
case customTableView::OperatorRole_2:// 5
{
itemButton2->setStatusHover();
}
break;
case customTableView::OperatorRole_3:// 6
{
itemButton3->setStatusHover();
}
break;
}
return true;
}
break;
case QEvent::MouseButtonPress:
{
switch(index.column())
{
case customTableView::OperatorRole_1:// 4
{
itemButton1->setStatusPressed();
}
break;
case customTableView::OperatorRole_2:// 5
{
itemButton2->setStatusPressed();
}
break;
case customTableView::OperatorRole_3:// 6
{
itemButton3->setStatusPressed();
}
break;
}
return false;
}
break;
case QEvent::MouseButtonRelease:
{
switch(index.column())
{
case customTableView::OperatorRole_1:// 4
{
itemButton1->setStatusReleased();
emit signals1(index);
}
break;
case customTableView::OperatorRole_2:// 5
{
itemButton2->setStatusReleased();
emit signals2(index);
}
break;
case customTableView::OperatorRole_3:// 6
{
itemButton3->setStatusReleased();
emit signals3(index);
}
break;
}
return true;
}
break;
default:
{
switch(index.column())
{
case customTableView::OperatorRole_1:// 4
{
itemButton1->setStatusNone();
}
break;
case customTableView::OperatorRole_2:// 5
{
itemButton2->setStatusNone();
}
break;
case customTableView::OperatorRole_3:// 6
{
itemButton3->setStatusNone();
}
break;
}
QStyledItemDelegate::editorEvent(event, model, option, index);
return false;
}
break;
}
}
else
{
switch(index.column())
{
case customTableView::OperatorRole_1:// 4
{
itemButton1->setStatusNone();
}
break;
case customTableView::OperatorRole_2:// 5
{
itemButton2->setStatusNone();
}
break;
case customTableView::OperatorRole_3:// 6
{
itemButton3->setStatusNone();
}
break;
}
return QStyledItemDelegate::editorEvent(event, model, option, index);
}
return true;
}
void customItemDelegate::showMessage1(const QModelIndex& index)
{
qDebug() << "showMessage1 --" << index;
QMessageBox::information(NULL, "触发消息", QString("showMessage1 开启"));
}
void customItemDelegate::showMessage2(const QModelIndex& index)
{
qDebug() << "showMessage2 --" << index;
QMessageBox::information(NULL, "触发消息", QString("showMessage2 删除"));
}
void customItemDelegate::showMessage3(const QModelIndex& index)
{
qDebug() << "showMessage3 --" << index;
QMessageBox::information(NULL, "触发消息", QString("showMessage3 打开"));
}
ItemButton::ItemButton(QString iconName): buttonWidget(new QPushButton())
{
buttonIconName = iconName;
buttonWidget->setStyleSheet("\
QPushButton{\
border: none;\
background-color: transparent;\
image: url(:/icon/icon/" + iconName + ".png);\
}\
QPushButton:hover {\
image: url(:/icon/icon/" + iconName + "-hover.png);\
}\
QPushButton:pressed {\
image: url(:/icon/icon/" + iconName + "-pressed.png);\
}\
");
}
void ItemButton::paintButton(QPainter* painter, const QStyleOptionViewItem& option, const QPoint& pos)
{
QStyleOptionButton buttonOption;
buttonOption.rect = QRect(option.rect.x() + posx, option.rect.y() + poxy, width, height);
buttonOption.state = QStyle::State_Enabled;
if(buttonOption.rect.contains(pos))
{
if(buttonStatus == BUTTON_STATUS::HOVER)
buttonOption.state |= QStyle::State_MouseOver;
else if(buttonStatus == BUTTON_STATUS::PRESSED)
buttonOption.state |= QStyle::State_Sunken;
}
// 根据需要选择使用的绘制函数
// QApplication::style()->drawControl(QStyle::CE_PushButton, &buttonOption, painter, buttonWidget.data());
// option.widget->style()->drawControl(QStyle::CE_PushButton, &buttonOption, painter, buttonWidget.data());
buttonWidget.data()->style()->drawControl(QStyle::CE_PushButton, &buttonOption, painter, buttonWidget.data());
}
void ItemButton::setStatusNone()
{
buttonStatus = NONE;
}
void ItemButton::setStatusHover()
{
buttonStatus = HOVER;
}
void ItemButton::setStatusPressed()
{
buttonStatus = PRESSED;
}
void ItemButton::setStatusReleased()
{
buttonStatus = RELEASED;
}
bool ItemButton::withinButtonRegion(const QPoint pos, const QStyleOptionViewItem& option)
{
QStyleOptionButton buttonOption;
buttonOption.rect = QRect(option.rect.x() + posx, option.rect.y() + poxy, width, height);
return buttonOption.rect.contains(pos);
}
ItemProgressBar::ItemProgressBar(): progressBarWidget(new QProgressBar())
{
progressBarWidget->setStyleSheet("\
QProgressBar{\
border: 2px solid #347;\
border-radius:4px;\
}\
QProgressBar::chunk {\
background-color: #77AAEE;\
}\
");
}
void ItemProgressBar::paintQProgressBar(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index)
{
int progress = index.data().toDouble() * 100;
QStyleOptionProgressBar progressBarOption;
progressBarOption.initFrom(option.widget);
progressBarOption.rect = QRect(option.rect.x() + left, option.rect.y() + top, option.rect.width() - left - right, option.rect.height() - top - bottom);
// progressBarOption.rect = option.rect;
progressBarOption.minimum = 0;
progressBarOption.maximum = 100;
progressBarOption.progress = progress;
progressBarOption.text = QString::number(progress) + "%";
progressBarOption.textVisible = true;
progressBarOption.textAlignment = Qt::AlignHCenter | Qt::AlignVCenter;
// 根据需要选择使用的绘制函数
// QApplication::style()->drawControl(QStyle::CE_ProgressBar, &progressBarOption, painter, progressBarWidget.data());
// option.widget->style()->drawControl(QStyle::CE_ProgressBar, &progressBarOption, painter, progressBarWidget.data());
progressBarWidget.data()->style()->drawControl(QStyle::CE_ProgressBar, &progressBarOption, painter, progressBarWidget.data());
}
MainWindow::MainWindow(QWidget* parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
table_view = new customTableView(this);
ui->tableView->setModel(table_view);
customItemDelegate* processingDelegate = new customItemDelegate(this);
ui->tableView->setItemDelegate(processingDelegate);
ui->tableView->setMouseTracking(true);
// 测试
customDatastructure* test = new customDatastructure(true, 1, "hello1.jpg", 100);
test->setCurSize(39);
table_view->addData(test);
table_view->addData(new customDatastructure(true, 2, "hello2.jpg", 150));
ui->tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Fixed);
ui->tableView->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch);
ui->tableView->resizeColumnsToContents();
}