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. sizeHint() of a QWidget doesn't work if the creation of a QMainwindow is triggered by clicking context menu
Forum Updated to NodeBB v4.3 + New Features

sizeHint() of a QWidget doesn't work if the creation of a QMainwindow is triggered by clicking context menu

Scheduled Pinned Locked Moved Unsolved General and Desktop
8 Posts 3 Posters 1.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.
  • F Offline
    F Offline
    fanyha
    wrote on 16 Aug 2021, 10:41 last edited by
    #1

    Hi,
    this issue has confused me for two weeks and I finally decided to ask for a help here.

    My problem:
    I have a MainWindow which has a QTabWidget as its central widget and a bottom dock widget called "test center", like below:
    db57e70f-258a-47b0-ba04-7e574137f810-image.png

    the corresponding source code is as following:

    MainWindow::MainWindow(QWidget *parent)
        : FrameWin(parent)
        , ui(new Ui::MainWindow)
    {
       ui->setupUi(this);
    
       //set a QTabWidget called mainTab as MainWindows's central widget
       setCentralWidget(mainTab);
       //addOneTab("new 1");
    
       //create a control center and attach it as a dock to MainWindow
       QDockWidget *dock = new QDockWidget(this);
       TestControl* control = new TestControl(this);
       dock->setParent(this);
       dock->setWindowTitle("control center");
       dock->setWidget(control);
       addDockWidget(Qt::BottomDockWidgetArea, dock);
    }
    

    now I hope that I can add a tab on the mainTab, this tab has a left dock widget called "Hello" with default width=300 and a QTexEdit as its central widget. note MyWidget is a subclass of QWidget and override the sizeHint() function like this:

    class MyWidget : public QWidget
    {
    public:
        virtual QSize sizeHint() const
        {
           return size; /* Define the initial size of the dock here */
        }
        QSize size;
    };
    
    void MainWindow::addOneTab(QString s)
    {
    
        //create a QMainWindow as a tab page of QTabWidget
        QMainWindow * mWin = new  QMainWindow(this);
        mainTab->addTab(mWin, s);
        mainTab->setCurrentIndex(mainTab->count() -1);
    
        //crete a dock widget and set its default width = 300, attach this dock to QMainWindow
        QDockWidget *dock = new QDockWidget(mWin);
        dock->setParent(mWin);
        dock->setWindowTitle("Hello");
        MyWidget *wi = new MyWidget;
        wi->setParent(dock);
        wi->size=QSize(300,100);
        dock->setWidget(wi);
       // dock->setVisible(true);
        mWin->addDockWidget(Qt::LeftDockWidgetArea, dock);
    
    
        //create a central widget for the QMainWindow
        QTextEdit * wi2 = new QTextEdit;
        mWin->setCentralWidget(wi2);
    
    }
    
    

    it works fine if this tab is added from MainWindow's construction function ( I uncommented "addOneTab("new 1");" in the constructor function), like following:
    de4fc176-2d83-4e48-a2b8-24bb5a4c3a3e-image.png

    However, now I hope the add tab operation is triggered by clicking the contex menu item -"my review" of the QTreeWidget in the test center:
    8a8cc97f-e9c1-4db5-bd82-308093f237c0-image.png

    TestControl::TestControl(QWidget *parent) :
        QWidget(parent),
        ui(new Ui::TestControl)
    {
        ui->setupUi(this);
        m_parent = parent;
    
        ui->m_tree->setContextMenuPolicy(Qt::CustomContextMenu);
        connect(ui->m_tree, SIGNAL(customContextMenuRequested(QPoint)), this,
                SLOT(onJobTreeShowContextMenu(QPoint)));
    
    }
    
    
     void TestControl::onJobTreeShowContextMenu(QPoint pos)
     {
         QMenu menu;
         QIcon icon = QIcon();
         QAction* OpenReview = new QAction(icon, "my review", &menu);
         connect(OpenReview, SIGNAL(triggered(bool)), this, SLOT(onOpenJobReview()));
         menu.addAction(OpenReview);
    
         menu.exec(ui->m_tree->mapToGlobal(pos));
         menu.exec();
     }
    
     void TestControl::onOpenJobReview()
     {
         ((MainWindow*)m_parent)->addOneTab("new x");
     }
    
    

    the tab can be added, however, the "Hello" dockwidget's default width is not correct, it looks like it get expanded.
    d4ec3a74-4faf-472e-8e44-c71cdce01411-image.png

    I really don't know why this happen, is there anyone can help me?

    version: Qt 4.8.7

    1 Reply Last reply
    0
    • S Offline
      S Offline
      SGaist
      Lifetime Qt Champion
      wrote on 16 Aug 2021, 11:28 last edited by
      #2

      Hi and welcome to devnet,

      You current code triggers quite a lot of questions, so just a couple of them to get started:

      1. Why are you creating a full new QMainWindow when calling addOneTab ?
      2. What is FrameWin ?

      For number one you seem to want to have two widgets one beside each other but do you really need a dock widget for that rather than a horizontal layout ?
      If the dock widget is supposed to be tightly associated with the text edit, you are going to lose that information as soon as your users are going to start undocking and re-docking them in different "tabs"

      Since you are mentioning tabs in your code, do you really want dock widgets or are you looking of something like QTabWidget ?

      @fanyha said in sizeHint() of a QWidget doesn't work if the creation of a QMainwindow is triggered by clicking context menu:

      void TestControl::onOpenJobReview()
      {
      ((MainWindow*)m_parent)->addOneTab("new x");
      }

      This is several levels wrong, if you want your MainWindow to get triggered, use proper signals and slots. Here you make the assumption that you have a parent and that the parent is MainWindow based class. You are also storing that parent as a member variable while Qt already provides a getter for that if really required.

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      F 1 Reply Last reply 20 Aug 2021, 09:23
      2
      • S SGaist
        16 Aug 2021, 11:28

        Hi and welcome to devnet,

        You current code triggers quite a lot of questions, so just a couple of them to get started:

        1. Why are you creating a full new QMainWindow when calling addOneTab ?
        2. What is FrameWin ?

        For number one you seem to want to have two widgets one beside each other but do you really need a dock widget for that rather than a horizontal layout ?
        If the dock widget is supposed to be tightly associated with the text edit, you are going to lose that information as soon as your users are going to start undocking and re-docking them in different "tabs"

        Since you are mentioning tabs in your code, do you really want dock widgets or are you looking of something like QTabWidget ?

        @fanyha said in sizeHint() of a QWidget doesn't work if the creation of a QMainwindow is triggered by clicking context menu:

        void TestControl::onOpenJobReview()
        {
        ((MainWindow*)m_parent)->addOneTab("new x");
        }

        This is several levels wrong, if you want your MainWindow to get triggered, use proper signals and slots. Here you make the assumption that you have a parent and that the parent is MainWindow based class. You are also storing that parent as a member variable while Qt already provides a getter for that if really required.

        F Offline
        F Offline
        fanyha
        wrote on 20 Aug 2021, 09:23 last edited by
        #3

        @SGaist
        really appreciate for your reply.

        to answer your first 2 questions:

        1. Why are you creating a full new QMainWindow when calling addOneTab ?
          My answer: sorry, I am a little confused, what do you mean by "a full new QMainWindow"? here I just need to create a QMainWindow to put my dock widgets on, is there any other way to implement this?

        2. What is FrameWin ?
          sorry, I made code looks complex. FrameWin is just a subclass of QMainwindow, mainTab is created in its constructor. now I have removed FrameWin and make mainTab created in MainWindow.

        answers to some other questions:
        yes, I need dockwidget, in our real project, we use it like this. note what I have shown is just a simple demo to reproduce this issue. it's not our real project source code.
        by the way, tab1 's dock widget seems not be able to put on tab2.

        about the code issue:

        void TestControl::onOpenJobReview()
        {
        ((MainWindow*)m_parent)->addOneTab("new x");
        }
        

        yes, I admit there's an issue here, thanks for point it out. but in my sample source code, m_parent is MainWindow type, so in my simple demo, it won't be an issue to cause the layout issue. and I have changed it to signals/slots.

        note I just write this demo to reproduce the layout issue, I am not sure if it's QT's bug, but now it looks like it is.

        JonBJ 1 Reply Last reply 20 Aug 2021, 10:25
        0
        • F fanyha
          20 Aug 2021, 09:23

          @SGaist
          really appreciate for your reply.

          to answer your first 2 questions:

          1. Why are you creating a full new QMainWindow when calling addOneTab ?
            My answer: sorry, I am a little confused, what do you mean by "a full new QMainWindow"? here I just need to create a QMainWindow to put my dock widgets on, is there any other way to implement this?

          2. What is FrameWin ?
            sorry, I made code looks complex. FrameWin is just a subclass of QMainwindow, mainTab is created in its constructor. now I have removed FrameWin and make mainTab created in MainWindow.

          answers to some other questions:
          yes, I need dockwidget, in our real project, we use it like this. note what I have shown is just a simple demo to reproduce this issue. it's not our real project source code.
          by the way, tab1 's dock widget seems not be able to put on tab2.

          about the code issue:

          void TestControl::onOpenJobReview()
          {
          ((MainWindow*)m_parent)->addOneTab("new x");
          }
          

          yes, I admit there's an issue here, thanks for point it out. but in my sample source code, m_parent is MainWindow type, so in my simple demo, it won't be an issue to cause the layout issue. and I have changed it to signals/slots.

          note I just write this demo to reproduce the layout issue, I am not sure if it's QT's bug, but now it looks like it is.

          JonBJ Offline
          JonBJ Offline
          JonB
          wrote on 20 Aug 2021, 10:25 last edited by JonB
          #4

          @fanyha said in sizeHint() of a QWidget doesn't work if the creation of a QMainwindow is triggered by clicking context menu:

          ((MainWindow*)m_parent)->addOneTab("new x");
          

          Just a very quick note. Don't use C-style casts like this any longer, they are needlessly dangerous. Use C++ either

          static_cast<MainWindow*>(m_parent)->addOneTab("new x");
          

          which asserts if m_parent is not MainWindow*. In your case where you know it is it effectively behaves like your C-cast, but is safer; or

          MainWindow* mainWin = dynamic_cast<MainWindow*>(m_parent);
          // or use `qobject_cast` in place of `dynamic_cast`
          if (mainWin)
              mainWin->addOneTab("new x");
          else
              .... // whatever
          
          1 Reply Last reply
          0
          • S Offline
            S Offline
            SGaist
            Lifetime Qt Champion
            wrote on 20 Aug 2021, 18:02 last edited by
            #5

            Please provide a complete compilable minimal and clean example that shows your issue.

            Can you please explain the purpose of your design ?

            There's no problem having several QMainWindow in an application however using them like you do currently is a bit strange. Therefore, knowing why you need that many "subwidgets" that are in fact QMainWindows will help us understand what you are trying to achieve.

            Interested in AI ? www.idiap.ch
            Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

            F 1 Reply Last reply 23 Aug 2021, 09:51
            0
            • S SGaist
              20 Aug 2021, 18:02

              Please provide a complete compilable minimal and clean example that shows your issue.

              Can you please explain the purpose of your design ?

              There's no problem having several QMainWindow in an application however using them like you do currently is a bit strange. Therefore, knowing why you need that many "subwidgets" that are in fact QMainWindows will help us understand what you are trying to achieve.

              F Offline
              F Offline
              fanyha
              wrote on 23 Aug 2021, 09:51 last edited by
              #6

              hi @SGaist , to simply describe my issue:
              if I click on the menu item of a contex menu, the slot addOneTab() is triggered, and a new tab is shown, but MyWidget in this tab is not shown with width = 300 (the actual result is MyWidget always get expanded ).
              If I call addOneTab() in MainWindow constructor function directly, MyWidget in this tab is shown with width = 300, which is as expected.
              both operation call addOneTab(), Why this difference happen?

              below is my source code:

              //mainwindow.cpp
              void MainWindow::addOneTab(const QString& s)
              {
              
                  //create a QMainWindow as a tab page of QTabWidget
                  QMainWindow * mWin = new  QMainWindow(this);
                  mainTab->addTab(mWin, s);
                  mainTab->setCurrentIndex(mainTab->count() -1);
              
                  //crete a dock widget and set its default width = 300, attach this dock to QMainWindow
                  QDockWidget *dock = new QDockWidget(mWin);
                  dock->setParent(mWin);
                  dock->setWindowTitle("Hello");
                  MyWidget *wi = new MyWidget;
                  wi->setParent(dock);
                  wi->size=QSize(300,100);
                  dock->setWidget(wi);
                 // dock->setVisible(true);
                  mWin->addDockWidget(Qt::LeftDockWidgetArea, dock);
              
              
                  //create a central widget for the QMainWindow
                  QTextEdit * wi2 = new QTextEdit;
                  mWin->setCentralWidget(wi2);
              
              }
              
              
              MainWindow::MainWindow(QWidget *parent)
                  : QMainWindow(parent)
                  , ui(new Ui::MainWindow)
              {
                  ui->setupUi(this);
                  mainTab = new QTabWidget(this);
              
                 //set a QTabWidget called mainTab as MainWindows's central widget
                 setCentralWidget(mainTab);
                 //addOneTab("new 1");
              
                 //create a control center and attach it as a dock to MainWindow
                 QDockWidget *dock = new QDockWidget(this);
                 TestControl* control = new TestControl(this);
                 dock->setParent(this);
                 dock->setWindowTitle("test center");
                 dock->setWidget(control);
                 addDockWidget(Qt::BottomDockWidgetArea, dock);
              }
              
              
              //testcontrol.cpp
              TestControl::TestControl(QWidget *parent) :
                  QWidget(parent),
                  ui(new Ui::TestControl)
              {
                  ui->setupUi(this);
                  m_parent = parent;
              
                  ui->m_tree->setContextMenuPolicy(Qt::CustomContextMenu);
                  connect(ui->m_tree, SIGNAL(customContextMenuRequested(QPoint)), this,
                          SLOT(onJobTreeShowContextMenu(QPoint)));
              
                  connect(this, SIGNAL(showTab(const QString&)), parent, SLOT(addOneTab(const QString&)));
              
              }
              
              
               void TestControl::onJobTreeShowContextMenu(QPoint pos)
               {
                   QMenu menu;
                   QIcon icon = QIcon();
                   QAction* OpenReview = new QAction(icon, "my review", &menu);
                   connect(OpenReview, SIGNAL(triggered(bool)), this, SLOT(onOpenJobReview()));
                   menu.addAction(OpenReview);
              
                   menu.exec(ui->m_tree->mapToGlobal(pos));
                   menu.exec();
               }
              
               void TestControl::onOpenJobReview()
               {
                   //((MainWindow*)m_parent)->addOneTab("new x");
                   emit showTab("new  2");
               }
              
              
              1 Reply Last reply
              0
              • S Offline
                S Offline
                SGaist
                Lifetime Qt Champion
                wrote on 23 Aug 2021, 19:58 last edited by
                #7

                sizeHint, as the name suggests, is a hint. It does not guarantee that your widget will be shown to exactly that size.

                Interested in AI ? www.idiap.ch
                Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                F 1 Reply Last reply 24 Aug 2021, 13:48
                0
                • S SGaist
                  23 Aug 2021, 19:58

                  sizeHint, as the name suggests, is a hint. It does not guarantee that your widget will be shown to exactly that size.

                  F Offline
                  F Offline
                  fanyha
                  wrote on 24 Aug 2021, 13:48 last edited by
                  #8

                  @SGaist
                  thanks, so what is a normal way to set a dock widget's default width?
                  As I know, there's a method that we can install a event filter on the dockwidget's client widget, and set the widget max and min width in its show event. this method works fine.
                  However, it seems almost every post recommend that we use sizehint() on the dockwidget's client widget. my test result is: it doesn't works fine in my special case.
                  may I know what is your suggestion to implement that?

                  1 Reply Last reply
                  0

                  1/8

                  16 Aug 2021, 10:41

                  • Login

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