简体   繁体   English

如何识别当前选项卡在 QTabWidget 中的更改时间?

[英]How to identify when the current tab is changing in a QTabWidget?

I'm using a QTabWidget and I need a way to handle the change of the current tab before it actually happens, and possibly cancel it if certain conditions are met.我正在使用QTabWidget并且我需要一种方法来在实际发生之前处理当前选项卡的更改,并且如果满足某些条件可能会取消它。 The QTabWidget::currentChanged signal is received after the current tab has changed, but is there a QTabWidget::currentChanging signal or another way to achieve the behavior I need?在当前选项卡更改后收到QTabWidget::currentChanged信号,但是否有QTabWidget::currentChanging信号或其他方式来实现我需要的行为?

In my case, I connect SIGNAL and SLOT like this:就我而言,我像这样连接 SIGNAL 和 SLOT:

//check if user clicked at a tab
connect(ui->tabWidget, SIGNAL(currentChanged(int)), this, SLOT(tabSelected()));

and in tabSelected() function, I check current Tab Index:tabSelected()函数中,我检查当前标签索引:

void MainWindow::tabSelected(){
    if(ui->tabWidget->currentIndex()==0){

        // Do something here when user clicked at tab1

    }
    if(ui->tabWidget->currentIndex()==3){

        // Do something here when user clicked at tab4

    }
}

This is how I solved it这就是我解决它的方法

void MainWindow::on_tabWidget_currentChanged(int index)
{
    if (lockTabs) ui->tabWidget->setCurrentIndex(lockedTab);
}

On click of a button, I set lockTabs to true and save the current tab index to lockedTab (int).单击按钮时,我将 lockTabs 设置为 true 并将当前选项卡索引保存到 lockedTab (int)。 No matter what tab you click it will just throw you back to the locked tab.无论您单击哪个选项卡,它都会让您返回锁定的选项卡。

I do agree with the first comment that disabling tabs is the better way tho.我确实同意第一个评论,即禁用选项卡是更好的方法。 This is my solution for disabling tabs:这是我禁用选项卡的解决方案:

void MainWindow::lockTabs(int except){
    for (int i=0; i<ui->tabWidget->count(); i++) {
        if (i!=except) ui->tabWidget->setTabEnabled(i, false);
    }
}

void MainWindow::unlockTabs() {
    for (int i=0; i<ui->tabWidget->count(); i++) {
        ui->tabWidget->setTabEnabled(i, true);
    }
}

In your header, declare:在您的标题中,声明:

QWidget *saveTab

Create a routine tabChanged have the slot for the currentChanged() signal.创建一个例程tabChangedcurrentChanged()信号的插槽。 Then:然后:

void pkgName::tabChanged
//"ask your question"
if "bad reply"
  // This is where you'll "set back to your old tab"
  ui->tabWidget->setCurrentWidget(savedWidget)
end if
savedWidget = ui->tabWidget-> getCurrentWidget() 
// Process

Using a regular QTabWidget and flipping back to previous tab after currentChanged was emitted if change was forbidden does not look right for user as the new tab is made visible before the previous one is re-selected, this is due to QTabWidget informing the tab "changed", not "is about to change".如果禁止更改,则使用常规QTabWidget并在发出currentChanged后翻回上一个选项卡对用户来说看起来QTabWidget ,因为在重新选择前一个选项卡之前使新选项卡可见,这是由于QTabWidget通知选项卡“已更改” ”,而不是“即将改变”。

One option is to create your own QTabWidget .一种选择是创建您自己的QTabWidget Thanks to QTabBar , this is pretty obvious.感谢QTabBar ,这很明显。

You'll also need to create QTabWidget like function to use it "like" a QTabWidget , but there's not so many function you'll need.您还需要创建QTabWidget像函数来使用它“喜欢”一个QTabWidget ,但有没有这么多的功能,你需要。

Here is an example of QTabWidget like class with a aboutToChangeTab signal being emitted informing that tab is about to be changed, one may set allowed to false to forbid tab change.这是一个类似QTabWidget类的示例, QTabWidget发出aboutToChangeTab信号,通知选项卡即将更改,可以将allowed设置为false以禁止选项卡更改。

#pragma once

#include <QWidget>

class QTabBar;
class QStackedWidget;

class SmartTabWidget : public QWidget
{
    Q_OBJECT

    typedef QWidget baseClass;

public:
    SmartTabWidget( QWidget* parent );

    int addTab(QWidget* page, const QString& label);
    int addTab(QWidget* page, const QIcon& icon, const QString& label);

    int currentIndex() const;
    QWidget* widget( int index );

signals:
    void aboutToChangeTab( QWidget* curTab, QWidget* nextTab, bool* allowed );

private slots:
    void tryToChangeTab( int index );

private:
    QTabBar* m_tab;
    QStackedWidget* m_stack;
};

And:和:

#include "smart_tab_widget.h"

#include <QTabBar>
#include <QStackedWidget>
#include <QVBoxLayout>
#include <QIcon>

SmartTabWidget::SmartTabWidget( QWidget* widget ) :
    baseClass( widget )
{
    new QVBoxLayout( this );
    layout()->setContentsMargins( 0,0,0,0 );

    layout()->addWidget( m_tab = new QTabBar(this) );
    layout()->addWidget( m_stack = new QStackedWidget(this) );

    connect(m_tab, SIGNAL(currentChanged(int)), this, SLOT(tryToChangeTab(int)));
}

int SmartTabWidget::addTab(QWidget* page, const QString& label)
{
    return addTab( page, QIcon(), label );
}

int SmartTabWidget::addTab(QWidget* page, const QIcon& icon, const QString & label)
{
    m_stack->addWidget( page );

    int index = m_tab->addTab( icon, label );
    assert( m_stack->count() == index+1 );

    return index;
}

int SmartTabWidget::currentIndex() const
{
    return m_tab->currentIndex();
}

QWidget* SmartTabWidget::widget( int index )
{
    return m_stack->widget( index );
}

void SmartTabWidget::tryToChangeTab( int index )
{
    int currentIndex = m_stack->currentIndex();
    bool canChange = true;
    emit aboutToChangeTab( m_stack->widget( currentIndex ),
                           m_stack->widget( index ),
                           &canChange );

    if ( canChange )
    {
        m_stack->setCurrentIndex( index );
    }
    else
    {
        // prevent this function to be called again
        bool blocked = m_tab->blockSignals( true );
        // unselect requested tab as change is not allowed
        m_tab->setCurrentIndex( currentIndex );
        m_tab->blockSignals( blocked );
    }
}

One can connect aboutToChangeTab to a slot ( allowTabChange ) and do something like:可以将aboutToChangeTab连接到插槽( allowTabChange )并执行以下操作:

void MyWidget::allowTabChange( QWidget* curTab, QWidget* nextTab, bool* allowed )
{
    if ( !canChange( curTab, nextTab ) )
        *allowed = false;
}

There is a simple solution with event filters that doesn't require to subclass QTabWidget.有一个简单的解决方案,它不需要继承 QTabWidget 的事件过滤器。 In my case I needed to disable switching to a particular tab在我的情况下,我需要禁用切换到特定选项卡

ui->tabWidget->tabBar()->installEventFilter(this);

then:然后:

bool MainWindow::eventFilter(QObject* watched, QEvent* event)
{
    if(watched == ui->tabWidget->tabBar())
    {
        if(event->type() == QEvent::MouseButtonPress)// || event->type() == QEvent::MouseButtonRelease)
        {
            auto pos = dynamic_cast<QMouseEvent*>(event)->pos();
            auto index = ui->tabWidget->tabBar()->tabAt(pos);
            if(ui->tabWidget->widget(index) == ui->addButtonTab)
                return true; // cancell event
        }
    }
    return QMainWindow::eventFilter(watched, event);
}

At the stage of mouse click it is possible to retrieve index of a currently selected tab and prepare it for being switched(or cancel switching as done in my example).在鼠标单击阶段,可以检索当前选定选项卡的索引并准备切换(或取消切换,如我的示例中所做的那样)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM