Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Problem with QT MousePressedEvent / MouseMoveEvent
Forum Updated to NodeBB v4.3 + New Features

Problem with QT MousePressedEvent / MouseMoveEvent

Scheduled Pinned Locked Moved Unsolved General and Desktop
12 Posts 2 Posters 5.2k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • mrjjM mrjj

    Hi and welcome to the forums.
    Dont worry, your english is fine.
    Im not sure however, what you mean by
    " MousePressedEvent in an specific period of time (= so that clicked Labels don´t get clicked back...). "

    You mean like, once the user have clicked a clickLabel one time, he should not able to click on it again until you
    sort of say "reset board/new game" so all are free again ?
    Im not sure what the "clicked back" means :)

    btw: is this your label?
    https://wiki.qt.io/Clickable_QLabel

    T Offline
    T Offline
    tianstar
    wrote on last edited by
    #3

    Thanks for your fast answer. Yes you are right! I took those labels.```
    //#ifndef CLICKABLELABEL_H
    #define CLICKABLELABEL_H

    #include <QLabel>
    #include <QWidget>
    #include <Qt>
    #include <QString>

    class ClickableLabel : public QLabel {
    Q_OBJECT

    public:

    bool pressed;
    QString color = "black";
    explicit ClickableLabel(QWidget* parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags());
    ~ClickableLabel();
    

    signals:
    void clicked();

    protected:
    void mousePressEvent(QMouseEvent* event);
    void mouseMoveEvent(QMouseEvent* event); // to implement

    };

    #endif // CLICKABLELABEL_H

    
    

    #include <clickablelable.h>
    #include <QMouseEvent>

    ClickableLabel::ClickableLabel(QWidget* parent, Qt::WindowFlags f)
    : QLabel(parent)
    {
    pressed = false;
    }

    ClickableLabel::~ClickableLabel() {}

    void ClickableLabel::mousePressEvent(QMouseEvent *event) {

    if (text() == " "){
        pressed = true;
        setText("  ");
        setStyleSheet(QString("QLabel { background-color:").append(color).append(QString(" }")));
    }
    else{
        pressed = false;
        setText(" ");
        setStyleSheet(QString("QLabel { background-color: white }"));
    }
    
    emit clicked();
    

    }

    void ClickableLabel::mouseMoveEvent(QMouseEvent *event) // to implement
    {
    if(event->buttons() == Qt::LeftButton)
    {
    emit clicked();

     }
    

    }

    I wanted to say with :
    " MousePressedEvent in an specific period of time (= so that clicked Labels don´t get clicked back...). " 
    that if I pressed my Mouse Button and move it around my Gridlayout, I want to click all label I crossed once.
    
    I thought about doing it like : MouseMoveEvent = several MousePressedEvents and to don´t click any label twice I need to say that those click´s have a good timing.. :/ ? But I dont have any idea to implement this, I`ll have to buy me one QT Book I guess.
    
    
    "You mean like, once the user have clicked a clickLabel one time, he should not able to click on it again until you
    sort of say "reset board/new game" so all are free again ?
    Im not sure what the "clicked back" means :)" - so this is totally right !
    
    How can I fix that ? :D
    1 Reply Last reply
    0
    • mrjjM Offline
      mrjjM Offline
      mrjj
      Lifetime Qt Champion
      wrote on last edited by
      #4

      Hi
      So you press mouse button and you can then move cursor around and cell will be painted when mouse enter?
      The click label can handle it for you.
      add a
      bool isPainted=false;
      to class .h

      Then in mouseMoveEvent
      if(event->buttons() == Qt::LeftButton && ! isPainted )
      isPainted=true;

      than also a new function in public in class .h

      void Reset() {
      isPainted=false;
      update();
      }

      Then in main program, loop over all clicklabels in your QList
      and call Reset() on each. ( when you want to clear board)

      I would also add a paintEvent and draw the background there and dont use stylesheet for it but
      that is just to make code easier as currently it will only color background when u click on it and
      what you seem to want is not clicking it but simply move into the cell and then its painted. (correct ?)

      1 Reply Last reply
      1
      • mrjjM Offline
        mrjjM Offline
        mrjj
        Lifetime Qt Champion
        wrote on last edited by mrjj
        #5

        Hi
        Here is example:

        #ifndef BOARDCELL_H
        #define BOARDCELL_H
        
        #include <QWidget>
        #include <QMouseEvent>
        #include <QPainter>
        #include <QApplication>
        #include <QDebug>
        
        class BoardCell : public QWidget {
          Q_OBJECT
        public:
          explicit BoardCell(QWidget* parent = nullptr) : QWidget(parent) {
            setMouseTracking(true);
          }
        
          void Reset() {
            isPainted = false;
          }
        
        signals:
          void clicked();
        
        protected:
          void mousePressEvent(QMouseEvent* event) {
            emit clicked();
          }
          void mouseMoveEvent(QMouseEvent* event) override {
            if(! isPainted  ) {
              isPainted = true;
              update();
            }
          }
        
          bool isPainted = false;
        protected:
          virtual void paintEvent(QPaintEvent* ) override {
            QPainter p(this);
            p.setBrush(Qt::white);
            if (isPainted)
              p.setBrush(Qt::red);
            p.drawRect(QRect(0, 0, width() - 1, height() - 1));
        
          }
        };
        #endif
        

        alt text

        There is one issue. When you click on first one (AND hold), it capture mouse and the other cells wont see it.

        I also checked QApplication::mouseButtons() but it wont work
        after clicking inside first cell. ( it takes the mouse so it can get Release Event)

        Not sure how to work around that and i would normally suggest just to paint the board as one widget.
        You might be able to use the draw events or eventfilter but
        it seems kinda pointless as there are better way to design it.

        1 Reply Last reply
        2
        • T Offline
          T Offline
          tianstar
          wrote on last edited by
          #6

          Thank you very much for your work and your time!, but I am still failing hard :(. I know there are easier ways to manage the field.. but this task is the last I need to complete. I tried to rebuild your example in my Clickable Lable Class. But it doesnt work maybe cause your example ist from QWidget and mine from QLabel ? :/

          My cpp source:

          #include <clickablelable.h>
          #include <QMouseEvent>
          
          
          ClickableLabel::ClickableLabel(QWidget* parent, Qt::WindowFlags f)
              : QLabel(parent)
          {
              pressed = false;
              setMouseTracking(true);
          }
          
          ClickableLabel::~ClickableLabel() {}
          
          void ClickableLabel::reset()
          {
              isPainted = false;
              update();
          }
          
          void ClickableLabel::mousePressEvent(QMouseEvent *event) {
          
              if (text() == " "){
                  pressed = true;
                  setText("  ");
                  setStyleSheet(QString("QLabel { background-color:").append(color).append(QString(" }")));
              }
              else{
                  pressed = false;
                  setText(" ");
                  setStyleSheet(QString("QLabel { background-color: white }"));
              }
          
              emit clicked();
          }
          
          void ClickableLabel::mouseMoveEvent(QMouseEvent *ev)
          {
              if(ev->buttons() == Qt::LeftButton && ! isPainted ){
                  setStyleSheet(QString("QLabel { background-color:").append(color).append(QString(" }")));
                  setText("  ");
                  isPainted=true;
              }
          }
          
          
          
          
          

          My header file:

          /#ifndef CLICKABLELABEL_H
          #define CLICKABLELABEL_H
          
          #include <QLabel>
          #include <QWidget>
          #include <QApplication>
          #include <QString>
          #include <QMouseEvent>
          #include <QDebug>
          
          
          
          class ClickableLabel : public QLabel {
              Q_OBJECT
          
          public:
          
              explicit ClickableLabel(QWidget* parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags());
          
              ~ClickableLabel();
          
              void reset();
          
              bool pressed;
              bool isPainted = false; // Wird implementiert für die mouseMoveEvents
              QString color = "black";
          
          
          
          signals:
              void clicked();
          
          protected:
              void mousePressEvent(QMouseEvent* event);
              void mouseMoveEvent(QMouseEvent *ev) override ;
          
          };
          
          #endif // CLICKABLELABEL_H
          
          

          I would really like to avoid to start from new with painting a gameboard. I´m just using setText to manage living cells vs dead cells and the setStyleSheet for the visual representation..

          1 Reply Last reply
          0
          • mrjjM Offline
            mrjjM Offline
            mrjj
            Lifetime Qt Champion
            wrote on last edited by
            #7

            Hi
            Well the main issue is that the others are not getting a mouseMoveEvent when you are holding
            button down. the first ClickLabel you click on, steals the mouse and until you release they others
            cannot be painted.
            I could not find a way to allow it.

            Maybe others have an idea how to do it.

            1 Reply Last reply
            1
            • mrjjM Offline
              mrjjM Offline
              mrjj
              Lifetime Qt Champion
              wrote on last edited by
              #8

              You can easy make mine to QLabel too
              just replace QWidget 2 places.

              1 Reply Last reply
              1
              • T Offline
                T Offline
                tianstar
                wrote on last edited by tianstar
                #9

                " steals the mouse and until you release they others
                cannot be painted. " okay now I understand the problem.

                "You can easy make mine to QLabel too
                just replace QWidget 2 places " What does this mean ?

                Just adding an Label Variabel to my Widget and making my operations on that ? So that I can still use setText and MouseMove ? or am I wrong ?

                I am so thankful for your fast answers ! German Forums are way more unfriendly

                mrjjM 1 Reply Last reply
                0
                • T tianstar

                  " steals the mouse and until you release they others
                  cannot be painted. " okay now I understand the problem.

                  "You can easy make mine to QLabel too
                  just replace QWidget 2 places " What does this mean ?

                  Just adding an Label Variabel to my Widget and making my operations on that ? So that I can still use setText and MouseMove ? or am I wrong ?

                  I am so thankful for your fast answers ! German Forums are way more unfriendly

                  mrjjM Offline
                  mrjjM Offline
                  mrjj
                  Lifetime Qt Champion
                  wrote on last edited by mrjj
                  #10

                  @tianstar
                  Hi
                  we are super friendly here ;)

                  Its easy to change type

                  class BoardCell : public QWidget {
                  Q_OBJECT
                  public:
                  explicit BoardCell(QWidget* parent = nullptr) : QWidget(parent) {
                  setMouseTracking(true);
                  }

                  Just replace those with QLabel and it will be a QLabel instead.

                  Remember to do full rebuild as not to get funky errors. :)

                  1 Reply Last reply
                  0
                  • T Offline
                    T Offline
                    tianstar
                    wrote on last edited by
                    #11

                    Ah okay, I guess I missunderstand your example. I got more than one class in my Projekt. One for MainWindow , one GameWidget one GameRules and one for ClickableLable . I can totally delete clickable Labels and instead use your one with creating something like setText and PaintEvent. The result is that I dont have a Grid Layout full of ClickableLabels instead I´ll have a GridLayout full of small Widgets ? :)

                    Sounds good?

                    mrjjM 1 Reply Last reply
                    0
                    • T tianstar

                      Ah okay, I guess I missunderstand your example. I got more than one class in my Projekt. One for MainWindow , one GameWidget one GameRules and one for ClickableLable . I can totally delete clickable Labels and instead use your one with creating something like setText and PaintEvent. The result is that I dont have a Grid Layout full of ClickableLabels instead I´ll have a GridLayout full of small Widgets ? :)

                      Sounds good?

                      mrjjM Offline
                      mrjjM Offline
                      mrjj
                      Lifetime Qt Champion
                      wrote on last edited by
                      #12

                      @tianstar
                      Well if u change QWidget with QLabel and use that instead of your clicklabel , it should just work.
                      Yes you should be able to just replace ClickLabel with BoardCell without much fuss.

                      Sadly there is still the issue of it stealing mouse on first click

                      1 Reply Last reply
                      1

                      • Login

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • Users
                      • Groups
                      • Search
                      • Get Qt Extensions
                      • Unsolved