From 47037b8e80958e53b761db02db70cfec803c7921 Mon Sep 17 00:00:00 2001 From: xiepengfei Date: Thu, 23 Apr 2026 10:03:31 +0800 Subject: [PATCH] fix(editor): resolve tab bar jitter when adding new tabs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Batch layout operations with setUpdatesEnabled and double layout()->activate() to prevent scroll button cascade flicker. 修复新建标签页时标签栏抖动问题,通过批量布局操作和 双重layout激活消除滚动按钮级联闪烁。 Log: 修复新建标签页时标签栏抖动 PMS: BUG-353507 Influence: 新建标签页(2个及以上)时不再出现标签栏抖动现象,提升用户体验。 --- src/controls/tabbar.cpp | 44 ++++++++++++++++++++++++++++------------- src/widgets/window.cpp | 8 ++++++-- 2 files changed, 36 insertions(+), 16 deletions(-) diff --git a/src/controls/tabbar.cpp b/src/controls/tabbar.cpp index 1cd425ba..655b27f3 100644 --- a/src/controls/tabbar.cpp +++ b/src/controls/tabbar.cpp @@ -127,8 +127,17 @@ void Tabbar::addTabWithIndex(int index, const QString &filePath, const QString & // 除去空白符 梁卫东 2020-08-26 14:49:15 ;适配助记符 QString trimmedName = replaceMnemonic(tabName.simplified()); qDebug() << "trimmedName:" << trimmedName; + + // Batch all layout-triggering operations to avoid jitter: + // 1. Disable visual updates + // 2. Insert tab (triggers QTabBar layout with old width → may overflow) + // 3. Force DTabBar layout to resize inner QTabBar to correct width + // 4. Force QTabBar to recalculate tab positions with correct width + // 5. Re-enable visual updates → single paint with final state + setUpdatesEnabled(false); DTabBar::insertTab(index, trimmedName); DTabBar::setCurrentIndex(index); + qDebug() << "filePath.contains(Utils::localDataPath())"; if (filePath.contains(Utils::localDataPath())) { if (Utils::isBackupFile(filePath) && !tipPath.isNull() && tipPath.length() > 0) { @@ -159,6 +168,16 @@ void Tabbar::addTabWithIndex(int index, const QString &filePath, const QString & qDebug() << "path:" << path; setTabToolTip(index, path); } + + // Force DTabBar's layout to resize inner QTabBar to its new sizeHint + layout()->activate(); + // Force QTabBar internal layout recalculation with correct width + setIconSize(iconSize()); + // activate() may trigger scroll button show/hide cascade which + // invalidates layout again; run a second time to settle completely + layout()->activate(); + + setUpdatesEnabled(true); } void Tabbar::resizeEvent(QResizeEvent *event) @@ -826,23 +845,20 @@ QSize Tabbar::tabSizeHint(int index) const qDebug() << "Enter tabSizeHint, index:" << index; if (index >= 0) { int total = this->width(); - qDebug() << "total:" << total; - //计算每个tab平均宽度 返回 100到160 - int aveargeWidth = 160; - aveargeWidth = total / DTabBar::count(); - qDebug() << "aveargeWidth:" << aveargeWidth; - if (aveargeWidth >= 160) { - qDebug() << "aveargeWidth >= 160"; - aveargeWidth = 160; - } else if (aveargeWidth <= 110) { - qDebug() << "aveargeWidth <= 110"; - aveargeWidth = 110; + // 计算每个tab宽度:标签数未溢出时使用固定最大宽度,溢出时等分 + const int maxTabWidth = 160; + const int minTabWidth = 110; + int tabCount = DTabBar::count(); + int tabWidth = maxTabWidth; + + if (tabCount * maxTabWidth > total) { + tabWidth = total / tabCount; + tabWidth = qBound(minTabWidth, tabWidth, maxTabWidth); } - qDebug() << "aveargeWidth:" << aveargeWidth; #ifdef DTKWIDGET_CLASS_DSizeMode - return QSize(aveargeWidth, DGuiApplicationHelper::isCompactMode() ? s_TabbarHeightCompact : s_TabbarHeight); + return QSize(tabWidth, DGuiApplicationHelper::isCompactMode() ? s_TabbarHeightCompact : s_TabbarHeight); #else - return QSize(aveargeWidth, 40); + return QSize(tabWidth, 40); #endif } qDebug() << "Exit tabSizeHint"; diff --git a/src/widgets/window.cpp b/src/widgets/window.cpp index 458f705d..f85be8f5 100644 --- a/src/widgets/window.cpp +++ b/src/widgets/window.cpp @@ -3914,12 +3914,16 @@ void Window::checkTabbarForReload() if (fi.exists() && !fi.isWritable()) { qDebug() << "check tabbar for reload backup-files not writable"; tabName.append(readOnlyStr); - m_tabbar->setTabText(m_tabbar->currentIndex(), tabName); + if (m_tabbar->currentName() != tabName) { + m_tabbar->setTabText(m_tabbar->currentIndex(), tabName); + } wrapper->textEditor()->setReadOnlyPermission(true); } else { qDebug() << "check tabbar for reload backup-files writable"; tabName.remove(readOnlyStr); - m_tabbar->setTabText(m_tabbar->currentIndex(), tabName); + if (m_tabbar->currentName() != tabName) { + m_tabbar->setTabText(m_tabbar->currentIndex(), tabName); + } wrapper->textEditor()->setReadOnlyPermission(false); }