首页 > 解决方案 > 如何在 Qt 中固定选项卡

问题描述

是否可以使用 Qt 固定选项卡?

我希望一个选项卡始终保持原位(索引 0),同时仍然能够移动其他选项卡。

到目前为止,我试图听 QTabBar::tabMoved 并恢复移动,但为时已晚。我什至不希望它尝试移动。

对我来说最坏的情况是被迫改变鼠标处理。如果有其他方法,请告诉我。

标签: qtqtabbar

解决方案


我从来没有找到一个很好的方法来做到这一点。但是,我使用了这样一个事实,即您可以将原始数据存储在QTabBar固定选项卡中,如果它是固定选项卡,则撤消移动。它并不完美,我仍然有一些丑陋的行为,但我也不想使用鼠标事件。

首先,创建一个结构来存储选项卡的当前状态:

struct PinnedTab
{
    bool isPinned;
    int currentIndex;
};

Q_DECLARE_METATYPE(PinnedTab); // For QVariant

然后,创建一个自定义QTabBar来处理移动并用于QTabWidget替换当前的选项卡栏(您必须在插入选项卡之前执行此操作):

class Bar: public QTabBar
{
public:
    void pin(int const index)
    {
        PinnedTab info;
        info.isPinned = true;
        info.currentIndex = index; // TODO: move the tab to the left and do not use current index
        setTabData(index, QVariant::fromValue(info));
    }

    Bar(QWidget* parent=nullptr): QTabBar(parent)
    {}

    virtual void tabLayoutChange() override
    {
        for (int i = 0; i != count(); ++i) // Check if a pinned tab has moved
        {
            if (tabData(i).isValid())
            {
                PinnedTab const info = tabData(i).value<PinnedTab>();
                if (info.isPinned == true && i != info.currentIndex) {
                    rollbackLayout();
                    return;
                }
            }
        }

        for (int i = 0; i != count(); ++i)
        {
            if (tabData(i).isValid())
            {
                PinnedTab info = tabData(i).value<PinnedTab>();
                info.currentIndex = i;
                setTabData(i, QVariant::fromValue(info));
            }
            else
            {
                PinnedTab info;
                info.isPinned = false;
                info.currentIndex = i;
                setTabData(i, QVariant::fromValue(info));
            }
        }
    }

    void rollbackLayout() {
        for (int i = 0; i != count(); ++i)
        {
            if (tabData(i).isValid())
            {
                PinnedTab const info = tabData(i).value<PinnedTab>();
                if (i != info.currentIndex) {
                    moveTab(i, info.currentIndex);
                }
            }
        }
    }
};

tabLayoutChange当布局改变时调用。因此,它会在您移动选项卡时调用。

rollbackLayout方法用于将每个选项卡移动到选项卡数据中存储的最后一个位置。

调用pin以固定具有给定索引的选项卡。

为了更清晰,我简化了我的代码,您可能必须重新定义一些行为(现在,如果您固定一个选项卡,它将保持其当前位置并且不会处理插入/删除选项卡)。


推荐阅读