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.
  • T Offline
    T Offline
    tianstar
    wrote on last edited by tianstar
    #1

    Hey guys,

    first of all let me tell you that I am really new in programming with QT and C++ and that my english is very bad, sorry for that!

    I tried to implement a 2D game with an Menu Bar. My Classes are already done. My only Problem is the GUI especially my ClickableLabels. My gameboard needs to be Clickable (MousePressedEvent) and as well MousePressed + MouseMoveEvent.
    I implemented a QList to coordinate my dynamic amount of Clickable Labels which are shown in a Gridlayout on the GUI.

    What I need is a function which realises MousedPressedEvent and MouseMoveEvent as MousePressedEvent in an specific period of time (= so that clicked Labels don´t get clicked back...). And of course that more than one Label gets clicked in an MouseMoveEvent. I have really no idea how I can program that.

    I know it would be easier if paint the gameboard instead of having ClickableLabels.. but I want to try it like that :). Would be great if someone understand my problem and can manage to show me how to get to it.

    Please help me!
    Sorry for my bad english and my programming skills, I´ll improve both !

    Thank you for your time!

    (This is my second thread, i forgot to select a category don´t know where it´s gone) :)

    Atm I am not at home, i´ll add a part of my Code especially the Clickable Labels when I am at home.

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

      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 1 Reply Last reply
      3
      • 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