如何识别 QTabWidget 中当前选项卡何时发生更改?

发布于 2024-12-18 21:59:20 字数 188 浏览 2 评论 0原文

我正在使用 QTabWidget,我需要一种方法来在当前选项卡的更改实际发生之前处理它,并且如果满足某些条件,可能会取消它。当前选项卡更改后会收到 QTabWidget::currentChanged 信号,但是是否有 QTabWidget::currentChanging 信号或其他方式来实现我需要的行为?

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. 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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

ˇ宁静的妩媚 2024-12-25 21:59:20

就我而言,我像这样连接 SIGNAL 和 SLOT:

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

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

    }
}

In my case, I connect SIGNAL and SLOT like this:

//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:

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

    }
}
深海里的那抹蓝 2024-12-25 21:59:20

这就是我解决这个问题的方法

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

单击按钮,我将 lockTabs 设置为 true 并将当前选项卡索引保存到lockedTab (int)。无论您单击哪个选项卡,它都会让您返回到锁定的选项卡。

我确实同意第一个评论,即禁用选项卡是更好的方法。这是我禁用选项卡的解决方案:

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);
    }
}

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). 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);
    }
}
抹茶夏天i‖ 2024-12-25 21:59:20

有一个带有事件过滤器的简单解决方案,不需要子类化 QTabWidget。就我而言,我需要禁用切换到特定选项卡

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

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);
}

在鼠标单击阶段,可以检索当前选定选项卡的索引并准备将其切换(或取消切换,如我的示例中所做的那样)。

There is a simple solution with event filters that doesn't require to subclass 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).

终止放荡 2024-12-25 21:59:20

在标头中,声明:

QWidget *saveTab

创建一个例程 tabChanged,其中包含 currentChanged() 信号的槽。然后:

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

In your header, declare:

QWidget *saveTab

Create a routine tabChanged have the slot for the currentChanged() signal. 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
别理我 2024-12-25 21:59:20

如果禁止更改,则使用常规的 QTabWidget 并在发出 currentChanged 后翻转回上一个选项卡对于用户来说并不合适,因为新选项卡在上一个选项卡之前可见重新选择,这是由于 QTabWidget 通知选项卡“已更改”,而不是“即将更改”。

一种选择是创建您自己的QTabWidget。感谢 QTabBar,这非常明显。

您还需要创建类似 QTabWidget 的函数来“像”QTabWidget 一样使用它,但您需要的函数并不多。

下面是一个 QTabWidget 类的示例,其中发出 aboutToChangeTab 信号,通知选项卡即将更改,可以将 allowed 设置为 < code>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;
};

并且:

#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 );
    }
}

可以将 aboutToChangeTab 连接到插槽 (allowTabChange) 并执行以下操作:

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

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".

One option is to create your own QTabWidget. Thanks to QTabBar, this is pretty obvious.

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.

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.

#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:

void MyWidget::allowTabChange( QWidget* curTab, QWidget* nextTab, bool* allowed )
{
    if ( !canChange( curTab, nextTab ) )
        *allowed = false;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文