【问题标题】:how to delete table row on right click如何在右键单击时删除表格行
【发布时间】:2019-07-26 02:31:58
【问题描述】:

我正在尝试这样做,以便您可以右键单击表格小部件中的一行并将其删除。我找不到一个可行的例子。非常感谢任何帮助。

这是我更新的代码以更好地可视化:

bool MainWindow::eventFilter(QObject *obj, QEvent *event) {
    if (obj == ui->tableWidgetOther->viewport() ) {
        QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
        if (mouseEvent->button() == Qt::RightButton) {
            QTableWidgetItem *cell = ui->tableWidgetOther->currentItem();
            int row = cell->row();
            ui->tableWidgetOther->removeRow(row);
        }
    }
}

【问题讨论】:

    标签: c++ qt qt5 qtablewidget


    【解决方案1】:

    当您使用 Qt 设计器创建QTableWidget 并设置行和列时,不一定每个网格都关联一个QTableWidgetItem,因此最好不要使用currentItem()

    因此,您应该使用QModelIndex,使用indexAt() 方法和事件位置,而不是使用QTableWidgetItem

    由于要求是右键单击,因此使用cellClicked 信号是不正确的。在这种情况下,我将使用eventFilter()

    ui->tableWidget->viewport()->installEventFilter(this);
    
    bool MainWindow::eventFilter(QObject *obj, QEvent *event) { 
        if (obj == ui->tableWidget->viewport() and 
            event->type() == QEvent::MouseButtonPress) {
            QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
            if (mouseEvent->button() == Qt::RightButton) {
                QModelIndex ix = ui->tableWidget->indexAt(mouseEvent->pos());
                if(ix.isValid())
                    ui->tableWidget->removeRow(ix.row());
            }
        }
        return QMainWindow::eventFilter(obj, event);
    }
    

    如果你想构建自己的QTableWidget,那么在mousePressEvent()方法中实现相同的逻辑:

    void TableWidget::mousePressEvent(QMouseEvent *event)
    {
        if(event->buttons() == Qt::RightButton){
            QPoint p = viewport()->mapFromGlobal(mapToGlobal(event->pos()));
            QModelIndex ix = indexAt(p);
            if(ix.isValid())
                removeRow(ix.row());
        }
        QTableWidget::mousePressEvent(event);
    }
    

    【讨论】:

    • 谢谢!我通常用 C# 而不是 C++ 编码,所以你让它很容易理解,现在当我右键单击该行时它可以工作
    【解决方案2】:

    首先,引发警告/错误“控制到达非 void 函数的末尾”,因为您没有返回任何内容,而 eventFilter() 应该返回 bool

    其次,为什么不直接使用mousePressEvent()mouseReleaseEvent()

    我认为您应该覆盖 tableWidgetOther 对象的这些方法之一,并从此处执行删除任务。

    它可能看起来像:

    void TableWidgetOther::mousePressEvent(QMouseEvent * event)
    {
        if(event->buttons() == Qt::RightButton)
        {
            // TODO: remove the current cell (or do whatever you want).
        }
    }
    

    我在这里假设您将您的 tableWidgetOther 对象作为继承 QTableWidgetTableWidgetOther 类的实例(仅用于示例)。

    如果您想处理鼠标事件,我认为这是最简单的解决方案(仅我个人意见)。

    希望对你有帮助。

    【讨论】:

    • 感谢您的回复!我还是 QT 的新手,有人告诉我 void TableWidgetOther 是未声明的标识符?如何解决该错误
    • @SebastianShearer 是的,因为您没有任何 TableWidgetOther 类。这是关于创建一个继承 QTableWidget 而不是直接 QTableWidget 的类。但是接受的答案要完整得多:)
    【解决方案3】:

    由于您希望检测右键单击,一种方法是在 QTableWidget 的视口上安装事件过滤器:

    ui->tableWidget->viewport()->installEventFilter(this)
    

    您可以在 mainWindow 的构造函数中执行此操作。

    此事件过滤器允许我们查看是否在我们的表上发生了 mousePressEvent,然后我们可以从中检索行。这意味着我们需要一个 eventFilter 方法来处理我们的 mousePressEvent 并确保它在我们的 tableWidget 上:

    mainWindow::eventFilter(QObject *obj, QEvent *event) { 
        if (obj == ui->tableWidget->viewport() ) {
            QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event)
            if (mouseEvent->button() == Qt::RightButton) {
                QTableWidgetItem *cell = ui->TableWidget->currentItem();
                int row = cell->row()
                ui->tableWidget->removeRow(row)
            }
        }
        return QMainWindow::eventFilter(obj, event);
    }
    

    让我们知道这是否有效!

    【讨论】:

    • 当我单击表格并在编辑器中告诉我“控件到达非 void 函数的末尾”时,它给了我一个崩溃我将我编辑的代码添加到了帖子中,这样你就可以更好地想象我是如何输入它的出来。
    • 我忘记在 eventFilter 代码中添加返回。如果其他答案之一不起作用,请再看一遍!
    • @RakeebHossain 您的代码还有另一个错误,您假设唯一的事件是 QMouseEvent,如果在此之前发送了另一个像 FocusEvent 这样的事件,那么如果您检查我的实现,mouseEvent 将生成错误我使用事件的 type() 进行验证。
    【解决方案4】:

    您可以使用cellClicked(int, int) 信号并将其连接到将删除该行的插槽。例如:

    void MainWindow::deleteRow(int row, int column)
    {
        removeRow(row);
        Q_UNUSED(column)
    }
    
    connect(ui->tableWidget, SIGNAL(cellClicked(int, int)), this, SLOT(deleteRow(int, int)));
    

    编辑:

    使用新的连接语法看起来像这样:

    connect(ui->tableWidget, &QTableWidget::cellClicked, this, &MainWindow::deleteRow);
    

    希望这会有所帮助。

    【讨论】:

    • 很好的建议!但我认为您不应该将旧的连接语法与 SIGNAL 和 SLOT 宏一起使用。你应该写:connect(ui-&gt;tableWidget, &amp;QTableWidget::cellClicked, this, &amp;MainWindow::deleteRow);(假设tableWidgetQTableWidget)。
    • 我犯了一个错误,我忘记了OP要使用右键单击,所以cellClicked()无法完成这项工作,正如@eyllanesc所说。
    猜你喜欢
    • 2019-12-25
    • 2015-01-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-28
    • 2019-07-30
    • 2017-03-24
    • 2012-07-18
    相关资源
    最近更新 更多