update highlineview lastorder

This commit is contained in:
2025-08-31 23:07:06 +08:00
parent 4bf7977a30
commit 6ede3eff92
11 changed files with 145 additions and 36 deletions

BIN
QTradeProgram.VC.VC.opendb Normal file

Binary file not shown.

Binary file not shown.

View File

@@ -69,4 +69,47 @@ QString NumberFormatDelegate::displayText(const QVariant &value, const QLocale &
} }
return QStyledItemDelegate::displayText(value, locale); return QStyledItemDelegate::displayText(value, locale);
}
HighlightDelegate::HighlightDelegate(QObject *parent)
: QStyledItemDelegate(parent)
{
}
void HighlightDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
QStyleOptionViewItem opt = option;
initStyleOption(&opt, index);
// 检查是否需要高亮 - 通过映射到源模型获取高亮状态
QAbstractItemModel *model = const_cast<QAbstractItemModel*>(index.model());
QSortFilterProxyModel *proxyModel = qobject_cast<QSortFilterProxyModel*>(model);
bool isHighlighted = false;
if (proxyModel) {
QModelIndex sourceIndex = proxyModel->mapToSource(index);
isHighlighted = sourceIndex.data(IsHighlightedRole).toBool();
}
else {
isHighlighted = index.data(IsHighlightedRole).toBool();
}
if (isHighlighted) {
// 设置高亮背景
painter->fillRect(opt.rect, QColor(255, 192, 203)); // 浅黄色背景
// 设置加粗字体
QFont boldFont = opt.font;
boldFont.setBold(true);
painter->setFont(boldFont);
// 绘制文本
painter->setPen(opt.palette.color(QPalette::Text));
painter->drawText(opt.rect, opt.displayAlignment, opt.text);
}
else {
// 正常绘制
QStyledItemDelegate::paint(painter, opt, index);
}
} }

View File

@@ -3,8 +3,15 @@
#include <QObject> #include <QObject>
#include <QStyledItemDelegate> #include <QStyledItemDelegate>
#include <QSortFilterProxyModel>
#include <QPainter> #include <QPainter>
// 在文件顶部添加高亮角色定义
enum CustomRoles {
IsHighlightedRole = Qt::UserRole + 100
};
/* 订单类型单元格渲染委托 */ /* 订单类型单元格渲染委托 */
class OrderTypeDelegate : public QStyledItemDelegate class OrderTypeDelegate : public QStyledItemDelegate
{ {
@@ -33,4 +40,19 @@ public:
QString displayText(const QVariant &value, const QLocale &locale) const override; QString displayText(const QVariant &value, const QLocale &locale) const override;
}; };
#endif // ORDERTYPEDELEGATE_H
// 新大单高亮委托
class HighlightDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
explicit HighlightDelegate(QObject *parent = nullptr);
void paint(QPainter *painter, const QStyleOptionViewItem &option,
const QModelIndex &index) const override;
// 可选如果需要编辑器可以重写createEditor等方法
};
#endif // HIGHLIGHTDELEGATE_H

View File

@@ -71,7 +71,7 @@ bool QBigOrderManager::addBigOrder(const BigOrderInfo &order)
locker.unlock(); // <20>Ƚ<EFBFBD><C8BD><EFBFBD><EFBFBD>ٷ<EFBFBD><D9B7>ź<EFBFBD> locker.unlock(); // <20>Ƚ<EFBFBD><C8BD><EFBFBD><EFBFBD>ٷ<EFBFBD><D9B7>ź<EFBFBD>
emit bigOrderAdded(order); emit bigOrderAdded(order);
emit markBigOrderSignal(); emit markBigOrderSignal();
return true; return true;

View File

@@ -15,32 +15,14 @@
#include <QWidget> #include <QWidget>
#include <QCheckBox> #include <QCheckBox>
//// ==================== OrderTypeDelegate ====================
//OrderTypeDelegate::OrderTypeDelegate(QObject *parent)
// : QStyledItemDelegate(parent)
//{
//}
//
//void OrderTypeDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
// const QModelIndex &index) const
//{
// if (!index.isValid()) return;
//
// QString type = index.data(Qt::DisplayRole).toString();
// if (type == "买入") {
// painter->fillRect(option.rect, QColor(255, 230, 230)); // 买入订单浅红背景
// } else if (type == "卖出") {
// painter->fillRect(option.rect, QColor(230, 255, 230)); // 卖出订单浅绿背景
// }
// QStyledItemDelegate::paint(painter, option, index);
//}
// ==================== QBigOrderViewer ==================== // ==================== QBigOrderViewer ====================
QBigOrderViewer::QBigOrderViewer(QWidget *parent) QBigOrderViewer::QBigOrderViewer(QWidget *parent)
: QWidget(parent), : QWidget(parent),
m_model(new QStandardItemModel(0, 7, this)), m_model(new QStandardItemModel(0, 7, this)),
m_proxyModel(new QSortFilterProxyModel(this)), m_proxyModel(new QSortFilterProxyModel(this)),
m_typeDelegate(new OrderTypeDelegate(this)) m_typeDelegate(new OrderTypeDelegate(this)),
m_lastOrderDelegate(new HighlightDelegate(this))
{ {
initUI(); initUI();
initConnections(); initConnections();
@@ -120,9 +102,12 @@ void QBigOrderViewer::initUI()
// m_tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Interactive); // m_tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Interactive);
m_tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); m_tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
// 默认按时间列第6列索引5升序排序 // 设置高亮委托到所有列
m_tableView->setItemDelegate(m_lastOrderDelegate);
// 默认按时间列第6列索引5升序排序 -> 新插入的行放在最顶上,故修改为降序排序 @2025.08.30 stone
const int timeColumnIndex = 6; const int timeColumnIndex = 6;
m_proxyModel->sort(timeColumnIndex, Qt::AscendingOrder); m_proxyModel->sort(timeColumnIndex, Qt::DescendingOrder);
mainLayout->addWidget(m_tableView); mainLayout->addWidget(m_tableView);
@@ -226,17 +211,60 @@ void QBigOrderViewer::applyFilters()
} }
} }
//void QBigOrderViewer::onBigOrderAdded(const BigOrderInfo &order)
//{
// auto newOrder = QSharedPointer<BigOrderInfo>::create(order);
// m_allOrders.append(newOrder);
// if (matchesFilter(newOrder)) {
// m_currentOrders.append(newOrder);
//
// // 高效插入单行
// int row = m_model->rowCount();
// m_model->insertRow(row);
// setRowData(row, newOrder);
// }
//}
void QBigOrderViewer::onBigOrderAdded(const BigOrderInfo &order) void QBigOrderViewer::onBigOrderAdded(const BigOrderInfo &order)
{ {
auto newOrder = QSharedPointer<BigOrderInfo>::create(order); auto newOrder = QSharedPointer<BigOrderInfo>::create(order);
m_allOrders.append(newOrder); m_allOrders.append(newOrder);
// 应用过滤条件
if (matchesFilter(newOrder)) { if (matchesFilter(newOrder)) {
m_currentOrders.append(newOrder); m_currentOrders.append(newOrder);
// 高效插入单行 // 在源模型的首行插入
int row = m_model->rowCount(); int row = 0 ;
m_model->insertRow(row); m_model->insertRow(row);
setRowData(row, newOrder); setRowData(row, newOrder);
// 设置高亮标记
for (int col = 0; col < m_model->columnCount(); ++col) {
QModelIndex index = m_model->index(row, col);
m_model->setData(index, true, IsHighlightedRole);
}
// 通知视图更新
QModelIndex topLeft = m_model->index(row, 0);
QModelIndex bottomRight = m_model->index(row, m_model->columnCount() - 1);
emit m_model->dataChanged(topLeft, bottomRight);
// 2秒后取消高亮
QTimer::singleShot(2000, this, [this, row]() {
for (int col = 0; col < m_model->columnCount(); ++col) {
QModelIndex index = m_model->index(row, col);
m_model->setData(index, false, IsHighlightedRole);
}
// 通知视图更新
QModelIndex topLeft = m_model->index(row, 0);
QModelIndex bottomRight = m_model->index(row, m_model->columnCount() - 1);
emit m_model->dataChanged(topLeft, bottomRight);
});
// 确保代理模型按时间降序排序,新数据在顶部
m_proxyModel->sort(6, Qt::DescendingOrder);
} }
} }
@@ -253,13 +281,26 @@ void QBigOrderViewer::setRowData(int row, QSharedPointer<BigOrderInfo> order)
QString::number(order->price, 'f', 2)); QString::number(order->price, 'f', 2));
m_model->setData(m_model->index(row, 5), m_model->setData(m_model->index(row, 5),
QString::number(order->level)); QString::number(order->level));
QString str = order->svrRecvTime.mid(11); // 确保时间格式正确,用于排序
if (str == nullptr) QString timeStr;
{ if (order->svrRecvTime.length() >= 11) {
QDateTime dateTime = QDateTime::currentDateTime(); timeStr = order->svrRecvTime.mid(11);
str = dateTime.toString("hh:mm:ss");
} }
m_model->setData(m_model->index(row, 6), str); else {
QDateTime dateTime = QDateTime::currentDateTime();
timeStr = dateTime.toString("hh:mm:ss");
}
m_model->setData(m_model->index(row, 6), timeStr);
// 添加一个隐藏的时间戳列用于精确排序
QDateTime fullDateTime;
if (order->svrRecvTime.length() >= 19) {
fullDateTime = QDateTime::fromString(order->svrRecvTime.left(19), "yyyy-MM-dd hh:mm:ss");
}
else {
fullDateTime = QDateTime::currentDateTime();
}
m_model->setData(m_model->index(row, 6), fullDateTime, Qt::UserRole + 101); // 使用自定义角色存储完整时间戳
} }
bool QBigOrderViewer::matchesFilter(QSharedPointer<BigOrderInfo> order) bool QBigOrderViewer::matchesFilter(QSharedPointer<BigOrderInfo> order)

View File

@@ -50,6 +50,7 @@ private:
QStandardItemModel *m_model; QStandardItemModel *m_model;
QSortFilterProxyModel *m_proxyModel; QSortFilterProxyModel *m_proxyModel;
OrderTypeDelegate *m_typeDelegate; OrderTypeDelegate *m_typeDelegate;
HighlightDelegate *m_lastOrderDelegate;
// 数据存储 // 数据存储
QList<QSharedPointer<BigOrderInfo>> m_allOrders; QList<QSharedPointer<BigOrderInfo>> m_allOrders;

View File

@@ -22,6 +22,7 @@ QHistoryOrderDialog::QHistoryOrderDialog(QWidget *parent)
m_proxyModel(new QSortFilterProxyModel(this)), m_proxyModel(new QSortFilterProxyModel(this)),
m_typeDelegate(new OrderTypeDelegate(this)), m_typeDelegate(new OrderTypeDelegate(this)),
m_numberDelegate(new NumberFormatDelegate(this)) m_numberDelegate(new NumberFormatDelegate(this))
{ {
setWindowTitle("<EFBFBD><EFBFBD>ʷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѯ"); setWindowTitle("<EFBFBD><EFBFBD>ʷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѯ");
setMinimumSize(800, 600); setMinimumSize(800, 600);

View File

@@ -52,6 +52,7 @@ private:
QStandardItemModel *m_model; QStandardItemModel *m_model;
QSortFilterProxyModel *m_proxyModel; QSortFilterProxyModel *m_proxyModel;
// <20><><EFBFBD><EFBFBD>ί<EFBFBD><CEAF>
NumberFormatDelegate *m_numberDelegate; NumberFormatDelegate *m_numberDelegate;
OrderTypeDelegate *m_typeDelegate; OrderTypeDelegate *m_typeDelegate;

View File

@@ -241,7 +241,7 @@ void QOrderProcessor::internalProcess(const OrderBookData& orderData)
try { try {
const auto result = findExtremeOrders(orderData); const auto result = findExtremeOrders(orderData);
for (int i = 0; i < result.size(); i++) for (int i = 0; i < result.size(); i++)
{ {
if(result.at(i).isBigOrder) if(result.at(i).isBigOrder)

View File

@@ -1,9 +1,9 @@
<EFBFBD><EFBFBD>Ʊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>,<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ <EFBFBD><EFBFBD>Ʊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>,<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ
09885,200000 09885,200000
00581,300000 00581,30000
03383,800000 03383,800000
02666,500000 02666,500000
00839,500000 00839,500000
06098,600000 06098,600000
06865,150000 06865,10000
00700,10000 00700,1000
1 股票代码 检测阈值
2 09885 200000
3 00581 300000 30000
4 03383 800000
5 02666 500000
6 00839 500000
7 06098 600000
8 06865 150000 10000
9 00700 10000 1000