QGraphicView not maximized in complete layout

后端 未结 1 2060
刺人心
刺人心 2021-01-24 05:21

I have following GUI having four QGraphicView objects \"enter

It have four t

1条回答
  •  小蘑菇
    小蘑菇 (楼主)
    2021-01-24 05:24

    The code below works for me under both Qt 4 and Qt 5. It leverages the State Machine Framework to simplify the management of state transitions. The states with one view visible are a substate of the state with no views shown. This gets rid of the need for explicit signal-slot connections and for having to keep lists of views and buttons.

    The State class is there for debugging purposes only, to visualize state transitions.

    Alas, there's a bug (race?) at least in Qt 4.8.5 that makes property assignments not always work properly with nested states. When nested states with overlapping properties are used, sometimes all views and buttons will be hidden in spite of the machine having entered the correct state. There's a workaround for this in the code below.

    Note that the grid widget must not have any other widgets with row/column span != 1. If it did, the spacing around hidden widgets would still be visible. This is why I've used two nested layouts.

    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    static const int N = 4;
    static QPointer logView;
    
    class State : public QState
    {
    public:
        explicit State(const QString& name, QState* parent = 0) : QState(parent) {
            setObjectName(name);
        }
    protected:
        virtual void onEntry(QEvent*) {
            QString state = objectName();
            QState* parent = this;
            while ((parent = parent->parentState()) && !parent->objectName().isEmpty() )
            {
                state = parent->objectName() + "->" + state;
            }
            logView->appendHtml(QString("Entering state: %1").arg(state));
        }
        virtual void onExit(QEvent*) {
            QString state = objectName();
            QState* parent = this;
            while ((parent = parent->parentState()) && !parent->objectName().isEmpty() )
            {
                state = parent->objectName() + "->" + state;
            }
            logView->appendHtml(QString("Exiting state: %1").arg(state));
        }
    };
    
    class Widget : public QWidget {
    public:
        explicit Widget(bool qt4) {
            QGridLayout *vert = new QGridLayout(this);
            QGridLayout *layout = new QGridLayout;
            layout->setContentsMargins(0, 0, 0, 0);
            logView = new QPlainTextEdit;
            logView->appendPlainText(QString("Qt %1").arg(QT_VERSION_STR));
            vert->addLayout(layout, 0, 0, 1, 1);
            vert->addWidget(logView, 1, 0, 1, 1);
            QStateMachine * const machine = new QStateMachine(this);
            machine->setObjectName("machine");
            State * const all = new State("all", machine);
            State * const none = new State("none", machine);
            QList ones;
            for (int i = 0; i < N; ++ i) {
                const QString label = QString("View %1").arg(i+1);
                ones << new State(label, none);
            }
            for (int i = 0; i < N; ++ i) {
                QState *one = ones[i];
                QGraphicsView *view = new QGraphicsView;
                QGraphicsScene *scene = new QGraphicsScene(view);
                scene->addText(one->objectName());
                view->setScene(scene);
                layout->addWidget(view, 2*(i/2), i%2, 1, 1);
                QPushButton *button = new QPushButton(one->objectName());
                layout->addWidget(button, 2*(i/2)+1, i%2, 1, 1);
                button->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Fixed);
                all->assignProperty(view, "visible", true);
                all->assignProperty(button, "visible", true);
                if (qt4) {
                    // Workaround for a bug: properties in nested states are
                    // sometimes not set correctly, so we explicitly set all properties
                    // in one state.
                    foreach (QState* s, ones) {
                        s->assignProperty(view, "visible", s == one);
                        s->assignProperty(button, "visible", s == one);
                    }
                } else {
                    none->assignProperty(view, "visible", false);
                    none->assignProperty(button, "visible", false);
                    one->assignProperty(view, "visible", true);
                    one->assignProperty(button, "visible", true);
                }
                all->addTransition(button, SIGNAL(clicked()), one);
                one->addTransition(button, SIGNAL(clicked()), all);
                if (!none->initialState()) none->setInitialState(one);
            }
            machine->setInitialState(all);
            machine->start();
        }
    };
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        Widget w(QT_VERSION < QT_VERSION_CHECK(5,0,0));
        w.show();
        return a.exec();
    }
    

    0 讨论(0)
提交回复
热议问题