Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

[SOLVED] QAbstractItemView, QGraphicsView - Resize Issue



  • Hi there

    I have a chart library with a class inheriting from QAbstractItemView with a QGraphicsView member. The initialisation in the constructor looks like this:

    @
    m_graphicsView = new QGraphicsView(m_graphScene);
    m_graphicsView->setResizeAnchor(QGraphicsView::AnchorViewCenter);
    m_graphicsView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    m_graphicsView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    m_graphicsView->resize(minimumSize());

    setViewport(m_graphicsView);
    

    @

    The setViewort() call is a recent addition. Without this call, all mouse events are intercepted by the QGraphicsView member (as far as I can determine) and never gets to the re-implemented QAbstractItemView functions (e.g. indexAt()).

    Before adding the setViewport() call, my resizeEvent() function looked like this:

    @
    QAbstractItemView::resizeEvent(p_event);
    m_graphicsView->resize(p_event->size());
    drawChart();
    @

    and worked fine. However, now that I set the viewport widget to be the QGraphicsView member, the above implementation for resizeEvent() no longer works as it should (it seems to me as if the QGraphicsView isn't resizing properly, the window resizes, the chart gets redrawn, but the view area remains the same size as that at initialisation, stuck to the top left part of the window...). If I take away the setViewport() call, I lose all the functionality of the re-implemented QAbstractItemView functions.

    The best work-around so far (and, quite honestly, it's still absolute crap) looks like this:

    @
    QAbstractItemView::resizeEvent(p_event);
    m_graphicsView->resize(p_event->size());
    m_graphicsView->fitInView(m_graphScene->sceneRect());
    drawChart();
    m_graphicsView->fitInView(m_graphScene->sceneRect());
    @

    So, I'd like to know how to either:

    • implement resizeEvent() better

    or

    • pass events from QGraphicsView to QAbstractItemView so that the setViewport() call is no longer required.

    My test client and the complete source can be obtained from "here on the project site":http://goblincoding.com/download/

    Thanking you in advance for your help.

    Kind regards,
    goblincoding



  • Turns out the problem is a "Qt 101" mistake. Never assigned a layout. The fix is to change the constructor snippet I included above to:

    @
    m_graphicsView = new QGraphicsView(m_graphScene);
    m_graphicsView->setResizeAnchor(QGraphicsView::AnchorViewCenter);
    m_graphicsView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    m_graphicsView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    m_graphicsView->resize(minimumSize());

    QVBoxLayout *l_layout = new QVBoxLayout;
    l_layout->addWidget(m_graphicsView);
    setLayout(l_layout);
    
    setViewport(m_graphicsView);
    

    @

    and then to have the simplest of resizeEvent() implementations:

    @
    QAbstractItemView::resizeEvent(p_event);
    drawChart();
    @



  • I tried the solution, however it was still buggy with Qt 4.8 since although the graphicsView was resized the scene was not properly rendered: a mixture of QGraphicsScene white background and QFrame gray background was shown when enlarged.

    The ultimate solution to the problem, consists in wrapping the QGraphicsView into a QFrame and setting the latter as the viewPort of the QAbstractItemView. The code will be the following:

    @
    QFrame* l_f = new QFrame;
    m_graphicsView = new QGraphicsView(m_graphScene);
    // optionally resizeAnchor and other bells and whistles
    QVBoxLayout *l_layout = new QVBoxLayout;
    l_layout->addWidget(m_graphicsView);
    l_f->setLayout(l_layout);
    setViewport(l_f);
    @


Log in to reply