In my project I created a transparent and frameless QMainWindow, then created QmlApplicationViewer. I need to be able to drag and resize the window.
How can I do?
This app is a small variation of the one presented here to deal with transparent windows in QML applications:
win.cpp:
#include <QApplication>
#include <QDeclarativeView>
#include <QMainWindow>
#include <QDeclarativeContext>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QMainWindow window;
QDeclarativeView* v = new QDeclarativeView;
window.setCentralWidget(v);
v->setSource(QUrl::fromLocalFile(("draw_rectangles.qml")));
// expose window object to QML
v->rootContext()->setContextProperty("mainwindow",&window);
window.setStyleSheet("background:transparent;");
window.setAttribute(Qt::WA_TranslucentBackground);
window.setWindowFlags(Qt::FramelessWindowHint);
window.show();
app.exec();
}
win.pro:
TEMPLATE += app
QT += gui declarative
SOURCES += win.cpp
draw_rectangles.qml:
import Qt 4.7
Item {
Rectangle {
opacity: 0.5
color: "red"
width: 100; height: 100
MouseArea {
anchors.fill: parent
onPressed: {
mainwindow.size.width = 200;
mainwindow.size.height = 500;
}
}
Rectangle {
color: "blue"
x: 50; y: 50; width: 100; height: 100
MouseArea {
id: mouseRegion
anchors.fill: parent;
property variant clickPos: "1,1"
onPressed: {
clickPos = Qt.point(mouse.x,mouse.y)
}
onPositionChanged: {
var delta = Qt.point(mouse.x-clickPos.x, mouse.y-clickPos.y)
mainwindow.pos = Qt.point(mainwindow.pos.x+delta.x,
mainwindow.pos.y+delta.y)
}
}
}
}
}
Even though you are not interested in transparency, this app shows how to expose QMainWindow to QML. This allows the QML application to make changes in the main window.
Click on the blue rectangle to drag the window around, and click on the red rectangle to resize the window using hardcoded values in the qml. Of course, as the window is transparent you won't have the visual feedback of a regular opaque application when you resize it. But the resize operation works, though. Enjoy!
Related
I have a QML window declared for example in MyWindow.qml:
Item {
id: thisWindow
width: 500
height: 140
... sub-items that declare the UI of the window ...
And a C++ class that instantiates that QML:
class MyWindow : public QQuickView
...
MyWindow::MyWindow() {
setSource(QUrl("qrc:/MyWindow.qml"));
setFlags(Qt::WindowFlags(Qt::Popup));
}
How do I close that window from Javascript/QML code?
I can't call thisWindow.close(), because it's just an item type in the hierarchy.
You don't need c++ to do that. You can do it with the window attached property straight from QML.
//other imports
import QtQuick.Window 2.2
Item {
id: thisWindow
width: 500
height: 140
//... sub-items that declare the UI of the window ...
MouseArea {
anchors.fill: parent
onClicked: Window.window.close()
}
}
The easiest option is to export the QQuickView to the .qml with setContextProperty():
#include <QQmlEngine>
#include <QQmlContext>
// ...
{
engine()->rootContext()->setContextProperty("view", this);
setSource(QUrl("qrc:/MyWindow.qml"));
setFlags(Qt::WindowFlags(Qt::Popup));
}
And then in QML you can use:
view.close()
Use the Qt global object and follow the instruction here:
http://doc.qt.io/qt-5/qml-qtqml-qt.html#quit-method
I want to enumerate all the objects (derived from QObject) existent and newly created in QQmlApplicationEngine. The main goal it to execute the following lines of code for each of them:
void denominate(QObject * const object)
{
if (object->objectName().isEmpty()) {
object->setObjectName(object->metaObject()->className());
}
}
It is needed to distinct some of the objects in QML runtime. Say, when StackView items are created from Components and I want to know which of them is really on the top.
Creation of some of components or C++ classes are delayed. And if I get a root objects and enumerate children() of them, it is a half of the solution. Also there is QQmlApplicationEngine::objectCreated signal, but I don't fully understand interrelation between contexts, engine and (root) objects.
How to name all the unnamed objects, which lives into QQmlEngine?
You can rename all of them using recursive enumeration
For example:
QML file:
import QtQuick 2.6
import QtQuick.Window 2.2
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
MouseArea
{
id: r1
width: 200
height: 200
}
Rectangle
{
id: r2
color: "green"
width: 100
height: 100
Item
{
id: r3
width: 50
height: 50
}
}
}
You can set their names in the c++ part using the next mechanism:
void changeNames(QList<QObject*> ch)
{
for( QObject* ob: ch)
{
if (ob->objectName().isEmpty())
{
ob->setObjectName(ob->metaObject()->className());
}
changeNames( ob->children() );
}
}
void enumerate(QList<QObject*> ch)
{
for( QObject* ob: ch)
{
qInfo() << ob->objectName();
enumerate( ob->children() );
}
}
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
QObject *rootObject = engine.rootObjects().first();
changeNames(rootObject->children());
enumerate(rootObject->children());
return app.exec();
}
You will see the next names in the output:
"QQuickRectangle"
"QQuickMouseArea"
"QQuickItem"
If you have to add new component dynamically you can repeat this procedure, or find necessary component and rename it
I am using the qml-box2d library. I would like to create a Box2D body with fixtures in C++ and use it in QML. Unfortunately, any time I create a b2Body object and create fixtures for the object my app crashes. If I use the Box2DBody object, that comes with the qml-box2d library, it doesn't show in QML.
I need the Box2D body with fixtures in C++ to collide with all Box2D bodies in QML. What is the proper way to do this?
Pay attention - Box2DBody is not visual item since it derived from QObject. It only adds physical properties to its target. Anyway, I think the easiest way to create physical bodies is to do that in QML. But if you still want to do that in C++ you can use the code below. Suppose, we have a scene in main.qml with a QML rect item:
Window {
width: 800
height: 600
visible: true
World {}
Rectangle {
objectName: "rect"
width: 100
height: 100
x: 350
y: 50
color: "green"
}
Rectangle {
id: floor
height: 50
anchors {
left: parent.left
right: parent.right
bottom: parent.bottom
}
color: "brown"
Body {
target: floor
fixtures: Box {
width: floor.width
height: floor.height
density: 0.5
friction: 0.5
restitution: 0.5
}
}
}
DebugDraw {
visible: true
opacity: 0.7
}
}
And now we want to "revive" it:
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
Box2DPlugin plugin;
plugin.registerTypes("Box2D");
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
QObject *root = engine.rootObjects()[0];
QQuickItem *rect = root->findChild<QQuickItem *>("rect");
Box2DBody * body = new Box2DBody(root);
body->setBodyType(Box2DBody::Dynamic);
body->setTarget(rect);
Box2DBox * fixture = new Box2DBox(rect);
fixture->setWidth(rect->width());
fixture->setHeight(rect->height());
fixture->setDensity(0.8);
fixture->setFriction(0.5);
fixture->setRestitution(0.5);
body->addFixture(fixture);
body->componentComplete();
return app.exec();
}
I'm beginning with QML in Qt Creator and I like too much everything I've read about it but now I found a complication.
See following code:
BLCMainWidget::BLCMainWidget(QWidget *parent) : BLCBaseWidgetControler(parent) {
QQuickView view;
view.setSource(QUrl("qrc:///main.qml"));
QWidget *container = QWidget::createWindowContainer(&view);
QHBoxLayout *layout = new QHBoxLayout;
layout->setSpacing(10);
layout->setAlignment(Qt::AlignHCenter);
layout->setContentsMargins(1, 1, 1, 1);
parent->setStyleSheet("background:QColor(200,100,150);");
layout->addWidget(container);
parent->setLayout(layout);
}
Where parent is my QWidget on QMainWindow of my application, but this code not show my QQuickView container. Obviously the parent in question has a setCentralWidget signed in main() method and I'm already using that concept for non-QML widgets perfectly. How can I fix that to show my QML object containers?
My QML is just a simple concept example:
import QtQuick 2.1
Item {
id: box
width: 640
height: 480
Rectangle {
id: redSquare
width: 30; height: 30
anchors.top: parent.top; anchors.left: parent.left; anchors.margins: 10
color: "green"
Text { text: "!"; font.pixelSize: 16; anchors.centerIn: parent }
}
}
Thanks
If you are using a recent version of Qt, QWidget::createWindoContainer is depricated. Create a QQuickWidget instead, and use it a a normal QWidget.
Take a look at this: QML C++ Integration
and this: Interact QML from C++
The LayoutMirroring QML attached property allows switching the directionality of an item from left-to-right to right-to-left, or vice versa. I would like to access an item's current LayoutMirroring values from C++ code, extending a QML application. I understand that the qmlAttachedPropertiesObject function can be used to access attached properties from C++, as explained in the documentation, but I don't know where I can find the class that represent this specific property in C++.
Is it possible to do that?
It's possible to read and write attached properties easily with QQmlProperty class since Qt5.
Simple main.qml file:
import QtQuick 2.0
Rectangle {
LayoutMirroring.enabled: true
LayoutMirroring.childrenInherit: true
}
Simple C++ code to read above LayoutMirroring.enabled attached property:
QQuickView view;
view.setSource(QUrl(QStringLiteral("qrc:/main.qml")));
view.show();
QQuickItem* rootItem = view.rootObject();
qDebug() << QQmlProperty::read(rootItem, "LayoutMirroring.enabled", qmlContext(rootItem));
Console output:
=> QVariant(bool, true)
import QtQuick 1.1
Rectangle {
id: parentRect
property alias layoutValue : LayoutMirroring.enabled// ? true : false;// Read Only
LayoutMirroring.enabled: false
LayoutMirroring.childrenInherit: true
width: 300; height: 50
color: "yellow"
border.width: 1
Row {
anchors { left: parent.left; margins: 5 }
y: 5; spacing: 5
Repeater {
model: 5
Rectangle {
color: "red"
opacity: (5 - index) / 5
width: 40; height: 40
Text {
text: index + 1
anchors.centerIn: parent
}
}
}
}
}
#include
#include
#include
#include
#include "qmlapplicationviewer.h"
Q_DECL_EXPORT int main(int argc, char *argv[])
{
QScopedPointer app(createApplication(argc, argv));
QScopedPointer viewer(QmlApplicationViewer::create());
viewer->setOrientation(QmlApplicationViewer::ScreenOrientationAuto);
viewer->setMainQmlFile(QLatin1String("qml/Test/main.qml"));
QDeclarativeProperty propLayout(viewer->rootObject(),"layoutValue");
QDeclarativeProperty propLayoutMargin(viewer->rootObject(),"anchors.leftMargin");
qDebug() showExpanded();
return app->exec();
}