2016-09-13 2 views
1

J'ai hérité de QQuickWindow et créé une fenêtre sans cadre qui peut être déplacée par glisser. Dans ma fenêtre, j'ai mis un élément Slider. Le problème est que le Slider transmet les événements à la fenêtre parente et quand j'essaie de changer la valeur sur le curseur, la fenêtre se déplace le long. Voici comment il se comporte:Rendre l'élément/le contrôle QML accepte les événements sans les transmettre au parent

enter image description here

Est-il possible de faire le curseur accepter les événements de souris et ne pas les transmettre à la fenêtre?

Voici mon code:

main.cpp

#include <QGuiApplication> 
#include <QQmlApplicationEngine> 
#include <QUrl> 

#include "mywindow.h" 

int main(int argc, char *argv[]) 
{ 
    QGuiApplication app(argc, argv); 

    qmlRegisterType<MyWindow>("mycustomlib", 1, 0, "MyWindow"); 

    QQmlApplicationEngine engine; 
    engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); 

    return app.exec(); 
} 

main.qml

import QtQuick 2.7 
import QtQuick.Window 2.2 
import QtQuick.Controls 1.4 
import mycustomlib 1.0 

MyWindow { 
    width: 300 
    height: 180 
    visible: true 
    x: 250 
    y: 250 
    color: "beige" 

    Slider { 
     anchors.fill: parent 
     value: 0.5 
    } 
} 

mywindow.h

#ifndef MYWINDOW_H 
#define MYWINDOW_H 

#include <QQuickWindow> 

class MyWindow : public QQuickWindow 
{ 
    Q_OBJECT 

public: 
    MyWindow(QWindow *pParent = Q_NULLPTR); 

protected: 
    virtual void mouseMoveEvent(QMouseEvent *e) Q_DECL_OVERRIDE; 
    virtual void mousePressEvent(QMouseEvent *e) Q_DECL_OVERRIDE; 
    virtual void mouseReleaseEvent(QMouseEvent* e) Q_DECL_OVERRIDE; 

private: 
    bool m_move; 
    QPoint m_initialMouseClickPos; 
}; 

#endif // MYWINDOW_H 

mywindow.cpp

#include "mywindow.h" 

#include <QDebug> 
#include <QCursor> 

MyWindow::MyWindow(QWindow *pParent) : 
    QQuickWindow(pParent), 
    m_move(false) 
{ 
    setFlags(Qt::FramelessWindowHint); 
} 

void MyWindow::mouseMoveEvent(QMouseEvent *e) 
{ 
    if (m_move) { 
     const QPoint newMousePosition = e->pos() - m_initialMouseClickPos + position(); 
     setPosition(newMousePosition); 
    } 

    QQuickWindow::mouseMoveEvent(e); 
} 

void MyWindow::mousePressEvent(QMouseEvent *e) 
{ 
    if (e->button() == Qt::LeftButton) 
    { 
     m_initialMouseClickPos = e->pos(); 
     m_move = true; 
    } 

    QQuickWindow::mousePressEvent(e); 
} 

void MyWindow::mouseReleaseEvent(QMouseEvent *e) 
{ 
    if (e->button() == Qt::LeftButton) 
    { 
     m_move = false; 
    } 

    QQuickWindow::mouseReleaseEvent(e); 
} 

Répondre

1

Le problème est que QQuickWindow::mouseXxxEvent() délivre l'événement à l'élément auquel il appartient. Vous avez remplacé les gestionnaires d'événements, faites votre d'abord, puis transmettez l'événement à QQuickWindow. Par conséquent, le Slider reçoit les événements après vous avez effectué votre traitement d'événement personnalisé. N'appelez pas l'implémentation de la classe de base lorsque vous ne voulez pas qu'elle envoie l'événement aux éléments, ou appelez l'implémentation de la classe de base en premier et effectuez votre traitement personnalisé uniquement si l'événement n'a pas été accepté.

void MyWindow::mousePressEvent(QMouseEvent *e) 
{ 
    QQuickWindow::mousePressEvent(e); 

    if (!e->isAccepted() && e->button() == Qt::LeftButton) 
    { 
     m_initialMouseClickPos = e->pos(); 
     m_move = true; 
    } 

} 
+0

Mais pouvez-vous me dire, pourquoi exactement le même code (sans votre correctif) mais en utilisant «QtWidgets» fonctionne bien? Pourquoi avec des widgets si je fais la manipulation en dernier, tout fonctionne bien? C'est à dire. si j'ai un QWidget et que je remplace tous ces gestionnaires d'événements et que je mets un QPushButton dessus tout fonctionne comme votre code (c'est-à-dire lorsque vous cliquez sur le QPushButton, l'événement ne parvient pas au widget parent). J'ai vraiment besoin de le savoir car il semble que le paradigme de propagation d'événements soit différent de widgets à qtquick. Merci! –

+1

'QWindow' est le point d'entrée de niveau inférieur pour les événements du système de fenêtrage, et' QWidget' n'est pas un 'QWindow'. Le QWidgetWindow sous-jacent, qui achemine l'événement vers le QWidget approprié, est caché de vous.Même si vous pouvez y accéder via 'QWidget :: windowHandle()', avec les widgets, vous surchargez les gestionnaires d'événements au niveau de 'QWidget', pas au niveau de' QWindow'. Vous pouvez penser à la livraison d'événements 'QQuickWindow' similaire à celle de' QGraphicsView'. Les gestionnaires d'événements de la vue fournissent les événements à sa scène/éléments. – jpnurmi

+1

Ou, pour le dire autrement, quand un 'QWindow' reçoit un événement souris, rien ne l'a encore traité. Lorsqu'un QWidget reçoit un événement souris, ses enfants ont déjà été traités et aucun d'eux ne l'a accepté. Si des enfants avaient accepté l'événement, le widget ne le recevrait pas. – jpnurmi

1

Le curseur n'est pas un widget, et il ne traite pas des événements tels que des widgets font :(

Pour mettre en œuvre glisser sur un QQuickWindow, vous pourriez avoir une zone de souris dans Qt Quick, derrière les contrôles, et l'a fait glisser vers l'avant vers un objet auxiliaire qui fait ensuite glisser la fenêtre.

+0

Merci pour l'intérêt! * vous pourriez avoir une zone de souris dans Qt Quick, derrière les contrôles, et l'avoir fait glisser vers un objet auxiliaire qui fait ensuite glisser la fenêtre * - oui mais cela semble très hacky ... 'QQuickWindow' a tous les événements de la souris doit implémenter élégamment ce genre de fonctionnalité ... et si vous voulez étendre cela à la fonctionnalité de redimensionnement des fenêtres, les choses deviennent plus complexes ... –

+0

'QQuickWindow' ne sait probablement rien de la géométrie des contrôles Qt Quick, ceci est géré en interne par Qt Quick ... –