首页 > 解决方案 > 如何防止 Qt 中的 currentCellChanged 信号或跳过“处理”?

问题描述

我有一个菜单项和一个带有插槽的 QTableWidget:

connect(ui->actionOpen, &QAction::triggered, this, &MainWindow::open);
connect(ui->fooTableWidget, SIGNAL(currentCellChanged(int, int, int, int)), 
    this, SLOT(checkFooChanged(int, int, int, int)));

打开文件时,我尝试通过使用标志变量来防止在插槽中执行任何操作:

void MainWindow::open()
{
    flag = false;
    ui->fooTableWidget->insertRow(0);
    ui->fooTableWidget->insertRow(1);
    flag = true;
}

void MainWindow::checkFooChanged(int row, int, int previousRow, int)
{
    if (flag && row != previousRow)
    {
        qDebug() << "processing";
        // do something here 
    }
}

但是,当我单击“打开”时,“处理”部分仍然会在打开完成后运行。有没有更可靠的方法可以暂时禁用 checkFooChanged “处理”,直到 open 完全完成?注意:当控制权返回给用户时,我需要将标志设置回 true,以便在用户更改 fooTableWidget 上的行时调用“处理”。

更新

这是一个最小的示例以及 eyllanesc 的建议:

#include <QDebug>
#include <QTableWidget>
#include <QFileDialog>
#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    ui->fooTableWidget->setColumnCount(1);
    connect(ui->actionOpen, &QAction::triggered, this, &MainWindow::open);
    connect(ui->fooTableWidget, SIGNAL(currentCellChanged(int, int, int, int)),
        this, SLOT(checkFooChanged(int, int, int, int)));
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::checkFooChanged(int row, int, int previousRow, int)
{
    qDebug() << "processing: " << row << ' ' << previousRow;
}

void MainWindow::open()
{
    QString fileName;
    fileName = QFileDialog::getOpenFileName(this, tr("Open"), "", "(*.emx)");
    if (fileName.isEmpty())
        return;
    qDebug() << "file " << fileName;
    ui->fooTableWidget->blockSignals(true);
    ui->fooTableWidget->setRowCount(0);
    ui->fooTableWidget->insertRow(0);
    QTableWidgetItem *item;
    item = new QTableWidgetItem();
    ui->fooTableWidget->setItem(0, 0, item);
    item->setText("Oh hi there!");
    ui->fooTableWidget->blockSignals(false);
}

所以问题似乎是由主窗口重新获得焦点引起的。

标签: c++qtqt5qtablewidget

解决方案


在您的情况下,我看到您想currentCellChanged暂时禁用信号触发器,为此您必须使用blockSignals()

void MainWindow::open()
{
    ui->fooTableWidget->blockSignals(true);
    ui->fooTableWidget->insertRow(0);
    ui->fooTableWidget->insertRow(1);
    ui->fooTableWidget->blockSignals(false);
}

更新:

正如您所指出的,问题似乎是由焦点的变化引起的,当您打开对话框时,焦点被消除,当焦点关闭时,它返回到centralWidget,产生意想不到的效果,一个可能的解决方案是在MainWindow. _

void MainWindow::open()
{
    QString fileName;
    fileName = QFileDialog::getOpenFileName(this, tr("Open"), "", "(*.emx)");
    if (fileName.isEmpty())
        return;

    setFocus(); //<--

    ui->fooTableWidget->blockSignals(true);
    ui->fooTableWidget->setRowCount(0);
    ui->fooTableWidget->insertRow(0);
    QTableWidgetItem *item = new QTableWidgetItem();
    ui->fooTableWidget->setItem(0, 0, item);
    item->setText("Oh hi there!");
    ui->fooTableWidget->blockSignals(false);
}

推荐阅读