Adding QQuickWidget in QStackedWidget - qt

I am trying to add a qquickwidget along with some other qwidgets in qstackedwidget. But when I am trying to set the current widget to the qquickwidget nothing appears on the window. Is there something else that need to be done? I am also setting the view property of the qquickwidget to true
QQuickWidget* mRoom = new QQuickWidget;
connect(mRoom, SIGNAL(statusChanged(QQuickWidget::Status)), this, SLOT(StatusChanged(QQuickWidget::Status)));
mRoom->setSource(QUrl::fromLocalFile("C:/Users/visjain/Desktop/main_vishwas.qml"));
mRoom->setResizeMode(QQuickWidget::SizeRootObjectToView);
QStackedWidget* mStack = new QStackedWidget(mparent);
mStack->addWidget(mRoom);
mStack->setCurrentWidget(mRoom);
mRoom->show();
qml code -
import QtQuick 2.5
import QtQuick.Window 2.2
Window {
visible: true
height: 1000
width: 1800
Rectangle{
height: parent.height
width: parent.width
color: "red"
}
}

Did you assign some QML file to the widget?
QQuickWidget *view = new QQuickWidget;
view->setSource(QUrl::fromLocalFile("myqmlfile.qml"));
view->show();
Some more source code might be helpful.
For some more detailed reference you might see this.
For putting a QWidget inside a QStackedWidget to the front you should use setCurrentIndex or setCurrentWidget. See this.

Related

Difference between Window and ApplicationWindow in QML?

https://doc.qt.io/qt-5/qml-qtquick-controls2-menubar.html
MenuBar is supported in ApplicationWindow and not in Window.
Following throws an error "Invalid property name: MenuBar"
Window
{
visible: true
width: 280; height: 280
menuBar: MenuBar {
Menu {}
}
}
whereas following works:
ApplicationWindow
{
visible: true
width: 280; height: 280
menuBar: MenuBar {
Menu {}
}
}
In the new Qt version 5.12, the default code uses Window and not ApplicationWindow.
What is the difference between Window and ApplicationWindow? Which one should be used in which case?
The docs is very clear:
ApplicationWindow is a Window that adds convenience for positioning items, such as MenuBar, ToolBar, and StatusBar in a platform independent manner.
That is, it is an item that inherits from Window but has certain default attributes, it is similar to QMainWindow with respect to QWidget.
When you say: In the new Qt version 5.12, the default code uses Window and not ApplicationWindow I suppose you mean that QtCreator uses Window by default in creating projects, that's just because the developers wanted to and there is no science in it, just a choice.
When you should use one or the other depends on when you want to customize and if you are comfortable with the ApplicationWindow structure since as you can see the latter has a predefined structure.
Note: There are 2 items called ApplicationWindow 1, 2

QT QML not resizing dynamically

I am fairly new to QT and would need some help with qml dynamic resizing. I am using Visual Studio with QT plugin, MSVC 2017 compiler.
Here is my qml file:
import QtQuick 2.0
import QtQml.Models 2.1
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.11
Rectangle
{
anchors.fill: parent
// or width/height here
Rectangle
{
anchors.fill: parent
color: "blue"
}
}
My custom QQuickWidget:
customWidget::customWidget(QWidget *parent)
{
this->setParent(parent);
this->setGeometry(QRect(QPoint(0, 0), parent->size())); //this is for debugging only
this->setResizeMode(QQuickWidget::SizeRootObjectToView);
this->setSource(QUrl::fromLocalFile("qmlpath"));
}
Widget Initialization
myWidget = new customWidget(ui.widgetArea); // widgetArea is an empty QWidget from the Qt Designer
qDebug() << myWidget->errors();
QVBoxLayout* layout = new QVBoxLayout(myWidget);
ui.widgetArea->setLayout(layout);
I have tried other suggestions like enclosing the rectangles in a grid layout for example and use "layout.fillWidth: true" etc.
Everything gives me a blank space (widget size of 0, 0) instead of a blue rectangle, unless I define a fixed width and height for it. Is there anything that I'm missing?

Dynamically add Menu in MenuBar of ApplicationWindow in QML

I'm trying to create an application that is extensible with plugins. Now the plugins should be able to add a Menu dynamically in the MenuBar.
From documentation I can find a MenuBar that is provided by QtLabsPlatform. This has a method addMenu. But Windows was not in the list of supported platforms. So I cannot benefit from it.
I tried the placeholder technique suggested in Error adding a Menu in QML, but this does not work with QtQuick.Controls 2.13
In the #timday answer in the question you indicate indicates the answer but does not show an example:
...
Dynamic creation of Menus is a little harder; see Qt.createQmlObject
or Qt.createComponent docs. (It may be simpler to just declare all the
ones you need in your code, but with their visible property wired to
whatever logic is appropriate). ...
(emphasis mine)
So my answer is just to show you how to do it although I think you want to add MenuItem to a Menu dynamically, instead of a Menu to a MenuBar:
import QtQuick 2.13
import QtQuick.Controls 2.13
ApplicationWindow {
id: root
width: 640
height: 480
visible: true
menuBar: MenuBar {
Menu {
id: plugins_menu
title: qsTr("&Plugins")
}
}
function onTriggered(item){
console.log(item.text)
}
Component.onCompleted:{
var plugin_names = ["plugin1", "plugin2", "plugin3"]
for(var i in plugin_names){
var item = Qt.createQmlObject('import QtQuick 2.13; import QtQuick.Controls 2.13; MenuItem {}',
plugins_menu)
item.text = plugin_names[i]
plugins_menu.addItem(item)
var f = function(it){
it.triggered.connect(function (){ root.onTriggered(it)
})}
f(item)
}
}
}

How to embed a QML view into a native window

I'm having a problem trying to insert a QML view into a native OSX window. I know it's possible, but I don't know what I'm doing wrong.
Basically, my goal is, given a native NSView* to then embed a QML based widget. The problem is that I get it to point where it does indeed renderer the qml inside the view but it creates an extra transparent window to the side and it doesn't seem to redraw the QML view properly.
Here's the code that I'm using (please disregard all the memory leaks):
#interface AppDelegate ()
-(void)processEvents;
#property(nonatomic) NSTimer* timer;
#property(nonatomic) QApplication* qt;
#end
#implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
// Insert code here to initialize your application
NSWindow* window = [[[NSApplication sharedApplication] windows] objectAtIndex:0];
NSView *view = [window contentView];
assert(view);
char* test[0];
int count = 0;
QApplication::instance()->setAttribute(Qt::AA_MacPluginApplication);
_qt = new QApplication(count, test);
QMacNativeWidget* native = new QMacNativeWidget(view);
assert(native);
QQuickWidget* qml = new QQuickWidget(native);
qml->setSource(QUrl(QStringLiteral("main.qml")));
QVBoxLayout* layout = new QVBoxLayout();
layout->addWidget(qml);
native->setLayout(layout);
qml->show();
native->show();
NSView* qmlView = (NSView*)native->winId();
[view addSubview:qmlView];
_timer = [NSTimer scheduledTimerWithTimeInterval:0.03 target:self selector:#selector(processEvents) userInfo:nil repeats:YES];
}
- (void)applicationWillTerminate:(NSNotification *)aNotification
{
// Insert code here to tear down your application
[_timer invalidate];
_qt->quit();
}
-(void)processEvents
{
_qt->processEvents();
_qt->sendPostedEvents(0,-1);
}
#end
And here's the simple qml:
import QtQuick 2.7
Item
{
visible: true
x: 0;
y: 0;
width: 100
height: 100
Rectangle
{
anchors.fill: parent
color: 'blue'
MouseArea
{
anchors.fill: parent
onClicked:
{
console.log(parent.color);
if(parent.color == '#0000ff')
parent.color = 'green';
else
parent.color = 'blue';
}
}
}
}
QQuickWidget composities its content with other widget content in a slightly complex way, involving a framebuffer and offscreen window, which I suspect might explain the odd results you see - I would not expect it to work in a plugin situation.
The easiest option would be use a QQuickWindow (or QQuickView) with createWindowContainer to turn the QWindow into a QWidget you can parent to your QMacNativeWidget.
However, I think the most robust approach would be to ignore widgets and windows entirely, and integrate at the framebuffer level, using QQuickRenderControl and an NSOpenGLView. This is more work to code up but keeps the NSView hierarchy straightforward, and should give the best possible performance. You can either render directly into the native OpenGL view (which requires creating a QOpenGLContext from the native context, possible since Qt 5.4), or into a framebuffer using a texture shared between the QtQuick and NSOpenGLContext.

QML: referencing root window by parent reference is unreliable

Qt/QML question. Using Qt 5.7.
Take the following simple QML program that displays a red rectangle and a blue rectangle aligned vertically. Click handlers for both rectangles attempt to change the color of the parent host window. But with a subtle difference. The red rectangle references the host window directly by it's id (rootWindow). The blue click handler changes color via a parent reference.
The former case works fine. The latter case does not work. It seems like the root window is treated specially and isn't directly part of the parent/child hierarchy, even if the Rectangles are logically nested in the code that way.
Can someone explain the rule around this?
import QtQuick 2.7
import QtQuick.Window 2.2
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
id: rootWindow
color: "#ffffee"
Rectangle {
id: rect1; width: 50; height: 50; color:"red"
MouseArea {
anchors.fill: parent;
onClicked: {
print("rect1 clicked");
rootWindow.color = "green"; // works fine
}
}
}
Rectangle {
id: rect2; width: 50; height: 50; color:"blue"
anchors.top: rect1.bottom
MouseArea {
anchors.fill: parent;
onClicked: {
print("rect2 clicked");
rect2.parent.color = "pink"; // does not work
}
}
}
}
If you add the following line to the onClicked handler, you'll see that its parent isn't the Window:
print(rect2.parent)
Output:
qml: QQuickRootItem(0x18b18147bc0)
This is explained not-so-visibly in the documentation for Window:
If you assign an Item to the data list, it becomes a child of the Window's contentItem, so that it appears inside the window. The item's parent will be the window's contentItem, which is the root of the Item ownership tree within that Window.
The window itself isn't an item, so it uses contentItem instead so that child items can have a parent.
However, in Qt 5.7, Window got an attached property that can be used to access the window of an item:
rect2.Window.window.color = "pink";
Whichever item comes before the Window.window part will be the item that the attached property is used on. You could use it on any item in this scene (e.g. the MouseArea), as they all belong to the same window.
Note that attached properties create a QObject-derived object for each unique item they're used on, so be mindful of how you use them, especially in items that are created in very large numbers.

Resources