QWidget::mousePressEvent() not called

303 Views Asked by At

I'm working on a TreeViewNode class derived from QObject and QGraphicsItem, responsible for creating the individual nodes of the tree view (which displays a family tree) and adding them to the scene. I made sure to include the setFlag(QGraphicsItem::ItemIsSelectable); method in the class constructor and I overloaded mousePressEvent like so:

void TreeViewNode::mousePressEvent(QGraphicsSceneMouseEvent *event) {
    if (event->button() == Qt::LeftButton) {
        qDebug() << "Mouse pressed on node: " << m_node->getPatient()->get_Name().c_str();
        emit clicked(this);
    }
    QGraphicsItem::mousePressEvent(event);
}

The clicked signal is defined in the header file as void clicked(TreeViewNode* node); Then I have a updateSelectedPatient slot in MainWindow

void MainWindow::updateSelectedPatient(TreeViewNode* node) {
    selected->setSelectedPatient(node->getNode()->getPatient());
}

and the corresponding connect statement in the MainWindow constructor

connect(treeView, &TreeViewNode::clicked, this, &MainWindow::updateSelectedPatient);

When I execute I see the nodes that have been added to the scene in the view but when I click on them nothing happens (I know through debugging and also because the setSelectedPatient() method updates a widget that shows the patient information of the currently selected patient); it seems like mousePressEvent() is not being called at all.. any help would be really appreciated, thank you for your time!

edit:

//TreeViewNode.hpp
class TreeViewNode : public QObject, public QGraphicsItem {
    Q_OBJECT
    Q_INTERFACES(QGraphicsItem)

private:
    node* m_node;
    Family_tree* m_family;
    QGraphicsScene* m_scene;
    static std::set<node*> addedNodes;

protected:
    void mousePressEvent(QGraphicsSceneMouseEvent* event) override;

public:
    TreeViewNode(node* node, Family_tree* family, QGraphicsScene* scene, QGraphicsItem* parent = nullptr);
    TreeViewNode* getTreeViewNode(node* n);
    node* getNode() const;
    static void clearAddedNodes();
    void updateNode(Patient& patient);
    QRectF boundingRect() const override;
    void drawBranches(QPainter* painter);
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;

signals:
    void clicked(TreeViewNode* node);
};

//TreeViewNode.cpp
TreeViewNode::TreeViewNode(node* node, Family_tree* family, QGraphicsScene* scene, QGraphicsItem* parent) : QGraphicsItem(parent), m_node(node), m_family(family), m_scene(scene) {
    if (m_node == m_family->get_root()) {m_scene->addItem(this);}
    addedNodes.insert(m_node);
    setFlag(QGraphicsItem::ItemIsSelectable);
    qDebug() << "Scene item count: " << m_scene->items().count();

    if (m_node->getFather()) {
        auto father = m_node->getFather();
        if (addedNodes.count(father) > 0) {return;}
        TreeViewNode* fatherNode = new TreeViewNode(m_node->getFather(), family, m_scene, this);
        fatherNode->setPos(-50, -100);
    }

    if (m_node->getMother()) {
        auto mother = m_node->getMother();
        if (addedNodes.count(mother) > 0) {return;}
        TreeViewNode* motherNode = new TreeViewNode(m_node->getMother(), family, m_scene, this);
        motherNode->setPos(50, -100);
    }

    if (m_node->getSpouse()) {
        auto spouse = m_node->getSpouse();
        if (addedNodes.count(spouse) > 0) {return;}
        TreeViewNode* spouseNode = new TreeViewNode(m_node->getSpouse(), family, m_scene, this);
        spouseNode->setPos(100, 0);
    }

    int childCount = 0;
    for (auto child : m_node->getChildren()) {
        if (addedNodes.count(child) > 0) {return;}
        TreeViewNode* childNode = new TreeViewNode(child, family, m_scene, this);
        childCount++;
        double xPos, yPos;
        xPos = pos().x() + 50 + 100 * (childCount - (m_node->getChildren().size() + 1) / 2.0);
        yPos = pos().y() + 100;
        childNode->setPos(xPos, yPos);
    }
}
2

There are 2 best solutions below

6
Franco On

You could use a normal event filter and check if is it a mouse press, release or move event then cast it to a mouse event and then just do whatever you want with it.

Example:

bool YourWidgetClass::eventFilter(QObject* object, QEvent* event)
{
if (object == YourInstance)
{
   switch (event->type()) 
   {
    case QEvent::GraphicsSceneMousePress: 
    {
       QMouseEvent * mouseEvent = static_cast<QMouseEvent*>(event);
       switch (mouseEvent->button())
       {
          case Qt::LeftButton:
                // Handle left button pressed here
                return true;

            case Qt::RightButton:
                // Handle right button pressed here
                return true;
            default:
                break;
        }
        break;
     }
   }
} 

Don't forget to install the event filter on your class

YourClassCtor->installEventFilter(this)
3
BanAnn On

I don't see from your question that you need it for anything special. the signal &QGraphicsScene::selectionChanged is not enough for you? Is the item set to interactive? So simply put:

declare a slot:

public slots:
   void selectionChanged();

define the slot:

void MainWindow::selectionChanged()
{
  qDebug() << ...... ;
}

and connect:

connect(scene,&QGraphicsScene::selectionChanged,this,&MainWindow::selectionChanged);