QT:使用 QMouseEvent 从代码中选择多个 QTableWidgetItem

Posted

技术标签:

【中文标题】QT:使用 QMouseEvent 从代码中选择多个 QTableWidgetItem【英文标题】:QT: Select multiple QTableWidgetItems from code with QMouseEvent 【发布时间】:2014-05-15 17:48:38 【问题描述】:

这是我在 *** 上的第一个问题,但不是你第一次帮助我(希望你能)。

首先我必须提到,我对 C++ 的经验并不丰富,尤其是在 QT 方面,这是我的问题所在。 我在将 QMouseEvents 从代码发布(或发送)到 QTableWidget 时遇到问题。 我想向 MultiSelect QTableWidget 发送多次点击,我希望,点击后的 QTableWidgetItems 会被选中。

为了重现该问题,我创建了一个小样本。有一个按钮将“点击”发送到 QTableWidget(在我的真实应用程序中,这是由网络触发的)。 单击按钮时,会执行两次“单击”(我在调试器中也看到了),但之后只选择了第一次单击的 TableWidgetItem。 我不知道为什么第二个项目没有被选中。我希望你们中的某个人可以:-)。非常感谢您的帮助!

这里是示例代码:

int main(int argc, char *argv[])

    QApplication a(argc, argv);
    QTableWidgetExamples w;
    w.show();
    return a.exec();

QTableWidgetExample.h:

#ifndef QTABLEWIDGETEXAMPLES_H
#define QTABLEWIDGETEXAMPLES_H

#include <QtGui/QMainWindow>
#include "ui_qtablewidgetexamples.h"

QT_BEGIN_NAMESPACE  // QT_BEGIN_NAMESPACE / QT_END_NAMESPACE are not needed in Qt user code
class QTableWidget; //forward declaration
class QTableWidgetItem; //forward declaration
QT_END_NAMESPACE

class QTableWidgetExamples : public QMainWindow

    Q_OBJECT

public:
    QTableWidgetExamples(QWidget *parent = 0, Qt::WFlags flags = 0);
    ~QTableWidgetExamples();

private:
    Ui::QTableWidgetExamplesClass _ui;
    QTableWidget* _tableWidget;
    void clickItemFromCode(int index);

public slots:
    void btnClicked();
    void onItemClick(QTableWidgetItem* item);
;

#endif // QTABLEWIDGETEXAMPLES_H

QTableWidgetExample.cpp:

#include <QTableWidget>
#include <QPushButton>
#include <QVBoxLayout>
#include <QMouseEvent>
//#include <QTest>
#include "qtablewidgetexamples.h"

QTableWidgetExamples::QTableWidgetExamples(QWidget *parent, Qt::WFlags flags)
    : QMainWindow(parent, flags)

    _ui.setupUi(this);
    QVBoxLayout *vlay = new QVBoxLayout(this);

    _tableWidget = new QTableWidget(3,1,this);
    _tableWidget->verticalHeader()->hide();
    _tableWidget->horizontalHeader()->hide();
    _tableWidget->setSelectionMode(QAbstractItemView::SelectionMode::MultiSelection);
    _tableWidget->setObjectName("list_1");
    _tableWidget->setItem(0, 0, new QTableWidgetItem("Item_0"));
    _tableWidget->setItem(1, 0, new QTableWidgetItem("Item_1"));
    _tableWidget->setItem(2, 0, new QTableWidgetItem("Item_2"));
    connect(_tableWidget, SIGNAL(itemClicked(QTableWidgetItem*)), this, SLOT(onItemClick(QTableWidgetItem*)));

    QPushButton *btn1 = new QPushButton("btn1");
    connect(btn1, SIGNAL(clicked()), this, SLOT(btnClicked()));

    vlay->addWidget(_tableWidget);
    vlay->addWidget(btn1);

    QWidget * wdg = new QWidget(this);
    wdg->setLayout(vlay);
    setCentralWidget(wdg);


QTableWidgetExamples::~QTableWidgetExamples() 

void QTableWidgetExamples::onItemClick(QTableWidgetItem *item)

    bool isSel = item->isSelected();
    QString text = item->text();


void QTableWidgetExamples::btnClicked()

    clickItemFromCode(1);
    clickItemFromCode(2);   


void QTableWidgetExamples::clickItemFromCode(int rowIndex)

    float subX, subY;
    subX = subY = 0.5;

    QModelIndex index = _tableWidget->model()->index(rowIndex, 0);
    QRect rc = _tableWidget->visualRect(index); // view()->visualRect(index);
    QPoint pt(rc.x()+rc.width()*subX,rc.y()+rc.height()*subY);

    // just for debug purposes
    QTableWidgetItem* item = _tableWidget->item(rowIndex,0);
    QString itemText = item->text();

    QWidget *widget = (QWidget*) _tableWidget; //view();
    widget = widget->childAt(10,10);

    QEvent *e = QMouseEvent::createExtendedMouseEvent(QEvent::MouseMove,
            pt,widget->mapToGlobal(pt), Qt::LeftButton,Qt::LeftButton,0);
    QApplication::sendEvent(widget, e);

    e = QMouseEvent::createExtendedMouseEvent(QEvent::MouseButtonPress,
            pt,widget->mapToGlobal(pt), Qt::LeftButton,Qt::LeftButton,0);
    QApplication::sendEvent(widget, e);

    e = QMouseEvent::createExtendedMouseEvent(QEvent::MouseButtonRelease,
            pt,widget->mapToGlobal(pt), Qt::LeftButton,Qt::LeftButton,0);
    QApplication::sendEvent(widget, e);

    //QApplication::sendPostedEvents();

编辑为最广泛的答案:

不幸的是,这是一项艰巨的要求。我将我的代码注入到另一个应用程序中,在那里我读取了其中几个 QTableWidget 并通过 TCP 将它们发送到我的应用程序。到目前为止,这运作良好。现在我需要从我的应用程序中更改这些选择,这就是问题所在。我的首选选择是通过鼠标点击来完成。其背后的意图是它的行为就像用户在该应用程序中工作一样(但似乎并非如此)。 但是,如果您有其他想法,我会尝试一下。也许还有更好的东西,我还没有想到。

【问题讨论】:

模拟鼠标点击是否有硬性要求?还是您只是想将这些项目设置为选中? 感谢您的回复,mbroadst。我更新了我的问题。 【参考方案1】:

您可以使用QTableWidgetItem::setSelected() 以编程方式选择项目。所以你的代码看起来像:

void QTableWidgetExamples::clickItemFromCode(int rowIndex)

    QTableWidgetItem *item = tableWidget->item(rowIndex, 0);
    item->setSelected(true);

或者,如果你真的需要模拟鼠标点击,那么:

// NOTE: I haven't explicitly tested this, but its the general idea
void QTableWidgetExamples::clickItemFromCode(int rowIndex)

    QTableWidgetItem *item = tableWidget->item(rowIndex, 0);
    QRect visualItemRect = tableWidget->visualRectItem(item);

    QMouseEvent *event = new QMouseEvent(QEvent::MouseButtonRelease, visualItemRect.center(),     
                                         Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
    QCoreApplication::sendEvent(tableWidget, event);

【讨论】:

再次感谢您的回复。以编程方式设置 selectedItems 的第一个解决方案有效。第二个不幸的是没有。因为它没有编译,所以我将获取 QRect 的行编辑为:QRect visualRectItem = tableWidget-&gt;visualRectItem(item); 我更新了第二个例子,你需要做的就是让它工作吗?我在这里很懒惰:) 不,它只是编译,但我能够让它工作。在我的示例中,QEvent::MouseMove 设置不正确。我稍后会发布我的工作代码。还有一个问题,就是鼠标没有移动到那个位置。我的意思是,当我点击按钮时,我希望鼠标移动到被点击的项目上,但事实并非如此【参考方案2】:

我终于找到了一个可行的解决方案:

QEvent::MouseMove 设置不正确。

这里是更正的。交换这个之后,示例代码就完成了它应该做的事情。

QEvent *e = QMouseEvent::createExtendedMouseEvent(QEvent::MouseMove,
            pt,widget->mapToGlobal(pt), Qt::NoButton, Qt::RightButton, Qt::NoModifier);
QApplication::postEvent(widget, e);

如果您不需要模拟鼠标点击,@mbroadst 的第一种方法(以编程方式设置所选项目)可能是更好的选择(谢谢)。

【讨论】:

以上是关于QT:使用 QMouseEvent 从代码中选择多个 QTableWidgetItem的主要内容,如果未能解决你的问题,请参考以下文章

事件(QEvent*)与 mousePressEvent(QMouseEvent *)冲突?

Qt学习: QPaintEvent和QMouseEvent的简单程序示例

如何使用 QMouseEvent 在 QChart 中显示鼠标位置?

Qt WebEngine 模拟鼠标事件

尝试使用 QMouseEvent

Qt 窗口随鼠标移动