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. Programmatically force redraw of QHeaderView

Programmatically force redraw of QHeaderView

Scheduled Pinned Locked Moved Solved General and Desktop
20 Posts 2 Posters 2.5k 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.
  • Christian EhrlicherC Offline
    Christian EhrlicherC Offline
    Christian Ehrlicher
    Lifetime Qt Champion
    wrote on last edited by
    #2

    I'm not sure if I'm on the right track but doesn't QHeaderView::setSectionSize() or QHeaderView::resize() help here?

    Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
    Visit the Qt Academy at https://academy.qt.io/catalog

    M 1 Reply Last reply
    2
    • Christian EhrlicherC Christian Ehrlicher

      I'm not sure if I'm on the right track but doesn't QHeaderView::setSectionSize() or QHeaderView::resize() help here?

      M Offline
      M Offline
      marcbf
      wrote on last edited by
      #3

      @Christian-Ehrlicher Thanks for your input, but I need the orthogonal size. The section size only reflects the size for the orientation of the header view, i.e. the width for horizontal header views and the height for vertical header views. Seems the Qt developers didn't think of a use case for the orthogonal sizes.

      1 Reply Last reply
      0
      • Christian EhrlicherC Offline
        Christian EhrlicherC Offline
        Christian Ehrlicher
        Lifetime Qt Champion
        wrote on last edited by
        #4

        The you should try setMiniumWidth/Height.

        Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
        Visit the Qt Academy at https://academy.qt.io/catalog

        M 1 Reply Last reply
        0
        • Christian EhrlicherC Christian Ehrlicher

          The you should try setMiniumWidth/Height.

          M Offline
          M Offline
          marcbf
          wrote on last edited by
          #5

          @Christian-Ehrlicher Sadly, that won't help me either. I need to react to the changes to the underlying non-frozen header view, so they both stay in sync.

          1 Reply Last reply
          0
          • Christian EhrlicherC Offline
            Christian EhrlicherC Offline
            Christian Ehrlicher
            Lifetime Qt Champion
            wrote on last edited by
            #6

            So why can't you modify the size of the other one with setMin/MaxWidth/Height?

            Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
            Visit the Qt Academy at https://academy.qt.io/catalog

            M 1 Reply Last reply
            0
            • Christian EhrlicherC Christian Ehrlicher

              So why can't you modify the size of the other one with setMin/MaxWidth/Height?

              M Offline
              M Offline
              marcbf
              wrote on last edited by
              #7

              Because it has no effect whatsoever.

              1 Reply Last reply
              0
              • Christian EhrlicherC Offline
                Christian EhrlicherC Offline
                Christian Ehrlicher
                Lifetime Qt Champion
                wrote on last edited by
                #8

                The please provide a minmal example. For me this sounds like https://bugreports.qt.io/browse/QTBUG-34095 which is fixed in 5.12

                Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                Visit the Qt Academy at https://academy.qt.io/catalog

                M 1 Reply Last reply
                2
                • Christian EhrlicherC Christian Ehrlicher

                  The please provide a minmal example. For me this sounds like https://bugreports.qt.io/browse/QTBUG-34095 which is fixed in 5.12

                  M Offline
                  M Offline
                  marcbf
                  wrote on last edited by
                  #9

                  @Christian-Ehrlicher It seems you're right about that bug. It does look very similar to my issue. However, even if it's fixed in 5.12 that would be of no use to me. We're currently on 5.4.1 (commercial) and planning to move to 5.9.7 when it gets available. At the very least this fix should be backported to the 5.9 branch (long term support and all that), preferably 5.9.7. Although I could probably reimplement QHeaderView::resizeEvent() since I'm subclassing anyway, as stated below.

                  I wasn't aware you're working on Qt (by the way, Thorbjørn is a former colleague of mine and (hopefully still :-) a friend).

                  As for the minimal example, sadly I cannot provide one. The code in question is several thousand lines long. What I can do is post my subclassed version of QHeaderView, FrozenHeaderView. It should be possible to plug this in to the Frozen Column example mentioned initially.

                  The FrozenHeaderView class works on two levels. At the base level it's just a wrapper on the normal QHeaderView with added code to try and catch resizing in "the other direction" (i.e. width for vertical headers and height for horizontal headers). That's the one without a "base header". As you can see, I've tried hooking into both sectionSizeFromContents() and paintSection() to get the size change. Both work equally well; that is, the respective signals/slots are emitted/called, but applying the changed width/height in updateSize() to the "frozen" header yields no result, and that seems to be my main issue. I can see that the updatedGeometries() signal is more elegant, but alas, it does not work. And even if, I still can't get the changed size applied.

                  The other level is the "frozen" header. Its sizeHint () method calls the base header's sizeHint() and adjusts the applicable width/height. That bit seems to work OK, but apparently sizeHint() isn't called often. At least not in a way that is helpful to my current problem.

                  Declaration:

                  class FrozenHeaderView : public QHeaderView
                  {
                    Q_OBJECT
                  
                  public:
                    explicit FrozenHeaderView(Qt::Orientation orientation, QWidget *parent = nullptr);
                    explicit FrozenHeaderView(QHeaderView *baseheader, QWidget *parent = nullptr);
                    virtual  ~FrozenHeaderView();
                  
                    void setBaseHeader(QHeaderView *baseheader);
                    QHeaderView* baseHeader() const;
                  
                    virtual QSize sizeHint() const override;
                    virtual QSize minimumSizeHint() const override;
                  
                  Q_SIGNALS:
                    void frozenHeaderResized(int section, int size);
                    void sizeHintChanged(QSize) const;
                    void frozenSizeHintChanged(QSize) const;
                    void sizeChanged(int) const;
                    void sizeUpdated();
                  
                  protected Q_SLOTS:
                    void headerResized(int logicalIndex, int oldSize, int newSize);
                    void updateSize(int);
                  
                  protected:
                    //virtual QSize sectionSizeFromContents(int logicalIndex) const override;
                    virtual void paintSection(QPainter *painter, const QRect &rect, int logicalIndex) const override;
                  
                    FrozenHeaderView *m_baseheader;
                    mutable QSize m_previoussize;
                    mutable QSize m_cachedsizehint;
                    mutable int   m_basecachedsize;
                    bool m_frozen;
                  };
                  
                  

                  Implementation:

                  FrozenHeaderView::FrozenHeaderView(Qt::Orientation orientation, QWidget *parent)
                  : QHeaderView(orientation, parent), m_baseheader(nullptr), m_frozen(false), m_basecachedsize(0)
                  {
                    connect(this, &QHeaderView::sectionResized, this, &FrozenHeaderView::headerResized);
                    m_cachedsizehint = QHeaderView::sizeHint();
                  }
                  
                  FrozenHeaderView::FrozenHeaderView(QHeaderView *baseheader, QWidget *parent)
                  : QHeaderView(baseheader->orientation(), parent), m_baseheader(nullptr), m_frozen(true), m_basecachedsize(0)
                  {
                    setBaseHeader(baseheader);
                    connect(this, &QHeaderView::sectionResized, this, &FrozenHeaderView::headerResized);
                    m_cachedsizehint = QHeaderView::sizeHint();
                  }
                  
                  FrozenHeaderView::~FrozenHeaderView()
                  {
                    disconnect(this, &QHeaderView::sectionResized, this, &FrozenHeaderView::headerResized);
                    if (m_baseheader)
                      disconnect(m_baseheader, &FrozenHeaderView::sizeChanged, this, &FrozenHeaderView::updateSize);
                  }
                  
                  void FrozenHeaderView::setBaseHeader(QHeaderView *baseheader)
                  {
                    if (baseheader == m_baseheader)
                      return;
                  
                    if (m_baseheader)
                      disconnect(m_baseheader, &FrozenHeaderView::sizeChanged, this, &FrozenHeaderView::updateSize);
                  
                    m_baseheader = qobject_cast<FrozenHeaderView*>(baseheader);
                  
                    if (m_baseheader)
                      connect(m_baseheader, &FrozenHeaderView::sizeChanged, this, &FrozenHeaderView::updateSize, Qt::QueuedConnection);
                  }
                  
                  QHeaderView* FrozenHeaderView::baseHeader() const
                  {
                    return m_baseheader;
                  }
                  
                  QSize FrozenHeaderView::sizeHint() const
                  {
                    QSize frozenSize = QHeaderView::sizeHint();
                  
                    if (m_baseheader)
                    {
                      QSize baseSize = m_baseheader->sizeHint();
                  
                      if (orientation() == Qt::Horizontal)
                        frozenSize.setHeight(baseSize.height());
                      else
                        frozenSize.setWidth(baseSize.width());
                  
                      if (frozenSize != m_previoussize)
                      {
                        m_previoussize = frozenSize;
                        emit sizeHintChanged(frozenSize);
                      }
                    }
                  
                    return frozenSize;
                  }
                  
                  QSize FrozenHeaderView::minimumSizeHint() const
                  {
                    return sizeHint();
                  }
                  
                  void FrozenHeaderView::headerResized(int logicalIndex, int oldSize, int newSize)
                  {
                    emit frozenHeaderResized(logicalIndex, newSize);
                  }
                  
                  void FrozenHeaderView::updateSize(int size)
                  {
                    if (m_baseheader)
                    {
                      int w = width();
                      QRect rect = geometry();
                      if (orientation() == Qt::Horizontal)
                        rect.setHeight(size);
                      else
                        rect.setWidth(size);
                      setGeometry(rect);
                      setMinimumSize(rect.size());
                      setMaximumSize(rect.size());
                      setAttribute(Qt::WA_Resized);
                      emit sizeUpdated();
                    }
                  }
                  
                  //QSize FrozenHeaderView::sectionSizeFromContents(int logicalIndex) const
                  //{
                  //  QSize s = QHeaderView::sectionSizeFromContents(logicalIndex);
                  //  if (m_baseheader == nullptr) // this is the base header
                  //  {
                  //    int newsize = orientation() == Qt::Horizontal ? s.height() : s.width();
                  //
                  //    if (newsize != m_basecachedsize)
                  //    {
                  //      m_basecachedsize = newsize;
                  //      emit sizeChanged(newsize);
                  //    }
                  //  }
                  //  
                  //  return s;
                  //}
                  
                  void FrozenHeaderView::paintSection(QPainter *painter, const QRect &rect, int logicalIndex) const
                  {
                    QHeaderView::paintSection(painter, rect, logicalIndex);
                  
                    if (m_baseheader == nullptr) // this is the base header
                    {
                      int newsize = orientation() == Qt::Horizontal ? rect.height() : rect.width();
                  
                      if (newsize != m_basecachedsize)
                      {
                        m_basecachedsize = newsize;
                        emit sizeChanged(newsize);
                      }
                    }
                  }
                  
                  1 Reply Last reply
                  0
                  • M Offline
                    M Offline
                    marcbf
                    wrote on last edited by
                    #10

                    Hmm... Reimplementing resizeEvent() is a much cleaner solution than (ab)using either sectionSizeFromContents() or paintSection(). I'm not sure why I did not go this route earlier. However, I still cannot get the new size applied to the frozen header... :S

                    1 Reply Last reply
                    0
                    • Christian EhrlicherC Offline
                      Christian EhrlicherC Offline
                      Christian Ehrlicher
                      Lifetime Qt Champion
                      wrote on last edited by
                      #11

                      I would try to mimic the behavior of the patch by catching QEvent::Resize and then doing something so d->invalidateCachedSizeHint(); is callled. You could call this directly but then you need to use private headers which should be avoided... maybe by calling dataChanged() with invalid indexes (it calls invalidateCachedSizeHint() without checking the indexes).

                      Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                      Visit the Qt Academy at https://academy.qt.io/catalog

                      1 Reply Last reply
                      0
                      • M Offline
                        M Offline
                        marcbf
                        wrote on last edited by
                        #12

                        Dumb question: Should I call dataChanged() on the frozen header or on the view that contains the frozen header? I'm asking because the former doesn't seem to work (as everything else I've tried so far).

                        1 Reply Last reply
                        0
                        • Christian EhrlicherC Offline
                          Christian EhrlicherC Offline
                          Christian Ehrlicher
                          Lifetime Qt Champion
                          wrote on last edited by
                          #13

                          On the headerView which you wanted to resize. Maybe you should first play around with the testcase in the bugreport to find a solution there - so we have a common base and a minimal testcase.

                          Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                          Visit the Qt Academy at https://academy.qt.io/catalog

                          1 Reply Last reply
                          0
                          • M Offline
                            M Offline
                            marcbf
                            wrote on last edited by
                            #14

                            Sorry for taking so long to update this. I had to do some changes to the code from the bug, so it would work with Qt 5.4.1. Also, I needed to change it so I could add one line at a time to the view. Well, and regular work. ;-)

                            I wanted to upload the code, but apparently I do not have enough privileges.

                            Well, to make it short, everything works in the test case. Now I just need to figure out why that is and why my (substantially larger) version doesn't. I'll keep this thread updated with my findings.

                            1 Reply Last reply
                            0
                            • Christian EhrlicherC Offline
                              Christian EhrlicherC Offline
                              Christian Ehrlicher
                              Lifetime Qt Champion
                              wrote on last edited by
                              #15

                              At least good to hear that the testcase works :)
                              Uploading to the bug is only possible for bug-owners. You have to upload it here in the forum.

                              Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                              Visit the Qt Academy at https://academy.qt.io/catalog

                              M 1 Reply Last reply
                              0
                              • Christian EhrlicherC Christian Ehrlicher

                                At least good to hear that the testcase works :)
                                Uploading to the bug is only possible for bug-owners. You have to upload it here in the forum.

                                M Offline
                                M Offline
                                marcbf
                                wrote on last edited by
                                #16

                                That's what I meant. I'm not allowed to upload the code here.

                                While I'm at it, I've made some progress. Essentially it boils down to me having done too much instead of too little. What I needed to do was simply to emit a signal in the frozen header resize event and then in the main view call updateFrozenTableGeometry() instead of trying to force resizing inside the frozen header itself.

                                I'm not completly there yet. Still have a few issues I need to iron out.

                                1 Reply Last reply
                                0
                                • M Offline
                                  M Offline
                                  marcbf
                                  wrote on last edited by
                                  #17

                                  Well, it all seems to work reasonably well now. Now I only need to figure out how to synchronize two frozen views (one upper and one lower) so that everything stays in sync. It used to work previously when the upper view didn't resize itself. Now it does, but the size change isn't propagated to the lower one.

                                  1 Reply Last reply
                                  0
                                  • M Offline
                                    M Offline
                                    marcbf
                                    wrote on last edited by
                                    #18

                                    Eureka! Seems like I finally cracked the last piece of the puzzle! I need to call updateGeometries() on the linked (lower) table view. That will call sizeHint() on the header views associated with it and thus propagate the size change and sync the upper and lower table views.

                                    @Christian-Ehrlicher thanks for all your input and pointing me in the direction of that bug report. (I still think that should be backported to 5.9.x. :-)

                                    1 Reply Last reply
                                    0
                                    • Christian EhrlicherC Offline
                                      Christian EhrlicherC Offline
                                      Christian Ehrlicher
                                      Lifetime Qt Champion
                                      wrote on last edited by
                                      #19

                                      @marcbf nice to hear that it's working now. But I don't think I can convince them to merge it back to 5.9 since it's really old, not prioritized and not much people complained about it. So you've a good argument updating to 5.12 soon :)

                                      Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                                      Visit the Qt Academy at https://academy.qt.io/catalog

                                      1 Reply Last reply
                                      0
                                      • M Offline
                                        M Offline
                                        marcbf
                                        wrote on last edited by
                                        #20

                                        @Christian-Ehrlicher the reason I'm banging on about 5.9 is that it's the latest long time support branch. Since I'm not doing my own thing with Qt but rather working at a company long term support it quite important to us. We don't have the luxury to upgrade to a newer Qt version every month or so. But maybe I should just get in touch with commercial support about this. :-)

                                        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