增加通讯协议
This commit is contained in:
+116
-7
@@ -5,6 +5,7 @@
|
||||
#include <QHeaderView>
|
||||
#include <QLabel>
|
||||
#include <QPushButton>
|
||||
#include <QKeyEvent>
|
||||
#include "global.h"
|
||||
|
||||
FaultTable::FaultTable(QWidget* parent)
|
||||
@@ -14,23 +15,26 @@ FaultTable::FaultTable(QWidget* parent)
|
||||
lay->setContentsMargins(0, 0, 0, 0);
|
||||
lay->setSpacing(10);
|
||||
|
||||
// 分页行(上一页 / 页码 / 下一页)
|
||||
// 分页行(上一页 / 页码 / 下一页)——水平居中,字号与按钮加大
|
||||
QHBoxLayout* nav = new QHBoxLayout();
|
||||
nav->setSpacing(50);
|
||||
nav->addStretch(1);
|
||||
|
||||
m_prev = new QPushButton("上一页", this);
|
||||
m_prev->setFixedSize(160, 64);
|
||||
m_prev->setFixedSize(240, 100);
|
||||
m_prev->setStyleSheet("font-size:50px;");
|
||||
connect(m_prev, &QPushButton::clicked, this, [this]() {
|
||||
if (m_page > 0) { setPage(m_page - 1); emit pageChanged(m_page); }
|
||||
});
|
||||
|
||||
m_pageLabel = new QLabel("1/1", this);
|
||||
m_pageLabel->setAlignment(Qt::AlignCenter);
|
||||
m_pageLabel->setStyleSheet(QString("color:%1;font-size:22px;").arg(C::TEXT));
|
||||
m_pageLabel->setFixedWidth(140);
|
||||
m_pageLabel->setStyleSheet(QString("color:%1;font-size:40px;").arg(C::TEXT));
|
||||
m_pageLabel->setFixedWidth(180);
|
||||
|
||||
m_next = new QPushButton("下一页", this);
|
||||
m_next->setFixedSize(160, 64);
|
||||
m_next->setFixedSize(240, 100);
|
||||
m_next->setStyleSheet("font-size:50px;");
|
||||
connect(m_next, &QPushButton::clicked, this, [this]() {
|
||||
if (m_page < pageCount() - 1) { setPage(m_page + 1); emit pageChanged(m_page); }
|
||||
});
|
||||
@@ -38,6 +42,7 @@ FaultTable::FaultTable(QWidget* parent)
|
||||
nav->addWidget(m_prev);
|
||||
nav->addWidget(m_pageLabel);
|
||||
nav->addWidget(m_next);
|
||||
nav->addStretch(1); // 尾部也留弹性 → 整行居中
|
||||
lay->addLayout(nav);
|
||||
|
||||
// 表格
|
||||
@@ -47,24 +52,127 @@ FaultTable::FaultTable(QWidget* parent)
|
||||
m_table->setEditTriggers(QAbstractItemView::NoEditTriggers);
|
||||
m_table->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||
m_table->setSelectionMode(QAbstractItemView::SingleSelection);
|
||||
m_table->setTabKeyNavigation(false); // 关掉视图自带的 Tab 导航,改由下方 eventFilter 按行切换
|
||||
m_table->verticalHeader()->setVisible(false);
|
||||
m_table->horizontalHeader()->setFocusPolicy(Qt::NoFocus); // 表头不参与 Tab
|
||||
m_table->verticalHeader()->setFocusPolicy(Qt::NoFocus);
|
||||
m_table->setAlternatingRowColors(true);
|
||||
m_table->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
|
||||
m_table->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Fixed);
|
||||
m_table->setColumnWidth(0, 120);
|
||||
m_table->horizontalHeader()->setSectionResizeMode(2, QHeaderView::Stretch);
|
||||
m_table->verticalHeader()->setDefaultSectionSize(100);
|
||||
m_table->verticalHeader()->setSectionResizeMode(QHeaderView::Fixed);
|
||||
m_table->horizontalHeader()->setFixedHeight(kHeaderHeight); // 固定表头高度(供对齐)
|
||||
// 每页 6 行等分,平均填满表格可用高度
|
||||
m_table->verticalHeader()->setSectionResizeMode(QHeaderView::Stretch);
|
||||
connect(m_table, &QTableWidget::cellClicked, this, [this](int row, int) {
|
||||
int global = m_page * m_pageSize + row;
|
||||
if (global >= 0 && global < m_data.size())
|
||||
emit rowClicked(global);
|
||||
});
|
||||
m_table->installEventFilter(this); // 拦截 Tab,实现按行切换
|
||||
m_table->viewport()->setMouseTracking(true); // 悬停整行高亮
|
||||
m_table->viewport()->installEventFilter(this); // 鼠标移出视口 → 取消高亮
|
||||
connect(m_table, &QAbstractItemView::entered, this,
|
||||
[this](const QModelIndex& idx) { setHoverRow(idx.row()); });
|
||||
lay->addWidget(m_table, 1);
|
||||
|
||||
refresh();
|
||||
}
|
||||
|
||||
QWidget* FaultTable::view() const { return m_table; }
|
||||
QWidget* FaultTable::prevButton() const { return m_prev; }
|
||||
QWidget* FaultTable::nextButton() const { return m_next; }
|
||||
|
||||
bool FaultTable::eventFilter(QObject* obj, QEvent* ev)
|
||||
{
|
||||
if (obj == m_table->viewport() && ev->type() == QEvent::Leave) {
|
||||
setHoverRow(-1); // 鼠标移出表格 → 取消悬停高亮
|
||||
return QWidget::eventFilter(obj, ev);
|
||||
}
|
||||
if (obj != m_table)
|
||||
return QWidget::eventFilter(obj, ev);
|
||||
|
||||
// 焦点进入表格时选中一行:正向(Tab)进末行→回首行、否则选首行;反向(Shift+Tab)同理选末行
|
||||
if (ev->type() == QEvent::FocusIn) {
|
||||
QFocusEvent* fe = static_cast<QFocusEvent*>(ev);
|
||||
const int last = m_table->rowCount() - 1;
|
||||
const int col = qMax(0, m_table->currentColumn());
|
||||
int row = -1;
|
||||
if (fe->reason() == Qt::TabFocusReason) {
|
||||
if (last >= 0 && (m_table->currentRow() < 0 || m_table->currentRow() >= last))
|
||||
row = 0;
|
||||
} else if (fe->reason() == Qt::BacktabFocusReason) {
|
||||
if (last >= 0 && (m_table->currentRow() < 0 || m_table->currentRow() <= 0))
|
||||
row = last;
|
||||
}
|
||||
if (row >= 0) {
|
||||
m_table->setCurrentCell(row, col);
|
||||
m_table->selectRow(row); // 显式整行选中(只设当前单元格时可能只高亮一格)
|
||||
}
|
||||
}
|
||||
|
||||
// 仅键盘(Tab/Shift+Tab)移走焦点时清除选中;鼠标点击/弹窗抢焦点时保留,便于看清当前行
|
||||
if (ev->type() == QEvent::FocusOut) {
|
||||
QFocusEvent* fe = static_cast<QFocusEvent*>(ev);
|
||||
if (fe->reason() == Qt::TabFocusReason || fe->reason() == Qt::BacktabFocusReason)
|
||||
m_table->clearSelection();
|
||||
return QWidget::eventFilter(obj, ev);
|
||||
}
|
||||
|
||||
// Tab / Shift+Tab:按行切换选中(每一行作为一个单位);回车/空格:等同鼠标点击
|
||||
if (ev->type() == QEvent::KeyPress) {
|
||||
QKeyEvent* ke = static_cast<QKeyEvent*>(ev);
|
||||
// 方向键在本机是"旋钮"键位(只给 ParamControl 调值),表格里不参与导航:
|
||||
// 换行只走 Tab/Shift+Tab,激活只走回车/空格
|
||||
if (ke->key() == Qt::Key_Up || ke->key() == Qt::Key_Down
|
||||
|| ke->key() == Qt::Key_Left || ke->key() == Qt::Key_Right)
|
||||
return true;
|
||||
|
||||
if (ke->key() == Qt::Key_Tab || ke->key() == Qt::Key_Backtab) {
|
||||
const bool back = (ke->key() == Qt::Key_Backtab) || (ke->modifiers() & Qt::ShiftModifier);
|
||||
const int next = m_table->currentRow() + (back ? -1 : 1);
|
||||
if (next >= 0 && next < m_table->rowCount()) {
|
||||
m_table->setCurrentCell(next, qMax(0, m_table->currentColumn()));
|
||||
m_table->selectRow(next); // 整行选中
|
||||
return true; // 消费事件,焦点留在表格内
|
||||
}
|
||||
// 已在首/末行:不拦截,焦点按 Tab 顺序移到下一个控件
|
||||
} else if (ke->key() == Qt::Key_Return || ke->key() == Qt::Key_Enter
|
||||
|| ke->key() == Qt::Key_Space) {
|
||||
// 键盘激活:与鼠标 cellClicked 走同一个信号,弹窗逻辑只有一份
|
||||
const int row = m_table->currentRow();
|
||||
const int global = m_page * m_pageSize + row;
|
||||
if (row >= 0 && global >= 0 && global < m_data.size()) {
|
||||
emit rowClicked(global);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return QWidget::eventFilter(obj, ev);
|
||||
}
|
||||
|
||||
// 鼠标悬停的整行高亮:颜色与“选中”一致(主色蓝底白字)
|
||||
void FaultTable::setHoverRow(int row)
|
||||
{
|
||||
if (row == m_hoverRow)
|
||||
return;
|
||||
if (m_hoverRow >= 0) {
|
||||
for (int c = 0; c < m_table->columnCount(); ++c)
|
||||
if (QTableWidgetItem* it = m_table->item(m_hoverRow, c)) {
|
||||
it->setData(Qt::BackgroundRole, QVariant());
|
||||
it->setData(Qt::ForegroundRole, QVariant());
|
||||
}
|
||||
}
|
||||
m_hoverRow = row;
|
||||
if (m_hoverRow >= 0) {
|
||||
for (int c = 0; c < m_table->columnCount(); ++c)
|
||||
if (QTableWidgetItem* it = m_table->item(m_hoverRow, c)) {
|
||||
it->setData(Qt::BackgroundRole, QColor(C::PRIMARY));
|
||||
it->setData(Qt::ForegroundRole, QColor("#FFFFFF"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FaultTable::setData(const QVector<FaultRecord>& data)
|
||||
{
|
||||
m_data = data;
|
||||
@@ -87,6 +195,7 @@ int FaultTable::pageCount() const
|
||||
|
||||
void FaultTable::refresh()
|
||||
{
|
||||
m_hoverRow = -1; // 单元格会重建,悬停行失效
|
||||
m_table->setRowCount(0);
|
||||
m_table->setRowCount(m_pageSize);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user