Ktokolwiek widział, ktokolwiek wie. Qt framework.
Od dwóch dni męczę się ze ścianą.
Mam Qt Widgets Application, w której moją główną klasą do wyświetlania obiektów, jest moja klasa dziedzicząca po QGraphicsView i zawierająca w sobie QGraphicsScene.
Ostatnio naszła mnie ochota na popróbowanie pisania sobie czegoś w QML ( do czego powinienem użyć Qt Quick Application).
Chciałbym dodać sobie na razie kilka elementów w ramach ćwiczeń do tej aplikacji, i dopiero następną zrobić sobie w Qt Quick Application. Postanowiłem spróbować zagłębić się trochę w temat i dowiedzieć, jak można dodawać elementy z QML do aplikacji z QGraphicsScene. No i tutaj zaczęły się schody.
Aplikacja którą mam, nie używa klasy QMainWindow ani QWindow, tylko QGraphicsView/QGraphicsScene- to jest już podstawowy mankament ( o tym później). W dokumentacji i na stackoverflow znalazłem kilka możliwych sposobów na dodanie obiektów QML do Widget Application, ale niektóre są już nieaktualne z racji nowej wersji Qt ( mowa o użyciu klasy QDeclarativeView).
Znalazłem jeden sposób który "działa", ale tylko połowicznie. Mianowicie, poprzez użycie klasy QQuickWidget...
QQuickWidget *view =new QQuickWidget();
view->resize(300,300);
view->setResizeMode(QQuickWidget::SizeRootObjectToView );
view->setSource(QUrl("qrc:/Button.qml"));//source qml, do sprawdzenia
scene->addWidget(view);
Problem tutaj jest taki, że nie zachodzi automatyczne "update()" obiektu. Jeżeli jest to obiekt zawierający w sobie tylko jakieś statyczne elementy, to wystarczy to, ale do czegoś animowanego w sposób ciągły, musiałbym chyba dodać QTimer i odwołać się do slotu "update()" tego/tych widgetów ( update następuje po np. zminimalizowaniu okna). Nie zadowala mnie to do końca, ponieważ zobaczyłem, że jeżeli QQuickWidget zostanie dodany do okna QMainWindow albo QWindow, to jest animowany w sposób ciągły bez żadnych QTimerów ( i dlatego pytam tutaj, bo może ktoś wie jak wywołać to samo dla QGraphicsScene).
Drugim sposobem którym udało mi się coś osiągnąć, jest użycie klasy QQuickView i użycia createWindowContainer:
QQuickView *view = new QQuickView();
view->setSource(QUrl("qrc:/Button.qml"));
QWidget *widget = QWidget::createWindowContainer(view,this->parentWidget()); // problemem może być ta linijka
widget->setFixedSize(300,300);
scene->addWidget(widget);
Problem tutaj polega, że mimo tego, że wyświetla mi się okienko okno/prostokąt w QGraphicsScene, to jest ono białe ( odnośnik do pliku jest dobry). Moje podejrzenia idą w stronę tej linijki:
QWidget *widget = QWidget::createWindowContainer(view,this->parentWidget());
Moja główna klasa dziedziczy po QGraphicsView i ma opcjonalnego rodzica ustawionego jako 0. Bez użycia "this->parentWidget()" dostaję ostrzeżenie: QGraphicsProxyWidget::setWidget: cannot embed widget 0x6956190 which is not a toplevel widget, and is not a child of an embedded widget... tak więc muszę to dodać.
Trzecią, najnowszą możliwością jaka przyszła mi do głowy, jest dodanie w konstruktorze mojej klasy, klasy QMainWindow i ustawienie jej jako rodzica, oraz użycie show() dla rodzica (żeby wyświetlić inne elementy aplikacji-> bez tego, mam małe, białe okienko).
Później, mógłbym powtórzyć kod ze sposobu drugiego, ale zamiast:
scene->addWidget(...);
dodałbym
widget->show();
Tym sposobem, mam mój widget NA mojej scene ( nie wewnątrz niej). Aktualizuje się w czasie rzeczywistym oraz wyświetla wszystko, ale za to jest nad elementami które są już wewnątrz QGraphicsView ( zasłania je). Nie widziałem w QWidget żadnej metody do ustawiania onTop/Bottom, czy coś takiego, ale przyznam, że nie szukałem za bardzo.
Podsumowując:
1 sposób: wyświetla wewnątrz QGraphicsScene, ale nie odświeża- prawdopodobnie potrzebny QTimer i update().
2 sposób: wyświetla wewnątrz QGraphicsScene białe okienko, bez zawartości;
3 sposób: wyświetla nad QGraphicsScene, odświeża dynamicznie, blokuje możliwość kliknięcia na elementy które są pod nim.
Moje ogólne pytanie jest, po tym całym wywodzie i moim toku myślenia, czy może ktoś ma jeszcze jakiś inny, sprytny sposób, który pozwoli mi na osiągnięcie wyniku ze sposobu 1, + odświeżanie bez QTimera ( chciałbym nie używać QTimera, bo trochę tych elementów będzie).
Pozdro, i sorry za wywód, oraz jeśli pytam o jakąś głupotę, ale nie mam więcej pomysłów.
QDeclarativeView
daje ci dostęp do wcześniejszej wersji QML-a bezpośrednio naQGraphicsView
.QGraphicsView
, jest bliżej sytemu, więc wydajnościowo jest efektywniejszy.