I am new in Qt. I am working on windows desktop application and using Qt with qml. On PC that hasn't QTouchDevices, splitter between component (element that allow you resize component on window) works good with mouse (screenshot "Good distance"), but if screen is touchscreen I have next problem, please look on screenshot "Wrong distance".
My application shouldn't support any touch device. So how to disable this Qt feature? I need the same behavior like on device without touch screen.
Wrong distance
Good distance
I have tried disable touch device using privet methods using next sample:
QWindowSystemInterface::unregisterTouchDevice(QTouchDevice::devices().first());
This works, but QWindowSystemInterface is private class and it disable touchscreen. And one more in QTCreator splitters work fine, exactly as I need.
If you can't patch Qt, the only way that I can think of would be to iterate through the children, searching for the MouseArea. For example, suppose you had this QML:
import QtQuick 2.5
import QtQuick.Controls 1.4
import QtQuick.Layouts 1.1
ApplicationWindow {
width: 600
height: 400
visible: true
property alias splitView: splitView
SplitView {
id: splitView
anchors.fill: parent
Rectangle {
width: 200
Layout.maximumWidth: 400
color: "lightblue"
Text {
text: "View 1"
anchors.centerIn: parent
}
}
Rectangle {
id: centerItem
Layout.minimumWidth: 50
Layout.fillWidth: true
color: "lightgray"
Text {
text: "View 2"
anchors.centerIn: parent
}
}
}
}
You could then print out the object tree of the SplitView like so:
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQuickItem>
#include <QDebug>
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
QObject *window = engine.rootObjects().first();
QQuickItem *splitView = window->property("splitView").value<QQuickItem*>();
splitView->dumpObjectTree();
return app.exec();
}
That gives you:
SplitView_QMLTYPE_1::
QQmlComponent::
QQuickSystemPalette::
QObject_QML_2::
QQmlComponent::
QQuickItem::
QQuickItem::
QQuickItem::
QQuickLoader_QML_3::
QObject_QML_4::
QQuickMouseArea_QML_5::
QQuickRectangle::
QQmlContext::
QQuickItem::
QQmlComponentAttached::
QQuickRectangle::
QQuickText::
QQuickLayoutAttached::
QQuickRectangle::
QQuickText::
QQuickLayoutAttached::
QQuickLayoutAttached::
QObject::dumpObjectTree() prints out metaObject->className(), so we know to look for an object whose metaObject has a className matching that:
Then:
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQuickItem>
#include <QScreen>
#include <QWindow>
#include <QDebug>
QQuickItem *findMouseArea(QQuickItem *item)
{
foreach (QQuickItem *childItem, item->childItems()) {
if (QString(childItem->metaObject()->className()).startsWith(QStringLiteral("QQuickMouseArea_QML"))) {
return childItem;
} else {
QQuickItem *mouseArea = findMouseArea(childItem);
if (mouseArea) {
return mouseArea;
}
}
}
return 0;
}
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
QWindow *window = qobject_cast<QWindow*>(engine.rootObjects().first());
QQuickItem *splitView = window->property("splitView").value<QQuickItem*>();
QQuickItem *mouseArea = findMouseArea(splitView);
mouseArea->setProperty("defaultMargin", QVariant(window->screen()->physicalDotsPerInch() / 25.4));
return app.exec();
}
Apparently, Screen::pixelDensity is calculated using the physical dots per inch of the screen, divided by 25.4, so we copy that as well. You could use any other value there.
You will need to adapt the code should a second MouseArea ever be introduced, for example.
It's still largely dependent on private API, but it doesn't touch Qt code, at least.
Quick&Easy: enable/disable mouse and touch synthesizing
No need to patch things or doing any crazy tree lookups, just enable or disable mouse or touch synthesizing.
Qt::AA_SynthesizeTouchForUnhandledMouseEvents
Qt::AA_SynthesizeMouseForUnhandledTouchEvents
Just disable what you don't want, either mouse or touch to accept only authentic events.
Related
I have a C++ plugin system, where a QQmlComponent is created and a qml file is loaded when the user requests a new plugin instance.
Currently I am using setContextProperty() to tell QML about a QObject that is needed for proper initialization.
mEngine->rootContext()->setContextProperty("controller", QVariant::fromValue(mController));
mComponent = new QQmlComponent(mEngine);
mComponent->loadUrl(QUrl{ "qrc:///MyPlugin.qml" });
The problem is, when instantiating a second plugin, both will use the controller of the second one because "controller" is global in QML.
Repeater {
model: controller.numEntries
Is there a way to set a context property locally (only for the current instance)?
I found solutions using setProperty() or QQmlIncubator and setInitialState(), but they all seem to require an object that was already created from my component. But in my plugin I only define the component, which is loaded in the main application through a Loader item. So, when trying these approaches, I always ended up in setting the value in a copy of the item, but not the one being created in my backend.
How can I get access to a property of the component that is created in QML?
mComponent->findChild<QQuickItem*>("controller");
does not give me any results, even if I defined the property in MyPlugin.qml.
Maybe you can create a QObject based class and have a slot and instead of using property you can call slot to slot create a new property in c++ and return it to QML
ControllerCreator.h
#ifndef CONTROLLERCREATOR_H
#define CONTROLLERCREATOR_H
#include <QObject>
class ControllerCreator : public QObject {
Q_OBJECT
public:
explicit ControllerCreator(QObject *parent = nullptr);
signals:
public slots:
int propertyCreator();
private:
int m_example;
};
#endif // CONTROLLERCREATOR_H
ControllerCreator.cpp
#include "ControllerCreator.h"
ControllerCreator::ControllerCreator(QObject *parent)
: QObject(parent), m_example(0)
{
}
int ControllerCreator::propertyCreator()
{
m_example++;
return m_example;
}
main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include "ControllerCreator.h"
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
ControllerCreator controllerCreator;
engine.rootContext()->setContextProperty("creator", &controllerCreator);
engine.load(QUrl(QLatin1String("qrc:/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
return app.exec();
}
main.qml
import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.3
ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Column{
anchors.fill: parent
Text{
text: creator.propertyCreator()
color: "blue"
}
Text{
text: creator.propertyCreator()
color: "red"
}
Text{
text: creator.propertyCreator()
color: "green"
}
}
}
I want to create a QQuickWidget with no parent, i.e window. I read about the doc(about QQuickWidget):
Making the window semi-transparent, with other applications and the
desktop visible in the background, is done in the traditional way: Set
Qt::WA_TranslucentBackground and change the Qt Quick Scenegraph's
clear color to Qt::transparent via setClearColor().
Here is the code I wrote, it works fine on Qt5.5.0 + Mint17.0 with an runtime warning-"QQuickWidget: Attempted to render scene with no context". When running on Windows10 + Qt 5.4.2, it is completely transparent.
//main.cpp
#include <QApplication>
#include <QQuickWidget>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
auto quick = new QQuickWidget();
quick->setWindowFlags(Qt::FramelessWindowHint|Qt::WindowStaysOnTopHint);
quick->setAttribute(Qt::WA_TranslucentBackground, true);
quick->setClearColor(Qt::transparent);
quick->setSource(QUrl("qrc:/main.qml"));
quick->show();
return a.exec();
}
//main.qml
import QtQuick 2.4
Rectangle {
height: 360
width: 360
color: "transparent"
Text{
text: "hello"
}
}
I've just started to learn about Qt Mobile programming with Qt Quick 2.0 and I've been on google the whole day and its driving me crazy so here goes.
I have got just your standard qt quick mobile app that qt makes for you. Here is all the files.
(I'm brand new to this so these might be noob qu's, sorry)
Ok so here is my list of I Don't Knows:
how on earth do I connect this class method to the button click in the qml file.
Would it be possible to connect the same click and pass params through the click from the qml to the method and if so how would I do it?
and also I was wondering if I could link the class to the qt quick like a regular QWidget class for instance:
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
SomeClass *sc = new SomeClass();
QtQuick2ApplicationViewer viewer;
// this I guess would be more like the Widget method but this i really dont know
// about, just a question I'm throwing out there
viewer. (Link qt quick qml to object "sc"(Containing all my processes))
viewer.setMainQmlFile(QStringLiteral("qml/Final2/main.qml"));
viewer.showExpanded();
return app.exec();
}
The main(.)cpp file
#include <QtGui/QGuiApplication>
#include "qtquick2applicationviewer.h"
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QtQuick2ApplicationViewer viewer;
viewer.setMainQmlFile(QStringLiteral("qml/Final2/main.qml"));
viewer.showExpanded();
return app.exec();
}
This is just the button element from my main.qml
Button {
id: btn
y: 443
height: 39
text: "Click Me"
anchors.bottom: parent.bottom
anchors.bottomMargin: 8
anchors.right: parent.right
anchors.rightMargin: 25
anchors.left: parent.left
anchors.leftMargin: 15
}
This is just some random class header :
#ifndef SOMECLASS_H
#define SOMECLASS_H
#include <QObject>
#include <QDebug>>
class SomeClass : public QObject
{
Q_OBJECT
public:
explicit SomeClass(QObject *parent = 0);
signals:
public slots:
void buttonClicked();
void buttonClicked(QString &in);
};
#endif // SOMECLASS_H
Of course the cpp file :
#include "someclass.h"
SomeClass::SomeClass(QObject *parent) :
QObject(parent)
{
}
void SomeClass::buttonClicked()
{
// do something
}
void SomeClass::buttonClicked(QString &in)
{
qDebug() << "Your string was : " << in;
}
I really appreciate all the help.
Thank you.
First, you need to export the SomeClass object to QtQuick (is that your third question?):
SomeClass sc;
viewer.rootContext()->setContextProperty(QStringLiteral("_someObject"), &sc);
This makes the sc object available in QtQuick, under the name "_someObject".
Then, in the QML use it like this:
Button {
....
onClicked: {
_someObject.buttonClicked(); //_someObject is the name used in setContextProperty.
}
}
This assumes the Button has a signal clicked() that's emitted on click/touch. Not knowing which Button component you use, I can't check that.
To pass an argument, just do
onClicked: {
_someObject.buttonClicked("Something");
}
I am trying to port a simple Qt Quick application from Qt4.8 to Qt5.0beta.
my initial (Qt4.8) code is similar to what is below:
main.cpp will dipsplay a QDeclarativeView in a frameless window with translucent background
#include <QtGui/QApplication>
#include "qmlapplicationviewer.h"
#include <QtDeclarative>
#include <QDeclarativeContext>
Q_DECL_EXPORT int main(int argc, char *argv[])
{
QScopedPointer<QApplication> app(createApplication(argc, argv));
QmlApplicationViewer viewer;
viewer.setOrientation(QmlApplicationViewer::ScreenOrientationAuto);
viewer.setMainQmlFile(QLatin1String("qml/main.qml"));
viewer.setWindowFlags(Qt::FramelessWindowHint);
viewer.setAttribute(Qt::WA_TranslucentBackground);
viewer.setStyleSheet("background:transparent;");
viewer.setResizeMode(QDeclarativeView::SizeViewToRootObject);
viewer.showExpanded();
return app->exec();
}
and the main.qml will just display a red rectangle inside another transparent rectangle.
import QtQuick 1.1
Rectangle {
width: 360
height: 360
color: "transparent"
Rectangle
{
x: 125
y: 122
width: 110
height: 116
anchors.centerIn: parent
color: "red"
radius: 27
}
Text {
color: "black"
text: qsTr("Press me!")
font.pointSize: 14
anchors.centerIn: parent
}
MouseArea {
anchors.fill: parent
onClicked: {
Qt.quit();
}
}
}
In order to make it compatible with Qt5 few changes were necessary.
(I have followed http://qt-project.org/doc/qt-5.0/portingqmlapp.html [qt-project.org]
in order not to miss something)
Now main.cpp is similar to:
#include <QtGui/QGuiApplication>
#include "qtquick2applicationviewer.h"
#include <QtWidgets/QtWidgets>
#include <QtWidgets/QLabel>
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QtQuick2ApplicationViewer viewer;
viewer.setMainQmlFile(QStringLiteral("qml/main.qml"));
viewer.setWindowFlags(Qt::FramelessWindowHint);
viewer.showExpanded();
return app.exec();
}
In main.qml only one line was replaced.
import QtQuick 2.0
but I am not able to find a way of keeping the transparency
setAttribute(Qt::WA_TranslucentBackground);
setStyleSheet("background:transparent;");
setAttribute and setStyleSheet were available for a QDeclarativeView (which is a QWidget)
but not for QQuickView (which is a QWindow)
Try my QuickWidget, if it helps you:
http://code.google.com/p/quickwidget/
Or, even better, use QQuickWidget from Qt 5.3+.
I am trying to build a game in which the ui part is made in qml (menu etc) while the rendering and logic part is in C++. For this I'm using a QGLWidget subclass. The game starts with Qml (using a QDeclarativeContext in the main function) and on clicking 'NewGame', I am loading my QGLWidget subclass. Something like this:
GameButton{
id:button2_1_1
x: 69
y: 101
width: 80
height: 80
onClicked:{ myObject.initialize(); myObject.show(); }
}
// myObject sets the context property to the object of my QGLWidget subclass
The problem is that I can't figure out a way to close my Qml window when I load the QGLWidget. As with what I've done two windows are displayed simultaneously.
Here's the code for it.
// import QtQuick 1.0 // to target S60 5th Edition or Maemo 5
import QtQuick 1.1
Rectangle {
id:newGameMenu
width: 640
height: 360
signal button2Clicked();
onButton2Clicked: console.log("new game should start")
Image{
id:background
source:"menubackground.jpg"
anchors.fill:parent
Button2 {
id: button21
x: 70
y: 101
width: 42
height: 42
}
}
Button2{
id:button2_1_1
x: 69
y: 101
width: 44
height: 44
onClicked:{ myObject.abc(); myObject.show(); console.log("glwindow called"); }
}
}
main.cpp
#include <QtGui/QApplication>
#include "qmlapplicationviewer.h"
#include <QDeclarativeView>
#include <QDeclarativeItem>
#ifndef GLWINDOW_H
#include "glwindow.h"
#endif
#include <QObject>
Q_DECL_EXPORT int main(int argc, char *argv[])
{
QScopedPointer<QApplication> app(createApplication(argc, argv));
QDeclarativeView view;
GLWindow w;
view.rootContext()->setContextProperty("myObject", &w);
view.setSource(QUrl::fromLocalFile(""));
view.show();
qDebug() << "into the qml";
return app->exec();
}
As with what I've done two windows are displayed simultaneously
I feels like you are showing two window, one QDeclarativeView and other QGLWidget.
In that case, you should try to hide, your QDeclarativeView when you are showing QGLWidget,
see http://qt-project.org/forums/viewthread/4109 which probably answers your question
Try setting .visible=false for the menu widget in onClicked.
What about http://qt-project.org/forums/viewthread/15160/
Also I would use a QStackedWidget with 2 QWidgets: One would be QDeclarativeView that holds your QML and the other QGLWidget that holds your OpenGL; Moving between QML and OpenGL would mean calling QStackedWidget::setCurrent();