简体   繁体   中英

Qt5 detecting widgets under an other one

I am trying to detect if two widgets are overlapping without any success. Here is a minimal example:

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

class MainWindow : public QMainWindow
{
    Q_OBJECT

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

private slots:
    void hover();
};

#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "hover.h"
#include <QPushButton>

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
{
    QPushButton* pb = new QPushButton("Button", this);
    setCentralWidget(pb);
    connect(pb, SIGNAL(clicked(bool)), this, SLOT(hover()));
}

MainWindow::~MainWindow() {}

void MainWindow::hover()
{
    Hover* h = new Hover(centralWidget());
    h->show();
}

hover.h

#ifndef HOVER_H
#define HOVER_H

#include <QDialog>

class QMoveEvent;

class Hover : public QDialog
{
public:
    Hover(QWidget* w, Qt::WindowFlags f = Qt::WindowFlags());

protected:
    void moveEvent(QMoveEvent* event);

private:
    QWidget* w;
};

#endif // HOVER_H

hover.cpp

Hover::Hover(QWidget* w, Qt::WindowFlags f) : QDialog(nullptr, f), w(w)
{
    setAttribute(Qt::WA_DeleteOnClose);
}

void Hover::moveEvent(QMoveEvent* event)
{
    if(qApp->widgetAt(event->pos()) == w)
    {
        qDebug() << "YES"; // Never triggered.
    }
}

As you can see above, I re implemented the QDialog::moveEvent of the Hover class in order to get notified when the widgets is dragged onto the MainWindow 's QPushButton . However, when I move the dialog over the button, it does not work.

Does anyone have a solution?

Thanks for your answers.

Edit

I played around with eyllanesc's code. It works well for the above sample. However I noticed something weird when using QPropertyAnimation . In fact, the global coordinates of the QPushButton seem to be wrong. The x coordinate of the QPushButton is slightly offset to the right. Just replace the code of the MainWindow by the following one:

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
class QPushButton;
class Hover;

class MainWindow : public QMainWindow
{
    Q_OBJECT

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

private slots:
    void hover();

private:
    QPushButton* pb;
    Hover* h;
};

#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "hover.h"
#include <QPushButton>

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
{
    pb = new QPushButton("Button", this);
    connect(pb, SIGNAL(clicked(bool)), this, SLOT(hover()));
}

MainWindow::~MainWindow() {}

void MainWindow::hover()
{
    QPropertyAnimation* a = new QPropertyAnimation(pb, "geometry");
    a->setDuration(1000);
    a->setStartValue(QRect(0, 0, pb->width(), pb->height()));
    a->setEndValue(QRect(50, 50, pb->width(), pb->height()));
    a->start();
    h = new Hover(pb);
    h->setGeometry(300, 300, 50, 100);
    h->show();
}

Does that happen to you as well? If so, does anyone have an explanation?

Thanks again for your answers.

Instead of using the widgetAt() function we can use the intersection of its areas (according to docs widgetAt() is slow)

For this we use the global position through the function mapToGlobal() and pos() , and the function size() , after that we check if there is an intersection

void Hover::moveEvent(QMoveEvent*)
{
    if(!visibleRegion().isNull() && w)
    {
       QRect RectW(w->mapToGlobal(QPoint(QPoint(0,0))), w->size()) ;
       QRect RectHover = QRect(pos(), size());
       if(!RectW.intersected(RectHover).isEmpty())
           qDebug()<<"yes";
       else {
           qDebug()<<"no";
       }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM