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. Decorator pattern and other common code for my windows
QtWS25 Last Chance

Decorator pattern and other common code for my windows

Scheduled Pinned Locked Moved General and Desktop
20 Posts 2 Posters 5.9k Views
  • 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.
  • raven-worxR Offline
    raven-worxR Offline
    raven-worx
    Moderators
    wrote on last edited by
    #6

    you should only wrap the most top-level widget with the "decorator-widget". You then can move the window, when you install the decorator-widget as an event-filter on the QMenuBar. Check if the mouse press event is in the empty zone by checking QMenuBar::actionAt(pos) == NULL

    --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
    If you have a question please use the forum so others can benefit from the solution in the future

    1 Reply Last reply
    0
    • A Offline
      A Offline
      aidaqt
      wrote on last edited by
      #7

      This works fine. So now I have a wrapper for my QMainWindow and this QMainWindow has installed a eventFilter that is the wrapper class. What could I do if in the future I need to reimplement QMainWindows eventFilter?

      Thanks

      1 Reply Last reply
      0
      • raven-worxR Offline
        raven-worxR Offline
        raven-worx
        Moderators
        wrote on last edited by
        #8

        what do you mean? Change it :)

        Also i meant that you implement the event filter in the decoration widget. And install this decoration widget as the event filter on your QMenuBar.

        You can keep the code very general to make it work in many cases. Show the code of your eventFilter() please.

        --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
        If you have a question please use the forum so others can benefit from the solution in the future

        1 Reply Last reply
        0
        • A Offline
          A Offline
          aidaqt
          wrote on last edited by
          #9

          @
          TitlelessWindow::TitlelessWindow(QWidget* widget){

          //...Removing title code and some decorating stuff... also:
          widget->setParent(this);
          this->layout()->addWidget(widget);

          }

          void TitlelessWindow::mouseMoveEvent(QMouseEvent *event){

          QPoint newPos=event->globalPos();
          move(newPos - clickPos);
          }

          void TitlelessWindow::mousePressEvent( QMouseEvent * e){

          clickPos=e->pos();
          QWidget::mousePressEvent(e);
          }

          bool TitlelessWindow::eventFilter(QObject *obj, QEvent *event)
          {
          if (event->type() == QEvent::MouseMove) {

          QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
          mouseMoveEvent(mouseEvent);
          return true;

           }if (event->type() == QEvent::MouseButtonPress) {
          

          QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
          mousePressEvent(mouseEvent);
          return true;

           } else {
               // standard event processing
               return QObject::eventFilter(obj, event);
           }
          

          }@

          This is the code of my wrapper class you told me. Then, I decorate QMainWindow with it, and I install its eventFilter for my QMenuBar. This is currently working, but I dont know if its what you meant.

          1 Reply Last reply
          0
          • raven-worxR Offline
            raven-worxR Offline
            raven-worx
            Moderators
            wrote on last edited by
            #10

            ok looks good.
            Some tips:

            • In TitlelessWindow::eventFilter() you can check if "obj" is of type QMenuBar and if it is cast it. Then you need to use actionAt() otherwise your menu items won't be clickable.

            • Don't route the events from the event filter through your class' event handler. This works in your case, but since they are propagated they may have side effects if you use top-level windows with a parent widget.
              @
              bool TitlelessWindow::eventFilter(QObject *obj, QEvent *event)
              {
              ...
              switch( event->type() )
              {
              case QEvent::MouseButtonPress:
              {
              QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);

                   QMenuBar* menuBar = qobject_cast<QMenuBar*>(obj);
                   if( menuBar )
                   {
                           if( menuBar->actionAt(mouseEvent->pos()) == 0 )
                                 //accept movement of window
                   }
              

              }
              break;
              case QEvent::MouseMove:
              ...
              break;
              }

            return QWidget::eventFilter(obj,event);
            };
            @

            Or you could also check in the constrcutor if the widget is a QMainWindow type and install the eventFilter on the menuBar() there.
            Then the whole implementation is in 1 class and all you have to do is wrap your widget with this decoration widget.

            --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
            If you have a question please use the forum so others can benefit from the solution in the future

            1 Reply Last reply
            0
            • A Offline
              A Offline
              aidaqt
              wrote on last edited by
              #11

              Thanks for your help,

              Regarding in your second tip, I originally put this code inside the eventFilter instead calling the mouseMoveEvent and mousePressEvent, but then, when I clicked, holded and moved the mouse 1px, it was jumping up like 10px for some reason at the start of the movement. Any idea why this behaviour?

              1 Reply Last reply
              0
              • raven-worxR Offline
                raven-worxR Offline
                raven-worx
                Moderators
                wrote on last edited by
                #12

                most probably a mapping issue.
                Easiest would be to always use the event's globalPos() and map it to your decoration widget. Then you should be safe.

                --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
                If you have a question please use the forum so others can benefit from the solution in the future

                1 Reply Last reply
                0
                • A Offline
                  A Offline
                  aidaqt
                  wrote on last edited by
                  #13

                  Hi,

                  I had to consider the geometry differences bewteen contained and container to call the QWidget::move function.

                  Only one question more: How would you add more event hadling for the QMenuBar? I have a wrapper class for the QMenuBar (MyQMenuBar), but I've just made a installEventFilter pointing to the TitlelessWindow class.

                  1 Reply Last reply
                  0
                  • raven-worxR Offline
                    raven-worxR Offline
                    raven-worx
                    Moderators
                    wrote on last edited by
                    #14

                    [quote author="aidaqt" date="1383750043"]
                    I had to consider the geometry differences bewteen contained and container to call the QWidget::move function.
                    [/quote]
                    Thats why i said it's easier to use the event's QMouseEvent::globalPos() and map it to your top-level widget using QWidget::mapFromGlobal(). ;)

                    [quote author="aidaqt" date="1383750043"]
                    Only one question more: How would you add more event hadling for the QMenuBar? I have a wrapper class for the QMenuBar (MyQMenuBar), but I've just made a installEventFilter pointing to the TitlelessWindow class.[/quote]
                    sorry but i don't understand the question.

                    --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
                    If you have a question please use the forum so others can benefit from the solution in the future

                    1 Reply Last reply
                    0
                    • A Offline
                      A Offline
                      aidaqt
                      wrote on last edited by
                      #15

                      If I would need to implement an eventFilter in my QMainWindow or MyQMenuBar, how could I achieve it?
                      Think for example if I wanted to implement more logic in MouseMoveEvent but only for my QMainWindow.

                      And how could I combine my TitlelessWindow with another similar one "DecoratedWindow"?

                      1 Reply Last reply
                      0
                      • raven-worxR Offline
                        raven-worxR Offline
                        raven-worx
                        Moderators
                        wrote on last edited by
                        #16

                        [quote author="aidaqt" date="1383751265"]If I would need to implement an eventFilter in my QMainWindow or MyQMenuBar, how could I achieve it?
                        Think for example if I wanted to implement more logic in MouseMoveEvent but only for my QMainWindow.
                        [/quote]

                        If it's for all QMainWindow's then do it like i did in my code for the QMenuBar (using qobject_cast).
                        If it's jsut for a special window you could subclass from this class and also reimplement eventFilter() and implement the special case and for the rect call the base class implementation...

                        [quote author="aidaqt" date="1383751265"]
                        And how could I combine my TitlelessWindow with another similar one "DecoratedWindow"?[/quote]
                        This is just a matter of Object-orientation. Meaning you could subclass TitlelessWindow... or generate a base-class which only implements the parts which are common for both, etc.

                        --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
                        If you have a question please use the forum so others can benefit from the solution in the future

                        1 Reply Last reply
                        0
                        • A Offline
                          A Offline
                          aidaqt
                          wrote on last edited by
                          #17

                          Hi,

                          More problems, I hope your patience hasnt ran out yet.. :)

                          -If I apply this TitlelessWindow to a QMainWindow everything is OK, widgets inside are in a centralWidget containing them.

                          -If a window has not centralWidget, decoration is applied to the concrete widgets inside ( QGroupBox for example) but the other parts of the window are transparent. Why do I need a centralWidget (or one containing the QGroupBoxes)?

                          -For a reason, QGroupBoxes doesnt inherits the eventFilter, but QTabWidgets does, so I needed to made MyQGroupBox class...

                          Thanks again

                          1 Reply Last reply
                          0
                          • raven-worxR Offline
                            raven-worxR Offline
                            raven-worx
                            Moderators
                            wrote on last edited by
                            #18

                            you only need to add the decoration-widget to widgets you know they are top-level widgets if i understood you correct what you want to achieve.
                            And also your decoration window doesn't necessarily need to inherit QMainWindow. It's enough if it looks like this:
                            @
                            TitlelessWindow::TitlelessWindow(QWidget* content, QWidget* parent)
                            : QFrame(parent)
                            {
                            //...Removing title code and some decorating stuff... also:

                             QVBoxLayout* layout = new QVBoxLayout;
                                 layout->addWidget(content);
                             this->setLayout(layout);
                            

                            }
                            @

                            --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
                            If you have a question please use the forum so others can benefit from the solution in the future

                            1 Reply Last reply
                            0
                            • A Offline
                              A Offline
                              aidaqt
                              wrote on last edited by
                              #19

                              Hi,

                              My TitlelessWindow inherits from QWidget. This is my Titleless constructor code:

                              @TitlelessWindow::TitlelessWindow(QWidget* widget) {

                                           //...Decorating stuff...
                              

                              widget->setParent(this); //Do I really need this?

                              this->setGeometry(widget->geometry()); //Pick the size. Not working also

                                          this->setLayout(new QGridLayout ()); 
                              

                              this->layout()->addWidget(widget); //Add the QMainWindow or other window to the layout of TitlelessWindow. //Do I really need this?

                              //Decorate the wrapper class
                              this->setWindowFlags(Qt::FramelessWindowHint);
                              this->setAttribute(Qt::WA_TranslucentBackground); //This is being propagated to the child widgets if not centralWidget is present

                              @

                              1 Reply Last reply
                              0
                              • raven-worxR Offline
                                raven-worxR Offline
                                raven-worx
                                Moderators
                                wrote on last edited by
                                #20

                                you can leave out the setParent since this is done when you add the widget to the layout anyway.

                                I would recommend to do the layout like i did, as long as you do not need the QGridLayout. Beside QGridLayout::addWidget(QWidget*) is not like it is intended to be used (QGridLayout expects row and col parameters).

                                Do you really need the widget attribute "TranslucentBackground"? You could also use QWidget::setMask() for instance.
                                If you need it, you can try to unset it on the child widget right after you have set it on the frame widget. Or set the attributes at the very first in the constructor.
                                Or also try QWidget::setAutoFillbackground(true) on the child widget.

                                --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
                                If you have a question please use the forum so others can benefit from the solution in the future

                                1 Reply Last reply
                                0

                                • Login

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