#include "tableoverlaywidget.h" #include #include #include #include TableOverlayWidget::TableOverlayWidget(QWidget *parent) : QWidget(parent), m_isVisible(false) { setupUI(); hide(); // 初始隐藏 } void TableOverlayWidget::setupUI() { // 设置浮层属性 setAttribute(Qt::WA_StyledBackground); setStyleSheet("TableOverlayWidget { background: transparent; }"); // 主布局 auto *mainLayout = new QHBoxLayout(this); mainLayout->setContentsMargins(0, 0, 0, 0); mainLayout->setSpacing(0); // 左侧标签栏滚动区域 m_tabScrollArea = new QScrollArea(this); m_tabScrollArea->setFixedWidth(130); m_tabScrollArea->setWidgetResizable(true); m_tabScrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); m_tabScrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); m_tabScrollArea->setStyleSheet( "QScrollArea { " " background: #34495e; " " border-right: 1px solid #2c3e50; " " border: none; " "}" "QScrollBar:vertical { " " background: #2c3e50; " " width: 10px; " " margin: 0px; " "}" "QScrollBar::handle:vertical { " " background: #546e7a; " " min-height: 20px; " " border-radius: 5px; " "}" "QScrollBar::handle:vertical:hover { " " background: #607d8b; " "}" "QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical { " " height: 0px; " "}" "QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical { " " background: none; " "}"); // 标签栏容器 m_tabBar = new QWidget(); m_tabBar->setStyleSheet( "QWidget { " " background: #34495e; " "}"); m_tabLayout = new QVBoxLayout(m_tabBar); m_tabLayout->setContentsMargins(8, 12, 8, 12); m_tabLayout->setSpacing(6); m_tabLayout->setAlignment(Qt::AlignTop); m_tabScrollArea->setWidget(m_tabBar); mainLayout->addWidget(m_tabScrollArea); // 内容容器(右侧) m_container = new QWidget(this); m_container->setStyleSheet( "QWidget { " " background: #f5f5f5; " " border: none; " " border-top-right-radius: 10px; " " border-bottom-right-radius: 10px; " "}"); auto *containerLayout = new QVBoxLayout(m_container); containerLayout->setContentsMargins(0, 0, 0, 0); containerLayout->setSpacing(0); // 标题栏 auto *headerWidget = new QWidget(this); headerWidget->setStyleSheet( "QWidget { " " background: qlineargradient(x1:0, y1:0, x2:1, y2:0, stop:0 #3498db, stop:1 #2980b9); " " border-top-left-radius: 0px; " " border-top-right-radius: 10px; " "}"); auto *headerLayout = new QHBoxLayout(headerWidget); headerLayout->setContentsMargins(20, 10, 10, 10); headerLayout->setSpacing(8); m_titleLabel = new QLabel("表格", this); m_titleLabel->setStyleSheet( "QLabel { " " color: white; " " font-size: 14pt; " " font-weight: bold; " " background: transparent; " "}"); headerLayout->addWidget(m_titleLabel); headerLayout->addStretch(); // 关闭按钮 - 正方形圆角,图标居中 m_closeBtn = new QPushButton("×", this); m_closeBtn->setFixedSize(32, 32); m_closeBtn->setCursor(Qt::PointingHandCursor); m_closeBtn->setStyleSheet( "QPushButton { " " background: rgba(255,255,255,0.2); " " color: white; " " border: none; " " border-radius: 6px; " " font-size: 20px; " " font-weight: normal; " " text-align: center; " " padding: 0px; " " margin: 0px; " "}" "QPushButton:hover { background: rgba(255,255,255,0.35); }" "QPushButton:pressed { background: rgba(255,255,255,0.5); }"); connect(m_closeBtn, &QPushButton::clicked, this, &TableOverlayWidget::onCloseButtonClicked); headerLayout->addWidget(m_closeBtn); containerLayout->addWidget(headerWidget); // 内容堆栈 m_contentStack = new QStackedWidget(this); m_contentStack->setStyleSheet( "QStackedWidget { " " background: white; " " border: none; " "}"); containerLayout->addWidget(m_contentStack, 1); mainLayout->addWidget(m_container, 1); // 设置默认大小(占父容器的70%宽度,90%高度) setMinimumWidth(600); setMaximumWidth(1200); } void TableOverlayWidget::addTable(const QString &tableId, const QString &tableName, QWidget *tableWidget) { if (m_tables.contains(tableId)) { qDebug() << "Table already exists:" << tableId; return; } TableTab tab; tab.id = tableId; tab.name = tableName; tab.widget = tableWidget; // 创建标签按钮 tab.tabButton = new QPushButton(tableName, m_tabBar); tab.tabButton->setFixedHeight(48); tab.tabButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); tab.tabButton->setProperty("tableId", tableId); tab.tabButton->setCursor(Qt::PointingHandCursor); tab.tabButton->setStyleSheet( "QPushButton {" " background: #455a64;" " color: #ecf0f1;" " border: none;" " border-radius: 6px;" " padding: 6px 6px;" " font-size: 9.5pt;" " font-weight: 500;" " text-align: center;" " border-left: 3px solid transparent;" "}" "QPushButton:hover {" " background: #546e7a;" " color: white;" "}" "QPushButton:checked {" " background: #2980b9;" " color: white;" " font-weight: bold;" " border-left: 3px solid #1976d2;" "}" "QPushButton:pressed {" " background: #21618c;" "}"); tab.tabButton->setCheckable(true); connect(tab.tabButton, &QPushButton::clicked, this, &TableOverlayWidget::onTabButtonClicked); // 添加到布局 m_tabLayout->addWidget(tab.tabButton); // 添加到内容堆栈 m_contentStack->addWidget(tableWidget); m_tables[tableId] = tab; // 如果是第一个表格,自动显示 if (m_tables.size() == 1) { showTable(tableId); } } void TableOverlayWidget::showTable(const QString &tableId) { if (!m_tables.contains(tableId)) { qDebug() << "Table not found:" << tableId; return; } // 取消之前的选中状态 if (!m_currentTableId.isEmpty() && m_tables.contains(m_currentTableId)) { m_tables[m_currentTableId].tabButton->setChecked(false); } // 切换到新表格 m_currentTableId = tableId; const TableTab &tab = m_tables[tableId]; tab.tabButton->setChecked(true); m_contentStack->setCurrentWidget(tab.widget); m_titleLabel->setText(tab.name); emit tableChanged(tableId); } void TableOverlayWidget::removeTable(const QString &tableId) { if (!m_tables.contains(tableId)) return; TableTab tab = m_tables.take(tableId); // 移除按钮 m_tabLayout->removeWidget(tab.tabButton); tab.tabButton->deleteLater(); // 移除内容 m_contentStack->removeWidget(tab.widget); // 如果删除的是当前表格,切换到第一个 if (m_currentTableId == tableId && !m_tables.isEmpty()) { showTable(m_tables.firstKey()); } else if (m_tables.isEmpty()) { m_currentTableId.clear(); hideOverlay(); } } void TableOverlayWidget::clearTables() { // 清除所有表格 for (const QString &tableId : m_tables.keys()) { removeTable(tableId); } m_currentTableId.clear(); } void TableOverlayWidget::showOverlay() { if (m_isVisible || m_tables.isEmpty()) return; // 如果当前没有选中的表格,显示第一个 if (m_currentTableId.isEmpty() && !m_tables.isEmpty()) { showTable(m_tables.firstKey()); } m_isVisible = true; m_container->show(); m_tabBar->show(); show(); animateShow(); } void TableOverlayWidget::hideOverlay() { if (!m_isVisible) return; m_isVisible = false; animateHide(); } void TableOverlayWidget::toggleOverlay() { if (m_isVisible) hideOverlay(); else showOverlay(); } void TableOverlayWidget::onTabButtonClicked() { QPushButton *btn = qobject_cast(sender()); if (!btn) return; QString tableId = btn->property("tableId").toString(); if (!tableId.isEmpty()) { showTable(tableId); } } void TableOverlayWidget::onCloseButtonClicked() { hideOverlay(); emit closed(); } void TableOverlayWidget::updateTabButtons() { for (const TableTab &tab : m_tables) { tab.tabButton->setChecked(tab.id == m_currentTableId); } } void TableOverlayWidget::animateShow() { // 淡入动画 QGraphicsOpacityEffect *effect = new QGraphicsOpacityEffect(this); setGraphicsEffect(effect); QPropertyAnimation *animation = new QPropertyAnimation(effect, "opacity"); animation->setDuration(200); animation->setStartValue(0.0); animation->setEndValue(1.0); animation->setEasingCurve(QEasingCurve::OutCubic); animation->start(QPropertyAnimation::DeleteWhenStopped); } void TableOverlayWidget::animateHide() { // 淡出动画 QGraphicsOpacityEffect *effect = new QGraphicsOpacityEffect(this); setGraphicsEffect(effect); QPropertyAnimation *animation = new QPropertyAnimation(effect, "opacity"); animation->setDuration(150); animation->setStartValue(1.0); animation->setEndValue(0.0); animation->setEasingCurve(QEasingCurve::InCubic); connect(animation, &QPropertyAnimation::finished, this, &TableOverlayWidget::hide); animation->start(QPropertyAnimation::DeleteWhenStopped); }