Я никогда не находил хороший способ сделать это. Но я использовал тот факт, что вы можете хранить необработанные данные в 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
, чтобы закрепить вкладку с указанным индексом.
Я упростил свой код для большей ясности, и вам, возможно, придется переопределить некоторое поведение (сейчас, если вы закрепите вкладку, она сохранит свой текущий положение, и он не будет обрабатывать вставки / удаления вкладок).