Tabview issue



  • Hi,

    In my application i have a main.qml file which has a loader which loads the content on the screen dependent on which state the application is in.
    One of the states is a TabView with 3 tabs. From the 3rd tab I can switch to a new state and from this state I can switch back to the 'tabview' state.
    When I switch back from this new state to the tabview state, I want my tabview to have the third tab active. I did this by binding the currentIndex of the TabView component to a variable in my state object (which is a QObject). This seems to work, except that the rendering of the tabview is kinda messed up after I switch back: the third tab is shown as the active tab, but it seems like the content of this tab is moved up until the top anchor point of the tab(instead of the bottom anchor point). Also the border is drawn to high.
    Good:
    http://www.foto-jw.com/NormalTab.png

    Bad:
    http://www.foto-jw.com/WrongTab.png

    Anyone has an idea what is wrong? (If i don't bind the currentIndex property, the first tab is active and it's content is shown correct (anchored to the bottom of the tab))
    Regards,

    Matt



  • Could you provide a simplified example demonstrating this behavior? It would make it a lot easier to see what's going wrong.



  • I'll try:

    main.qml
    @
    Rectangle
    {
    width: 1366
    height: 768
    Loader
    {

    id:loader
    source: stateMachineQMLInterface.activeStateQmlLocation;
    anchors.fill: parent
    }
    }
    @

    OperatorMain.qml (source file for the 'tabview' state)
    @
    Item
    {
    anchors.fill: parent;

    TabView
    {
    id: operatorTabs

    anchors.left: parent.left;
    anchors.leftMargin: 5;
    anchors.top: parent.top;
    anchors.topMargin: 5;

    width: parent.width - 10;
    height: parent.height - 10;

    currentIndex: operatorMainStateQMLInterface.currentTabIndex;
    Binding
    {
    target: operatorMainStateQMLInterface;
    property: "currentTabIndex";
    value: operatorTabs.currentIndex;
    }
    Tab
    {
    title: "Jobs";
    source: operatorJobManagementStateQMLInterface.getLocationOfQmlFile();
    }
    Tab
    {
    title: "System Monitor";
    source: operatorSystemMonitoringStateQMLInterface.getLocationOfQmlFile();
    }
    Tab
    {
    title: "History";
    source: operatorHistoryStateQMLInterface.getLocationOfQmlFile();
    }
    }
    }
    @

    OperatorMainStateQMLInterface.cpp:
    @
    class AMSOperatorMainStateQMLInterface : public AMSIStateQMLInterface
    {
    Q_OBJECT
    Q_PROPERTY(int currentTabIndex READ getCurrentTabIndex WRITE setCurrentTabIndex NOTIFY currentTabIndexChanged);
    }
    @

    (AMSIStateQMLInterface implements the methods for getLocationOfQmlFile and registers it's contextProperty to the viewers rootContext)

    When the state changes, the stateMachineQMLInterface.activeStateQmlLocationChanged signal is emitted, so the loader loads
    the new qml file (belonging to the new state). When I pop this state (the 'tabview' state is stored in the statemachine), again the
    activeStateQmlLocationChanged signal is emitted, so the qml file OperatorMain.qml is loaded (with the currentIndex bound to the
    qproperty in the stored state in the statemachine). When this is shown on screen, i get the wrong behaviour of the tabs.
    Hope this makes it more clear.
    Regards,

    Matt



  • I've got a more simple case which shows the error:

    Main.qml
    @
    import QtQuick 2.0
    import QtQuick.Layouts 1.0
    import QtQuick.Controls 1.0

    Rectangle {
    width: 800
    height: 600
    color: "red"
     
    TabView
    {
    id: operatorTabs
     
    anchors.left: parent.left;
    anchors.leftMargin: 5;
    anchors.top: parent.top;
    anchors.topMargin: 5;
     
    width: parent.width - 10;
    height: parent.height - 10;
     
    currentIndex: tabContext.tabIndex;
    Binding
    {
    target: tabContext;
    property: "tabIndex";
    value: operatorTabs.currentIndex;
    } 
    Tab
    {
    title: "Jobs";
    Rectangle
    {
    anchors.fill: parent
    color: "green"
    }
    }
    Tab
    {
    title: "System Monitor";
    Rectangle
    {
    anchors.fill: parent
    color: "yellow"
    }
    } 
    Tab
    {
    title: "History";
    Rectangle
    {
    anchors.fill: parent
    color: "blue"
    }
    }
    }
    }
    

    @
    TabContext.h
    @
    #ifndef TABCONTEXT_H
    #define TABCONTEXT_H

    #pragma warning(push, 0)
    #include <qobject.h>
    #pragma warning(pop)
     
     
    class TabContext : public QObject
    {
    Q_OBJECT
    Q_PROPERTY(int tabIndex READ getTabIndex WRITE setTabIndex NOTIFY tabIndexChanged);
     
    public:
    TabContext ();
    virtual ~TabContext (void);
     
    public: 
    int getTabIndex () const;
    void setTabIndex (int index);
     
     
    signals:
    void tabIndexChanged ();
     
    private:
    int _tabIndex;
    };
     
    #endif
    

    @

    TabContext.cpp
    @
    #include "TabContext.h"

    TabContext::TabContext(void)
    : _tabIndex(0)
    {
    }
     
     
    TabContext::~TabContext(void)
    {
    }
     
     
    int TabContext::getTabIndex() const
    {
    return _tabIndex;
    }
     
    void TabContext::setTabIndex(int index)
    {
    if(index != _tabIndex)
    {
    _tabIndex = index;
    emit tabIndexChanged();
    }
    }
    

    @

    Main.cpp
    @
    #pragma warning(push, 0)
    #include "qtquick2applicationviewer.h"
    #pragma warning(pop)

    #include "TabContext.h"
     
    #pragma warning(push, 0)
    #include <QtGui/QGuiApplication>
    #include <QtQml/qqmlcontext.h>
    #pragma warning(pop)
    #pragma warning(push, 0)
    #include <qobject.h>
    #include <qstringlist.h>
    #pragma warning(pop)
     
     
    #include "qtquick2applicationviewer.h"
     
    int main(int argc, char *argv[])
    {
    QGuiApplication app(argc, argv);
     
    QtQuick2ApplicationViewer viewer;
    TabContext context;
     
    viewer.rootContext()->setContextProperty(QString("tabContext"), &context);
     
    viewer.setMainQmlFile&#40;QStringLiteral("qml/test/main.qml"&#41;);
    viewer.showExpanded();
     
    return app.exec();
    }
    

    @

    If in TabContext, _tabIndex is initiallised as 0, everything is ok, if it is 1 or 2, the content from the tabs is drawn too high (the yellow and the blue square starts at the same level as the top of the tab-label, while it should start at the bottom of it).
    Anybody an idea, or is it just a bug in Qt?
    Regards,

    Matt



  • Just an update. I have now fixed this issue for 5.3.

    https://codereview.qt-project.org/#change,82917

    Unfortunately I don't have a practical workaround for older versions apart from modifying the deployed QML sources with the above mentioned fix. Though you could set the index in "onCompleted" but that would result in pretty ugly flickering.



  • Great, I'll just wait for 5.3 then.
    Thanks!


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.