如何将 QMainWindow 鼠标点击位置传递给 QGraphicsView

Posted

技术标签:

【中文标题】如何将 QMainWindow 鼠标点击位置传递给 QGraphicsView【英文标题】:How to Pass QMainWindow mouse clicked position to QGraphicsView 【发布时间】:2016-09-06 14:49:52 【问题描述】:

我有一个这样的显示窗口:

上面的显示小部件是QGraphicsView 小部件(它们在QGridLayout 中),我想要实现的是:

当用户单击MainWindow 时,我想抓住该单击位置并确定哪个QGraphicsView 小部件包含该位置并将所选QGraphicsView 小部件的边框设置为绿色。并且一次只能选择一个QGraphicView 小部件。

谁能给我一些想法?

谢谢

【问题讨论】:

只需重新实现mousePressEvent。焦点处理也可以是一个案例。 @ilotXXI 在MainWindow 或每个QGraphicView 小部件中重新实现mousePressEvent 【参考方案1】:

您可以将installEventFilter 用于您的QGraphicsViews 并检测它们上的鼠标按下事件。因此,您可以根据需要定义当前视图并为其制作边框。小例子:

main.cpp

#include "mainwindow.h"
#include <QApplication>

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

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

主窗口.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QGraphicsView>

namespace Ui 
class MainWindow;


class MainWindow : public QMainWindow

    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

public:
    bool eventFilter(QObject* watched, QEvent* event) override;


private:
    Ui::MainWindow *ui;
    QGraphicsView* view1_;
    QGraphicsView* view2_;
    QGraphicsView* selectedView_;
;

#endif // MAINWINDOW_H

主窗口.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QGridLayout>
#include <QMessageBox>
#include <QDebug>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow),
        view1_(nullptr),
        view2_(nullptr),
        selectedView_(nullptr)

    ui->setupUi(this);
        QGridLayout* grid = new QGridLayout(this->centralWidget());
        view1_ = new QGraphicsView(this);
        view2_ = new QGraphicsView(this);
        grid->addWidget(view1_, 0, 0);
        grid->addWidget(view2_, 0, 1);
        view1_->viewport()->installEventFilter(this);
        view2_->viewport()->installEventFilter(this);


MainWindow::~MainWindow()

    delete ui;


bool MainWindow::eventFilter(QObject* watched, QEvent* event)

    qDebug() << event->type();
    if (event->type() == QEvent::MouseButtonPress)
    
        if (watched == view1_->viewport())
            selectedView_ = view1_;
            QMessageBox::information(this, "!", "First");
            return false;
        
        else if (watched == view2_->viewport())
            selectedView_ = view2_; 
            QMessageBox::information(this, "!", "Second");
            return false;
        
    
    return QMainWindow::eventFilter(watched, event);

【讨论】:

感谢您的回答。还有一个问题:如果我允许用​​户在QGridLayout 中动态分配QGraphicsView 小部件的数量。那么,是否有合适的方法来处理相同的选择问题?您当前的实现是针对固定数量的QGraphicsView 小部件。 如果用户动态设置 QGraphicsViews 的数量,approch 将与两个小部件相同。为每个 QGraphicsView 设置事件过滤器,并在 eventFilter 方法中确定选择了哪个小部件。我没有看到问题。你能描述一下有什么不同吗? 我在这里有问题。如果用户动态设置QGraphicsViews 的数量,例如 9,然后用户将其更改为 4。我是否应该删除之前的 9 个QGraphicsViews 并重新新建 4 个QGraphicsViews 并将它们放入向量中。 (std::vector&lt;QGraphicsView *&gt;)。或者有没有更聪明的方法来做QGraphicsViews的动态分配 如果你知道 QGraphicsViews 的最大数量,用户可以选择,例如 9,你可以创建这样数量的 QGraphicsViews 对象并将它们放在向量中。当用户将数字更改为 4 时,您可以从布局中删除一些 QGraphicsView,但不能从矢量中删除。我认为,每次都重新创建对象,当用户更改次数不好时,最好创建一次对象,然后重复使用。【参考方案2】:

如果您只想更改鼠标悬停时的边框颜色,则不需要如此复杂的编程。 Qt supports 样式表,就像 CSS 一样。

在这种情况下,将以下样式表附加到您的 MainWindow 就足够了。

QGraphicsView:hover 
    border-style: solid;
    border-width: 2px;
    border-color: green;

有两种方法可以做到这一点:

使用设计器:首先选择MainWindow,然后在其属性面板中单击styleSheet,然后复制并粘贴样式表。

使用代码:使用QMainWindowsetStyleSheet(...)方法,并将样式表作为字符串传递。

【讨论】:

感谢您的回答。实际上,我设置了一个QComboBox 以允许用户选择他们需要的QGraphicsView 小部件的数量。比如用户设置QComboBox为9,那么上图就是结果。然后,我想确定用户单击了哪个QGraphicsView 小部件,并将视频流插入到选定的QGraphicsView 小部件。 @Johnnylin 很简单,看看QSignalMapper就行了。对于边框样式,样式表是可以的。

以上是关于如何将 QMainWindow 鼠标点击位置传递给 QGraphicsView的主要内容,如果未能解决你的问题,请参考以下文章

qt 画多边形(实现鼠标拖动节点)

html鼠标点击出现小球

将鼠标事件从 QGraphicsItem 传递给 QGraphicsScene

如何在Qt中将点击事件传递给下面的兄弟?

如何将 Qt 鼠标事件转发到 QQuickView?

如何将类实例传递给 LowLevelMouseProc?