Black screen after existing FullScreen mode - c++

I am trying to make a such thing:
I have a main window with a single button.
After pressing this button two semi transparent windows appear on all screens. They are in a FullScreen mode.
After 4 seconds screens dissapear.
Everything is ok. But when I cklick one of the screens, during process of disappearing, it becomes totaly black. How can I fix it?
// main.qml
import QtQuick 2.10
import QtQuick.Window 2.10
import QtQuick.Controls 2.2
Window {
id: main
visible: true
width: 100
height: 50
title: "Hello Splash World"
Button {
anchors.fill: parent
text: "Show splash"
onClicked: {
for (var i = 0; i < Qt.application.screens.length; ++i) {
var component = Qt.createComponent("SplashScreen.qml");
var window = component.createObject(main, {screen: Qt.application.screens[i]});
window.height = Qt.application.screens[i].height
window.width = Qt.application.screens[i].width
window.showSplash()
}
}
}
}
// SplashScreen.qml
import QtQuick 2.10
import QtQuick.Controls 2.2
ApplicationWindow {
id: splash
flags: Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint | Qt.WA_TranslucentBackground
color: "transparent"
Timer {
running: true
interval: 4000
onTriggered: hideSplash()
}
function showSplash() {
appearAnimation.start()
}
function hideSplash() {
disappearAnumation.start()
}
background: Rectangle {
id: bg
color: "black"
opacity: 0.8
}
SequentialAnimation {
id: appearAnimation
PropertyAction { target: splash; property: "visibility"; value: ApplicationWindow.FullScreen }
NumberAnimation { target: bg; property: "opacity"; duration: 1000; to: 0.8 }
}
SequentialAnimation {
id: disappearAnumation
NumberAnimation { target: bg; property: "opacity"; duration: 2000; to: 0 }
PropertyAction { target: splash; property: "visibility"; value: ApplicationWindow.Hidden }
}
}

I've come across some strange problems with repainting during further development of my program. For example, changing the size of the main form led to black form to. The solution I've found is to use OpenGL for rendering. You can do it by inserting this code:
QCoreApplication::setAttribute(Qt::AA_UseSoftwareOpenGL);

Denis Popov answer is correct, but in this mode my application was a bit laggy. Problem wasn't occuring if mode was set to:
QCoreApplication::setAttribute(Qt::AA_UseOpenGLES);
From the other hand this time I was getting following warning in the output everytime I was creating window:
DXGI WARNING: IDXGIFactory::CreateSwapChain: Blt-model swap effects (DXGI_SWAP_EFFECT_DISCARD and DXGI_SWAP_EFFECT_SEQUENTIAL) are legacy swap effects that are predominantly superceded by their flip-model counterparts (DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL and DXGI_SWAP_EFFECT_FLIP_DISCARD). Please consider updating your application to leverage flip-model swap effects to benefit from modern presentation enhancements. More information is available at http://aka.ms/dxgiflipmodel. [ MISCELLANEOUS WARNING #294: ]
Best solution I come up with so far is to run application in debug mode with one flag and in release/deployment with another:
#ifdef QT_DEBUG
QCoreApplication::setAttribute(Qt::AA_UseSoftwareOpenGL);
#else
QCoreApplication::setAttribute(Qt::AA_UseOpenGLES);
#endif

Related

QT 3D NodeInstantiator performance issue

I want to visualize x,y,z points as cubic blocks. I use C++ for backend and qtquick/javascript for frontend. I have implemented QAbstractListModel in C++ side and exposing to qml (qtquick) with QQmlApplicationEngine rootContext. Data include only x,y,z points and color codes. Data have arround 500 thousand coordinate points. I'm trying to visualize this data with NodeInstantiator dynamically. But it takes too much time to create objects, and ram usage increasing rapidly to 5-6 GB. If I solve the performance issue, I will try to add border lines to blocks. And I don't know how to do it aswell.
OS: Windows 10
Ram: 8 GB max
GPU: Nvidia 970 GTX
QT Creator 7.0.0
Kit: Desktop Qt 5.15.2 MinGW 64 Bit
import QtQuick 2.15
import QtQuick.Window 2.15 as W
import QtQuick.Scene3D 2.15
import Qt3D.Core 2.15
import Qt3D.Render 2.15
import Qt3D.Extras 2.15
import Qt3D.Input 2.15
import QtQuick.Controls 2.5
Page {
Rectangle {
id: rect1
x:0
y:0
width: 100
height: 100
color: "red"
}
Scene3D {
id: scene3dId
anchors.top: rect1.bottom
anchors.bottom: parent.bottom
anchors.right: parent.right
anchors.left: parent.left
//anchors.fill: parent
aspects: ["input", "logic"]
Entity {
id: scene
property color baseColor
property real metalness
property real roughness
property real exposure
property real gamma
components: [
RenderSettings {
activeFrameGraph: ForwardRenderer {
camera: mainCamera
clearColor: "white"
gamma: scene.gamma
}
},
// Event Source will be set by the Qt3DQuickWindow
InputSettings { }
]
Camera {
id: mainCamera
position: Qt.vector3d(0, 0, 12)
viewCenter: Qt.vector3d(0, 0, 0)
fieldOfView: 60
exposure: scene.exposure
}
OrbitCameraController {
camera: mainCamera
linearSpeed: 1000
lookSpeed: 240
}
CuboidMesh{
id: cubeMesh
xExtent: 1
yExtent: 1
zExtent: 1
}
NodeInstantiator {
id: grid
model: BM
delegate:
Entity {
Transform {
id: transformId
translation: Qt.vector3d(model.X, model.Y, model.Z)
}
PhongMaterial {
id: cubeMaterial
ambient: model.Color
}
components: [transformId, cubeMesh, cubeMaterial]
}
}
}
}
}
An example of what I want to do

QML: Asking confirmation before closing application

I have a QtQuick application. When the user tries to close the application, I want an "Are you sure?" window to pop up.
My main C++ class has this:
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
return app.exec();
}
And my main QML class has an application window:
ApplicationWindow {
id: root
...
}
Where and how would I catch the close event? I read about overriding closeEvent() from QMainWindow method or something, but I don't have a QMainWindow and I don't know where I'd put that code.
So I'd like to know how to prevent the app from closing and have something else happen instead, and how I'd close the app later when the user clicks "ok" in the confirmation dialog.
As far as I can see, the ApplicationWindow's "onClosing" only allows me to do some clean up before the inevitable close, but it doesn't prevent the close (please correct me if I'm wrong)
I solved it.
ApplicationWindow {
id: root
onClosing: close.accepted = false
}
This prevents the app from closing.
root.close()
This closes the app.
import QtQuick 2.13
import QtQuick.Layouts 1.12
import QtQuick.Controls 2.13
import QtQuick.Controls 1.4
import QtQuick.Dialogs 1.3
ApplicationWindow {
property bool closing: false
MessageDialog {
id: exitMessageDialogId
icon: StandardIcon.Question
text: "Are you sure to exit?"
standardButtons: StandardButton.Yes | StandardButton.No
onYes: {
closing = true
mainWindowId.close()
}
}
onClosing: {
close.accepted = closing
onTriggered: if(!closing) exitMessageDialogId.open()
}
id: mainWindowId
}
In this case it just close current window.
//use Qt 5.11.2
// for android y desktop
import QtQuick 2.9
import QtQuick.Controls 2.4
import QtQuick.Layouts 1.3
import QtQuick.Dialogs 1.2
ApplicationWindow {
title: qsTr("xxxx xxxx")
id: mainWindow
visible: true
//desision para salir
MessageDialog {
id: messageDialogQuit
title: "Deseas salir?"
icon: StandardIcon.Question
text: "xxxxxxxxxxxxxxxxxxxxxxxxx."
standardButtons: StandardButton.Yes |StandardButton.No
// Component.onCompleted: visible = true
onYes: Qt.quit()
// onNo: console.log("didn't copy")
}
onClosing:{
close.accepted = false
onTriggered: messageDialogQuit.open()
}
menuBar: MenuBar {
id: m_menu
LayoutMirroring.enabled: true
LayoutMirroring.childrenInherit: true
anchors.left: parent.left
Menu {
title: qsTr("File")
MenuItem {
text: qsTr("Exit")
onTriggered: messageDialogQuit.open()
}
}
}
width: 400
height: 300
}

Propagating onPositionChanged events to background items in QtQuick 1.1

Background.qml
import QtQuick 1.1
Item {
MouseArea {
id: backgroundMouseArea
anchors.fill: parent
hoverEnabled: true
onPositionChanged: {
console.log("Background")
}
}
}
Foreground.qml
import QtQuick 1.1
Item {
Background {
width: 1920
height: 1080
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
onPositionChanged: {
console.log("Foreground")
[mouse.accepted = false] - Not working (as the docs say)
[backgroundMouseArea.onPositionChanged(mouse)] - Not working
}
}
}
I need to execute onPositionChanged event on both background and foreground items.
F.ex. for onPressed I would do it by setting mouse.accepted = false in the foreground item.
Can I call onPositionChanged of the background item manually? If yes, how do I do it?
I am not completely sure what you are trying to achieve here.
A MouseArea is meant to grab mouse events from hardware. If you really want to propagate mouse events to background from a different MouseArea, maybe what you actually want to do is give Background a simple property mousePosition instead of the MouseArea, and then set that position from the Foreground onPositionChanged handler.
Also, your Foreground code relies on an internal id parameter inside of Background. This smells really bad. It is often more useful to think about the "Public API" of the Background and Foreground "classes". If what I described above is really what you want to do, this is what it should look like IMHO:
// Background.qml
import QtQuick 1.1
Rectangle {
// an object with just x and y properties
// or the complete mouseevent, whatever you want
// Use variant for QtQuick 1/Qt4, var for QtQuick 2.0 / Qt5
property variant mousePosition
onMousePositionChanged: console.log(
"Background " + mousePosition.x + " " + mousePosition.y
)
}
//Foreground.qml
import QtQuick 1.1
Item {
// use only ids defined in the same file
// else, someone might change it and not know you use it
Background { id: background }
MouseArea {
anchors.fill: parent
hoverEnabled: true
onPositionChanged: {
console.log("Foreground")
background.mousePosition = {x: mouse.x, y: mouse.y}
}
}
}
...........

How to do an action in Qml every time a user touches the screen?

I am writing an application for an embedded linux touchscreen device using Qt and Qml.
I need to implement a lock screen that appears after 30 seconds of inactivity.
To do this I've implemented a timer in C++, that changes the state of the program after timeout.
Is it possible to refresh this timer on a global scale every time the user touches the screen, so that I do not have to call the timers' start() slot in every touchable element in my program?
I would also like to refresh this timer even when the user touches a part of the screen where there are no buttons/interactive elements.
Something like this main.qml:
Rectangle {
id: mainRect
width: 800
height: 480
//something like this (oversimplified) pseudo code:
onGlobalUserTouch {
timers.startLockTimer()
}
//end pseudocode
Loader {
id: mainLoader
anchors.fill: parent
source: "FirstPage.qml"
Behavior on opacity {PropertyAnimation{duration:250}}
onLoaded: secondLoader.source = ""
}
states:[
State {
name:"SecondPage"
when: (mainCppClass.state == PanelStates.SECOND_PAGE)
PropertyChanges {
target: mainLoader
source: "SecondPage.qml"
}
}
]
}
All I was able to find on the web was how to implement this in either iOS or Android.
If mainRect is your root component, you can just start your timer in its MouseArea.
// touch area of your root component
MouseArea {
anchors.fill: parent
onClicked: {
timers.startLockTimer();
}
// child component
Rectangle {
color: "yellow"
x: 50; y : 50
width: 100; height: 100
}
}
This does not override descendant MouseAreas. Thus, if you touch area where there are no buttons/interactive elements, your startLockTimer will be called.

QML : Navigation between qml pages from design perception

We need to develop a QtQuick project, where we have about 100 screens.
I had tried to make a demo project for the navigation which has three screens on button click. I had used the concepts of 'States' in the navigation between the pages. Initially I tried the same using 'Loader' but loader was not able to retain the previous state of page, it was re-loading the entire page during the navigation.
Below is the code snippet of main.qml
// import QtQuick 1.0 // to target S60 5th Edition or Maemo 5
import QtQuick 1.1
Rectangle {
id:main_rectangle
width: 360
height: 640
Page1{
id:page1
}
Page2{
id:page2
}
Page3{
id:page3
}
states: [
State {
name: "page2"
PropertyChanges { target: page3; visible:false; }
PropertyChanges { target: page1; visible:false; }
PropertyChanges { target: page2; visible:true; }
},
State {
name: "page1"
PropertyChanges { target: page3; visible:false; }
PropertyChanges { target: page2; visible:false; }
PropertyChanges { target: page1; visible:true; }
},
State {
name: "page3"
PropertyChanges { target: page1; visible:false; }
PropertyChanges { target: page2; visible:false; }
PropertyChanges { target: page3; visible:true; }
}
]
}
This runs well with the small POC with three screens, but its not feasible to define states for 100 screens.
From designing aspect we concluded to make a C++ controller we controls the states, visibility of various pages.
Need suggestions how to implement the 'State' logic in C++.
Here is the simplest solution in plain QML, using a configurable page list (like a model) + a Repeater + Loader items to not load everything at startup (lazy instanciation) and not destroy a page after hiding it (to not have to reload it if we come back to it) :
import QtQuick 1.1
Rectangle {
id: main_rectangle;
width: 360;
height: 640;
// Put the name of the QML files containing your pages (without the '.qml')
property variant pagesList : [
"Page1",
"Page2",
"Page3",
"Page4",
"Page5"
];
// Set this property to another file name to change page
property string currentPage : "Page1";
Repeater {
model: pagesList;
delegate: Loader {
active: false;
asynchronous: true;
anchors.fill: parent;
visible: (currentPage === modelData);
source: "%1.qml".arg(modelData)
onVisibleChanged: { loadIfNotLoaded(); }
Component.onCompleted: { loadIfNotLoaded(); }
function loadIfNotLoaded () {
// to load the file at first show
if (visible && !active) {
active = true;
}
}
}
}
}
Hope it helps !
I suggest to use StackView from Qt Quick Components. Here is its documentation.