I am new to QT and want to develop a QT Quick app for the raspberry pi and its touch LCD display. The app should have several screens (sorry, not sure what the right terminology is, with screen I mean a state of the app which fills the whole display of the Raspberry Pi) and there should be buttons to switch between those screens. How is it possible to switch to a different screen when I press a button?
I tried using loader but (right now I am testing on the Desktop not the Raspberry) it opens the qml file in a new window, but I would like to have the content of the original window replaced.
Edit:
Yes, I plan using EGLFS. I enclose some code which does in principle what I want. However, I am not sure if this is the right way to do things: I put the screens I want to have into their own qml file, and toggle their visibility through buttons our mouse areas:
main.qml
import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.0
ApplicationWindow {
visible: true
width: 800
height: 460
title: qsTr("Hello World")
Page1 {
id: page1
visible: true
}
Page2 {
id: page2
visible: false
}
}
Page1.qml
import QtQuick 2.7
import QtQuick.Controls 2.0
Item {
Button {
id: button1
width: 200
height: 40
text: qsTr("To second page")
onClicked: {
page2.visible=true
page1.visible=false
}
}
}
Page2.qml
import QtQuick 2.3
import QtQuick.Window 2.2
Item {
Text {
id: text1
x: 181
y: 153
text: qsTr("Second Page")
font.pixelSize: 12
}
Rectangle {
id: rectangle
x: 252
y: 222
width: 200
height: 200
color: "#000000"
border.color: "#f12525"
}
MouseArea {
id: mouseArea
x: 234
y: 209
width: 244
height: 225
onClicked:{
page1.visible=true
page2.visible=false
}
}
}
I would venture to guess that most likely you want to use Qt5's eglfs mode on the raspberry pi. This gets rid of the normal desktop and runs your Qt5 (regular or QML) app full screen. When I last did this, I needed to compile Qt5 myself. That is something you will either want to figure out cross compiling for, or use a RaspberryPi 3 (the results can then be copied to slower Raspberry Pis if desired). I worked from the guide at https://wiki.qt.io/RaspberryPi2EGLFS
It was pretty trivial to run the program then in a window on a linux desktop or full screen on a Raspberry Pi with touch screen (both the special 7" screen or a generic 22" touch display).
A newer looking alternative to using eglfs is apparently the QtWayland Compositor. I haven't used it, but there is an interesting presentation on using it for full screen embedded applications from the most recent (2017) FOSDEM, available here: https://fosdem.org/2017/schedule/event/device_specific_compositors/
Related
This post is a copy of a message I already sent on the Qt forum but I couldn't get an answer.
You can find the original post here: https://forum.qt.io/topic/113890/prevent-mousearea-s-positionchanged-signal-to-propagate-in-scrollview/4
If the link is dead, everything is copied below:
I am trying to handle a positionChanged signal in a MouseArea (to create kind of a drag&drop effet) that is in a ScrollView.
My problem is that after the mouse travelled a short distance, the parent ScrollView seem's to get the focus (the scrollbar appears) and I stop to receive positionChanged signals.
The objective would be to receive the positionChanged signal (even if the mouse gets out of my MouseArea & over the ScrollView as long as my left mouse button stays pressed) without propagating the signal to the ScrollView.
I have 3 separate examples. This is a simple QML application that should be easy to run.
The two first examples work. The third does not work.
What is "working":
Press the mouse button down on the MouseArea
Move the mouse around without releasing the button
The message that logs coordinates should never stop printing, wherever you are on screen until you release the mouse button.
For the third example, I get logs until the mouse moves too much and all the updates stop.
Only ScrollView (works)
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12
ApplicationWindow{
id: root
visible: true
width: 1200
height: 600
ScrollView {
clip: true
anchors.fill: parent
MouseArea {
width: 300
height: 300
onPositionChanged: {
console.log('Moved', mouseX, mouseY)
}
}
}
}
Only ColumnLayout (works)
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12
ApplicationWindow{
id: root
visible: true
width: 1200
height: 600
ColumnLayout {
MouseArea {
width: 300
height: 300
onPositionChanged: {
console.log('Moved', mouseX, mouseY)
}
}
}
}
ColumnLayout inside a ScrollView (does not work)
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12
ApplicationWindow {
id: root
visible: true
width: 1200
height: 600
ScrollView {
clip: true
anchors.fill: parent
// note: It does not work for ColumnLayout, Column, Row or RowLayout. If I use a Item here, it works
ColumnLayout {
MouseArea {
width: 300
height: 300
onPositionChanged: {
console.log('Moved', mouseX, mouseY)
}
}
}
}
}
You can find a video of the behavior here: https://i.imgur.com/rIlWnhu.mp4
I press and release the mouse without moving: I get the pressed & released events correctly
I press and move the mouse: I get the pressed event, the move event, then it stops. No more move or released events.
I press and move the mouse without going too far from the position where I pressed the mouse: It works until I get too far
Note: I don't get any Released or Exited event, but the containsPressed property is correctly updated (ie: when I no longer receive events, its value is false). This is the property that I use to display the "Mouse pressed" text.
Is this something I do wrong with the ScrollView/ColumnLayout combo or is this a Qt bug ?
Add this to your MouseArea in your third example:
preventStealing: true
For more info see:
https://doc.qt.io/qt-5/qml-qtquick-mousearea.html#preventStealing-prop
There's a plugin called Qt.labs.platform. Among other things, it provides tray icon with a menu. That menu has a list of MenuItems. Any menu item may have an icon, which would be displayed on the left side of item's text.
There's two ways of setting the icon, none of which work for me:
1) Version 1.0 defined iconSource and iconName properties.
Silently does not work, just shows no icon.
2) Revision 1.1 (declared as Q_REVISION(1)) introduces icon.name, icon.source and icon.mask "sub-properties" (not sure what's the right name for it?)
Fails QML engine with a message:
"MenuItem.icon" is not available in Qt.labs.platform 1.1.
I tried both import Qt.labs.platform 1.1 and 1.0.
Am I missing something in the mechanics of QML revisions or this is a bug in Qt?
A MenuItem is declared in qquickplatformmenuitem_p.h and defined in qquickplatformmenuitem.cpp files.
I'm using ArchLinux, KDE/Plasma. Some other apps (like electron-based) do have their icons in menu showing properly.
UPD Reported as a Qt bug.
I don't know what exactly you are doing to achieve your goal, because there is no minimal reproducible example.
But take a look at here
import QtQuick 2.12
import QtQuick.Window 2.12
// import Qt.labs.platform 1.1
import QtQuick.Controls 2.12
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Rectangle {
width: 200
height: 200
anchors.centerIn: parent
MenuBar {
id: menuBar
Menu {
id: firstMenu
MenuItem {
icon.name: "download"
icon.source: "icons/cloud-down-icon.png"
}
MenuItem {
text: qsTr("Rewrap Paragraph")
onTriggered: rewrapParagraph()
}
}
}
}
}
Note: put your icon inside the icons folder in the project folder.
If you click on the menu then you should get a dropdown with two items, first one is just an icon without the text (you can include some text by yourself), second item is just a text.
I am following this tutorial on YouTube and the person sets the TextField to fill the width of the RowLayout. However, it doesn't seem to work for me. I tried using Layout.fillWidth on the CheckBox and it seems to work perfectly fine but it doesn't seem to want to work on the TextField. Here is my code:
main.qml:
import QtQuick 2.9
import QtQuick.Controls 2.2
ApplicationWindow
{
visible: true;
width: 640;
height: 480;
title: qsTr("Tabs");
ToDoList
{
anchors.centerIn: parent;
}
}
ToDoList.qml:
import QtQuick 2.9
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.3
Frame
{
ListView
{
// Using implicit width and height allows the frame to automatically scale to the size of the list view
implicitWidth: 250
implicitHeight: 250
clip: true
model: 100
delegate: RowLayout {
width: parent.width
CheckBox {}
TextField
{
Layout.fillWidth: true
}
}
}
}
Here is a screenshot of what mine looks like
What did I do wrong?
I don't know if this has anything to do with it but I made a "Qt Quick Application - Swipe" instead of "Qt Quick Controls 2 Application" as that option wasn't available to me. Thanks in advance for any help.
Edit: I have written step by step instructions to replicate the issue below.
File > New File or Project
From the new window make sure "Application" is selected then click "Qt Quick Application - Swipe" and press "Choose"
Set any name for the project and click "Next"
Set the build system to "qmake" and click "Next"
Set the minimal required Qt version to "Qt 5.9" and the Qt quick controls style to "Material Dark" and click "Next"
Select the "Desktop Qt 5.12.0 MSVC2017 64bit" as the kit and click "Next"
Set the options to have no version control and click "Finish"
Delete "Page1Form.ui.qml" and "Page2Form.ui.qml" from the "Projects" pane
Replace the contents of "main.qml" with:
import QtQuick 2.9
import QtQuick.Controls 2.2
ApplicationWindow
{
visible: true;
width: 640;
height: 480;
title: qsTr("Tabs");
ToDoList
{
anchors.centerIn: parent;
}
}
Right click on the root project file and click "Add New"
From the new window make sure "Qt" is selected then click "QML File (Qt Quick 2)" and press "Choose"
Name the file "ToDoList" and click "Next"
Add to project "qml.qrc Prefix: /" then set the options to have no version control and click "Finish"
Replace the contents of "ToDoList.qml" with:
import QtQuick 2.9
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.3
Frame
{
ListView
{
// Using implicit width and height allows the frame to automatically scale to the size of the list view
implicitWidth: 250
implicitHeight: 250
clip: true
model: 100
delegate: RowLayout {
width: parent.width
CheckBox {}
TextField
{
Layout.fillWidth: true
}
}
}
}
Run the project
The width is set properly. The problem is with TextField style. You may check it by setting background like
TextField
{
Layout.fillWidth: true
background: Rectangle {
color: "red"
}
}
Or just start typing into those fields with and without Layout.fillWidth: true
The issue seems so trivial that I almost believe it's a bug in Qt itself:
import QtQuick.Window 2.2
import QtQuick 2.2
import QtQuick.Controls 1.2
import QtQuick.Controls.Styles 1.2
import QtQuick.Layouts 1.1
Window {
id: window
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Rectangle {
color: "white"
Layout.columnSpan: 2
Layout.fillHeight: true
Layout.fillWidth: true
radius: 5
width: 640/2
height: 480/2
TextArea {
id: txtMemo
anchors.fill: parent
anchors.margins: 5
textColor: "black"
wrapMode: TextEdit.Wrap
readOnly: false
}
}
Button {
x: 0
y: 480/2
width: 640/2
height: 480/2
onClicked: {
//Qt.inputMethod.hide()
txtMemo.visible = false
}
}
}
You need to run this on an Android device to see the bug:
Type something in to the text area so the cursor and virtual keyboard appears.
When you click the button, the cursor & keyboard stay on screen. No idea why, perhaps a feature.
Anyways, that's not the main issue. When I uncomment Qt.inputMethod.hide() and trying to reproduce, an interesting thing happens:
if the keyboard is visible, both the cursor and keyboard disappear - awesome, exactly what I want
however if the keyboard isn't visible (closed by the arrow on the bottom during typing) and the cursor is, the cursor won't disappear at all:
(apologies for the picture quality)
So how do I get rid of the cursor? Tested on Qt 5.9.6 on Android (seems unrelated on Android version, happens on the latest version as well).
Is there already something like the android "toast" fading message popup for qml? I surely can create something by myself but I would assume/hope that there already is something like that delivered with Qt / QtQuickControls2
See ToolTip. It is styled like a "toast" when using the Material style.
import QtQuick 2.9
import QtQuick.Controls 2.2
ApplicationWindow {
width: 360
height: 520
visible: true
Button {
text: "Button"
anchors.centerIn: parent
ToolTip.text: "ToolTip"
ToolTip.visible: pressed
ToolTip.timeout: 3000
ToolTip.delay: 500
}
}