首先继承QTableView 写一个TableView,这样时常带来一些方便
TableView.h
#ifndef TABLEVIEW_H
#define TABLEVIEW_H
#include <QTableView>
class TableView : public QTableView
{
Q_OBJECT
public:
TableView(QWidget* parent = nullptr);
TableView(const QString& left_top_text, QWidget* parent = nullptr);
QModelIndexList get_selected_idx_list() const;
QModelIndex get_last_selected_idx() const;
// int get_left_top_corner_widget_width() const;
// void set_corner_widget_width(const int& width);
signals:
// press ENTER add a space row
void signal_add_a_space_row(const QModelIndex& idx);
void signal_delete_selected_rows(const QModelIndexList& idx_list);
protected:
void keyPressEvent(QKeyEvent* event) override;
bool eventFilter(QObject* object, QEvent* event) override;
};
#endif // TABLEVIEW_H
TableView .cpp
#include "TableView.h"
#include <QKeyEvent>
#include <QHeaderView>
#include <QApplication>
#include <QStylePainter>
#include <QAbstractButton>
#include <QDebug>
TableView::TableView(QWidget* parent)
: QTableView(parent)
{
horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
setContextMenuPolicy(Qt::CustomContextMenu);
}
TableView::TableView(const QString& left_top_text, QWidget* parent)
: QTableView(parent)
{
horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
setContextMenuPolicy(Qt::CustomContextMenu);
QAbstractButton* btn = findChild<QAbstractButton*>();
if( btn )
{
btn->setText(left_top_text);
btn->installEventFilter(this);
QStyleOptionHeader opt;
opt.text = btn->text();
QSize size = btn->style()->sizeFromContents(QStyle::CT_HeaderSection, &opt, QSize(), btn).expandedTo(QApplication::globalStrut());
if( size.isValid() )
{
verticalHeader()->setMinimumWidth(size.width());
}
}
}
//int
//TableView::get_left_top_corner_widget_width() const
//{
// QAbstractButton* btn = findChild<QAbstractButton*>();
// qDebug() << __FILE__ << __LINE__ << " btn->rect().width() " << btn->rect().width();
// if( btn )
// {
// return btn->rect().width();
// }
// return 0;
//}
//void
//TableView::set_corner_widget_width(const int& width)
//{
// QAbstractButton* btn = findChild<QAbstractButton*>();
// if( btn )
// {
// btn->setMinimumWidth(width);
// }
//}
QModelIndexList
TableView::get_selected_idx_list() const
{
return selectionModel()->selectedIndexes();
}
QModelIndex
TableView::get_last_selected_idx() const
{
const QModelIndexList& idx_list = this->get_selected_idx_list();
return idx_list.isEmpty() ? QModelIndex() : idx_list.last();
}
void
TableView::keyPressEvent(QKeyEvent* event)
{
//qDebug() << __FILE__ << __LINE__ << " event = " << event;
const int& key = event->key();
if( Qt::Key_Enter == key || Qt::Key_Return == key )
{
const QModelIndex& idx = get_last_selected_idx();
emit signal_add_a_space_row( idx );
}
else if( Qt::Key_Delete == key || Qt::Key_Backspace == key )
{
const QModelIndexList& idx_list = this->get_selected_idx_list();
emit signal_delete_selected_rows(idx_list);
}
QTableView::keyPressEvent(event);
}
bool
TableView::eventFilter(QObject* object, QEvent* event)
{
if( event->type() == QEvent::Paint )
{
QAbstractButton* btn = qobject_cast<QAbstractButton*>(object);
if(btn)
{
QStyleOptionHeader opt;
opt.init(btn);
QStyle::State state = QStyle::State_None;
if( btn->isEnabled() )
{
state |= QStyle::State_Enabled;
}
else if( btn->isActiveWindow() )
{
state |= QStyle::State_Active;
}
else if( btn->isDown() )
{
state |= QStyle::State_Sunken;
}
opt.state = state;
opt.rect = btn->rect();
opt.text = btn->text();
opt.position = QStyleOptionHeader::OnlyOneSection;
opt.textAlignment = Qt::AlignCenter;
QStylePainter painter(btn);
painter.drawControl(QStyle::CE_Header, opt);
return true;
}
}
return false;
}
Model主要是组装数据的
GoodsModel.h
#ifndef GOODSMODEL_H
#define GOODSMODEL_H
#include <QAbstractTableModel>
class DBUtil;
class GoodsItem;
/**
*
*/
class GoodsModel : public QAbstractTableModel
{
Q_OBJECT
public:
GoodsModel(QObject* parent = 0);
~GoodsModel();
public:
void clear_all();
void refresh();
// const QModelIndex get_idx_from_mat_name(const QString& material_name);
int get_id_from_idx(const QModelIndex& idx) const;
void delete_line(const QModelIndex& idx);
public:
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
QModelIndex index(int row, int column = 0, const QModelIndex &parent = QModelIndex()) const;
int rowCount(const QModelIndex& parent = QModelIndex()) const;
int columnCount(const QModelIndex& parent = QModelIndex()) const;
//bool hasChildren(const QModelIndex &parent = QModelIndex()) const;//
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
Qt::ItemFlags flags(const QModelIndex& index) const;
// when click revalue need
bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole);
private:
void init_data();
private:
DBUtil* d_db_util;
private:
QStringList d_head_names;
QVector<GoodsItem*> d_items;
};
#endif // GOODSMODEL_H
GoodsModel.cpp
#include "GoodsModel.h"
#include "GoodsItem.h"
#include "database/DBUtil.h"
#include "database/table/GoodsTable.h"
#include <QDebug>
GoodsModel::GoodsModel(QObject* parent)
: QAbstractTableModel(parent),
d_db_util(0)
{
d_head_names << QStringLiteral("商品名称")
<< QStringLiteral("编号")
<< QStringLiteral("入库日期")
<< QStringLiteral("标价")
<< QStringLiteral("成本")
<< QStringLiteral("售价")
<< QStringLiteral("出售日期");
d_db_util = new DBUtil();
init_data();
}
GoodsModel::~GoodsModel()
{
clear_all();
if( !d_head_names.isEmpty() )
{
d_head_names.clear();
}
if( d_db_util )
{
d_db_util->close();
delete d_db_util;
d_db_util = 0;
}
}
void
GoodsModel::clear_all()
{
if( d_items.isEmpty() )
{
return;
}
beginResetModel();
for( QVector<GoodsItem*>::Iterator pos = d_items.begin();
pos != d_items.end(); pos++)
{
delete *pos;
*pos = 0;
}
d_items.clear();
endResetModel();
}
void
GoodsModel::init_data()
{
GoodsTable table;
const QString& sql_str = table.get_select_goods_sql_str();
const QVector<QMap<QString, QString> >& result_data = d_db_util->select_data(sql_str);
if( result_data.empty() )
{
return;
}
//qDebug() << __FILE__ << __LINE__ << " result_data = " << result_data;
clear_all();
beginResetModel();
GoodsItem* item;
QMap<QString, QString> column_data;
for(int i = 0; i < result_data.size(); i++)
{
column_data = result_data.at(i);
item = new GoodsItem();
item->d_id = column_data["id"].toInt();
item->d_name = column_data["name"];
item->d_number = column_data["number"];
item->d_indate = column_data["indate"];
item->d_marked_price = column_data["marked_price"];
item->d_cost = column_data["cost"];
item->d_selling_price = column_data["selling_price"];
item->d_sell_date = column_data["sell_date"];
//qDebug() << __FILE__ << __LINE__ << " d_name = " << item->d_name;
d_items.push_back(item);
}
endResetModel();
}
void
GoodsModel::refresh()
{
init_data();
}
//const QModelIndex
//GoodsModel::get_idx_from_mat_name(const QString& material_name)
//{
// int row = -1;
// for( int i = 0; i < d_items.size(); i++)
// {
// if( d_items.at(i)->d_material_name == material_name )
// {
// row = i;
// break;
// }
// }
// if( row == -1 )
// {
// return QModelIndex();
// }
// return index(row);
//}
int
GoodsModel::get_id_from_idx(const QModelIndex& idx) const
{
if( !idx.isValid() )
{
return -1;
}
GoodsItem* item = (GoodsItem*)idx.internalPointer();
return item->d_id;
}
void
GoodsModel::delete_line(const QModelIndex& idx)
{
if( !idx.isValid() )
{
return;
}
beginResetModel();
const int& pos = idx.row();
const int& id = d_items.at(pos)->d_id;
GoodsTable table;
const QString& sql_str = table.get_delete_sql_str_from_goods_id(id);
d_db_util->delete_data(sql_str);
d_items.remove(pos);
endResetModel();
}
QVariant
GoodsModel::headerData(int section, Qt::Orientation orientation, int role) const
{
//qDebug() << __FILE__ << __LINE__ << " headerData ";
if( Qt::DisplayRole == role &&
Qt::Horizontal == orientation &&
section < d_head_names.size() )
{
return d_head_names.at(section);
}
return QAbstractTableModel::headerData(section, orientation, role);
}
QModelIndex
GoodsModel::index(int row, int column, const QModelIndex& parent) const
{
if( parent.isValid() )
{
return QModelIndex();
}
if( row < d_items.size() )
{
return createIndex(row, column, d_items.at(row));
}
return QModelIndex();
}
int
GoodsModel::rowCount(const QModelIndex& parent) const
{
Q_UNUSED(parent);
return d_items.size();
}
int
GoodsModel::columnCount(const QModelIndex& parent) const
{
Q_UNUSED(parent);
return d_head_names.size();
}
QVariant
GoodsModel::data(const QModelIndex& index, int role) const
{
if( !index.isValid() )
{
return QVariant();
}
GoodsItem* item = (GoodsItem*)index.internalPointer();
if( Qt::DisplayRole == role )
{
return item->get_value_from_idx(index.column());
}
return QVariant();
}
Qt::ItemFlags
GoodsModel::flags(const QModelIndex& index) const
{
Q_UNUSED(index);
Qt::ItemFlags flag = Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable;
return flag;
}
bool
GoodsModel::setData(const QModelIndex& index, const QVariant& value, int role)
{
if( !index.isValid() )
{
return false;
}
if( role != Qt::DisplayRole && role != Qt::EditRole )
{
return false;
}
GoodsItem* item = (GoodsItem*)index.internalPointer();
if( !item )
{
return false;
}
if( value.toString().isEmpty() )
{
return false;
}
const int& column = index.column();
if( column == 3 || column == 4 || column == 5 )
{
bool ok = true;
value.toDouble(&ok);
if( !ok )
{
// 说明价格不是数字
return false;
}
}
item->set_value_from_model_edit(index.column(), value);
GoodsTable table;
const QString& sql = table.get_update_sql_str(*item);
//qDebug() << __FILE__ << __LINE__ << " sql = " << sql;
DBUtil db_util;
db_util.update_data(sql);
return true;
}
Item单个数据元素
GoodsItem.h
#ifndef GOODSITEM_H
#define GOODSITEM_H
#include <QString>
#include <QVariant>
class GoodsItem
{
public:
GoodsItem();
QVariant get_value_from_idx(const int& idx);
void set_value_from_model_edit(const int& idx, const QVariant& value);
public:
int d_id;
// 名称
QString d_name;
// 编号
QString d_number;
// 入库日期
QString d_indate;
// 标价
QString d_marked_price;
// 成本
QString d_cost;
//---------------
// 售价
QString d_selling_price;
// 出售日期
QString d_sell_date;
};
#endif // GOODSITEM_H
GoodsItem.cpp
#include "GoodsItem.h"
#include <QDebug>
GoodsItem::GoodsItem()
{
}
QVariant
GoodsItem::get_value_from_idx(const int& idx)
{
switch (idx) {
case 0:
return d_name;
case 1:
return d_number;
case 2:
return d_indate;
case 3:
return d_marked_price;
case 4:
return d_cost;
case 5:
return d_selling_price;
case 6:
return d_sell_date;
default:
qDebug() << __FILE__ << __LINE__ << " warning: idx = " + idx;
break;
}
return QVariant();
}
void
GoodsItem::set_value_from_model_edit(const int& idx, const QVariant& value)
{
QString val = value.toString();
switch (idx) {
case 0:
d_name = val;
break;
case 1:
d_number = val;
break;
case 2:
d_indate = val;
break;
case 3:
d_marked_price = val;
break;
case 4:
d_cost = val;
break;
case 5:
d_selling_price = val;
break;
case 6:
d_sell_date = val;
break;
default:
qDebug() << __FILE__ << __LINE__ << " warning: idx = " + idx;
break;
}
}
Delegate鼠标点击单元格时,变成编辑状态,比如变成QCheckBox、QSpinBox、QDateTimeEdit、QDateEdit
这里写了一个日期代理
DateDelegate.h
#ifndef DATEDELEGATE_H
#define DATEDELEGATE_H
#include <QItemDelegate>
class DateDelegate : public QItemDelegate
{
Q_OBJECT
public:
DateDelegate(QObject* parent = nullptr);
QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const;
void setEditorData(QWidget* editor, const QModelIndex& index) const;
void setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const;
void updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index) const;
};
#endif // DATEDELEGATE_H
DateDelegate.cpp
#include "DateDelegate.h"
#include <QDateEdit>
#include <QDebug>
DateDelegate::DateDelegate(QObject* parent)
: QItemDelegate(parent)
{
}
QWidget*
DateDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem &/*option*/, const QModelIndex& index) const
{
QString str =index.model()->data(index).toString();
QDateEdit* editor = new QDateEdit(parent);
editor->setDisplayFormat("yyyy/M/d");
editor->setCalendarPopup(true);
editor->setDate(QDate::fromString(str, "yyyy/M/d"));
return editor;
}
void
DateDelegate::setEditorData(QWidget* editor, const QModelIndex& index) const
{
QString str = index.model()->data(index).toString();
QDateEdit* date = static_cast<QDateEdit*>(editor);
date->setDate(QDate::fromString(str, "yyyy/M/d"));
}
void
DateDelegate::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const
{
QDateEdit* date = static_cast<QDateEdit*>(editor);
QString str = date->date().toString("yyyy/M/d");
//qDebug() <<__FILE__<<__LINE__<< " str = " << str;
model->setData(index, str);
}
void
DateDelegate::updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& /*index*/) const
{
editor->setGeometry(option.rect);
}
model里面有一些数据库操作,自行替换O(∩_∩)O哈哈~