I use MouseArea for buttons in my QT app and need to know, when the user moves his finger on the touch on a button. On W7 using a mouse, I get this information with onEntered from MouseArea.
The problem: on the target platform with touchscreen, the entered-signal is only fired, when I press the MouseArea (first touch inside MouseArea), then move my finger out (exited-signal), then move the finger back in (entered-signal). But when the first touch is outside the area and I enter it, entered-signal is not fired.
I also tried MultiPointTouchArea with onTouchUpdated and onUpdated, same behaviour.
I am using Qt 5.5.1 on embedded linux.
Is there something I can do to make the MouseArea always fire the entered-signal? Or should I use something other than MouseArea or MultiPointTouchArea?
As a workaround I could think of a MouseArea on the complete window, with information where all the buttons are and checking on each positionChanged, if a button was entered, but I'm sure there must be a better solution.
Edit: When using a mouse on target platform, the entered-signal is fired when moving the mouse into the area.
This is my (simplified) code:
main.cpp
#include <QApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QtQml>
#include "uart_terminal.h"
int main(int argc, char *argv[])
{
system("mount /dev/mmcblk0p1 /mnt/sdcard/");
setenv("QT_QPA_EGLFS_PHYSICAL_WIDTH", "376", 1);
setenv("QT_QPA_EGLFS_PHYSICAL_HEIGHT", "301", 1);
QApplication app(argc, argv);
qmlRegisterType<UART_terminal>("com.uart", 1, 0, "UARTTerminal");
QQmlApplicationEngine engine;
engine.rootContext()->setContextProperty("applicationDirPath", QGuiApplication::applicationDirPath());
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
return app.exec();
}
main.qml:
Window
{
id: rootWindow
visible: true
width: 1280
height: 1024
Rectangle
{
id: test
color: "red"
width: 300
height: 300
MouseArea
{
anchors.fill: parent
hoverEnabled: true
acceptedButtons: Qt.AllButtons
onEntered:
{
console.log("entered")
test.color = "blue"
}
onExited: test.color = "red"
onCanceled: console.log("canceled")
onPositionChanged:
{
console.log("pos changed, containsMouse", containsMouse)
}
}
/*MultiPointTouchArea
{
anchors.fill: parent
onTouchUpdated: console.log("touch updated")
onUpdated: console.log("touchlist updated")
}*/
}
}
So as I didn't find any other solution, I had to implement the mentioned work around. I put a MouseArea "buttonContainer" on the whole screen, behind all other MouseAreas. Note that I have to propagate the positionChanged signal from each MouseArea, otherwise it won't create my button-entered signal when I started the touch in one button and then enter another one.
onPositionChanged:
{
// propagate event to buttonContainer with absolute mouse position
var position = roundMouseArea.mapToItem(root)
buttonContainer.xOffsetMouse = position.x
buttonContainer.yOffsetMouse = position.y
buttonContainer.positionChanged(mouse)
}
Then in buttonContainer's onPositionChanged I have to check for all Buttons that are currenty visible if they were entered. Don't forget to map each buttons position again with btn.mapToItem(buttonContainer) and to reset x- and yOffsetMouse in buttonContainer's onPressed.
In my case I had to do much more stuff like
check if button is disabled anyways, although visible
remember enteredBtn
set bool for each button if it's already entered from my container, so I don't get entered-signal at each positionChanged while I stay in that button
also check for button exited
set btnPressed true or false accordingly, eg. also at buttonContainer's onReleased
reset enteredBtn to undefined accordingly and check for that, before referencing any method or property of enteredBtn (eg. at buttonContainer's onReleased)
I think that was all. Don't want to copy my whole code here, just mention some aspects you might also need to consider if you have the same issue.
Related
WebEngineView should be displayed in the whole window, but it's not. Right margin strip and bottom margin strip is not displayed. Instead a strip of (red) background is visible. Yet I can click on red background on the input search formular and it can be filled. There shouldnt be any background visible.
I also tried QWebEngineView instead of QQmlApplicationEngine and it is exactly the same.
This code is run by Qt 6.4.0.
In Qt 5.12.5 it is displayed correctly.
What to do to show WebEngineView in the whole window ?
main.cpp:
int main(int argc, char *argv[])
{
QtWebEngineQuick::initialize();
QApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/webengine.qml")));
return app.exec();
}
webengine.qml:
import QtQuick
import QtQuick.Window
import QtWebEngine
Window {
width: 800
height: 600
visible: true
color: "red"
WebEngineView {
id: webEngineView
anchors.fill: parent
url: "https://doc.qt.io/qt-6/qtwebengine-webenginequick-minimal-example.html"
}
}
The gui:
This should already be fixed in 6.4.0, was this observed during the beta, if so, then try with the final release. If observed with the final, please open a bug report for at Qt.
In a Qt Quick application, I want to animate the main window height when I click on a toggle button, in order to show or hide a kind of tray panel. The main form content contains a header frame, a swipe view and a grid view below it.
To reach the desired effect, I added the following animations in my qss code, which are run depending of my toggle button state:
ParallelAnimation
{
id: one_dev_connected_toggle_window_height_increase
running: false
NumberAnimation { target: mainWindow; property: "height"; to: 750; easing.type: Easing.InOutQuad; duration: 500}
}
ParallelAnimation
{
id: one_dev_connected_toggle_window_height_decrease
running: false
NumberAnimation { target: mainWindow; property: "height"; to: 450; easing.type: Easing.InOutQuad; duration: 500}
}
When I try to open the tray, the animation cause a huge flickering on my whole interface. However, when I close the tray, the animation cause no flickering at all, and the effect is smooth, as I expected.
My main window is declared as follow:
ApplicationWindow
{
id: mainWindow
visible: true
width: 700
height: 750
color: "#000000"
title: qsTr("Drag&Drop App")
flags: Qt.Window | Qt.FramelessWindowHint
....
Can someone explain me why I'm facing a such flickering? What should I change to fix it?
First I tried to reproduce your behavior with a small app, which is listed below:
main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
int main(int argc, char* argv[])
{
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
QQmlContext* context = engine.rootContext();
// Adding the following line helps to remove the flickering
app.setAttribute(Qt::ApplicationAttribute::AA_ShareOpenGLContexts, true);
engine.load(QUrl("./data/main.qml"));
return app.exec();
}
main.qml
import QtQuick 2.13
import QtQuick.Controls 2.5
ApplicationWindow {
id: mainWindow
width: 800; height: 1000
title: "Animation Flickers"
visible: true
property bool large:true
MouseArea {
anchors.fill: parent
onClicked: {
if (mainWindow.large) {
decr.start()
} else {
incr.start();
}
mainWindow.large=!mainWindow.large;
}
}
ParallelAnimation
{
id: incr
running: false
NumberAnimation { target: mainWindow; property: "height"; to: 750; easing.type: Easing.InOutQuad; duration: 500}
}
ParallelAnimation
{
id: decr
running: false
NumberAnimation { target: mainWindow; property: "height"; to: 450; easing.type: Easing.InOutQuad; duration: 500}
}
}
Then I activated the application attribute AA_ShareOpenGLContexts and the flickering vanished. There might be many reasons for flickering and this might just remove one reason. I already experienced flickering by a non fitting graphics card driver. You should also consider to run your program on a different machine.
Please report back, if my solution didn't solved your problem.
Playing with the parameters, I finally found an acceptable solution.
Here's what I noticed:
Following the Aleph0's reply, I played around the OpenGL flags. I noticed that using the Qt::ApplicationAttribute::AA_UseOpenGLES flag resolved completely the flickering, however it caused a strange side effect in my case: the height of all components contained in my window became inconsistent while the main form height changed, causing a kind of wobbling during the animation, even with the correct anchoring and min and max height constraints defined.
On my main interface I removed the anchoring and used layouts instead. This resolved the strange wobbling during the height change, and almost all the flicker issues. I tested on different computers with different OS, the flickering appear only rarely in several particular cases.
However the wobbling still appears while the layouts are used if OpenGLES is used.
So replacing anchors by layouts was the solution in my case, even if it works not perfectly. But at least the result is acceptable.
So for my current project I need to use a transparent window.
On the creation of the window no problem it works is when you move the window that there is a problem.
The transparency does not apply because it considers that the window is part of the background and reproduces it in the new rendering.
I do not know if I'm very clear I put a picture in link it's more speaking sorry for the quality I had to take it with the laptop because when we capture it "refresh" the display and transparency becomes normal again.
Another surprising thing is that the transparency does not bug if what is behind is chrome ...
So basically the question is how to have a "normal" behavior?
Here I hope that you can help me I see no solution there.
At the code level:
main.cpp :
#include <QQuickView>
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QQuickView * view = new QQuickView;
view->setTitle("Test");
view->setSource(QUrl::fromLocalFile ("main.qml"));
view->setColor(Qt::transparent);
view->show();
return a.exec();
}
main.qml :
import QtQuick 2.0
Rectangle {
width: 400
height: 400
color : "#00000000"
Rectangle {
anchors.centerIn: parent
color: "red"
width: 100
height: 100
}
}
Result
I have ImageButton.qml which should change image when user holds the button.
import QtQuick 2.0
Image {
id: svg
property string idleImage
property string hoverImage
signal clicked
state: "idle"
source: state === "idle" ? idleImage : hoverImage
onSourceChanged: {
console.log("source = " + source)
}
MouseArea {
id: mouseArea
anchors.fill: parent
acceptedButtons: Qt.LeftButton
onPressedChanged: {
svg.state = pressed ? "hover" : "idle"
}
onClicked: svg.clicked()
}
}
But the image is not changed immediately. It's changed only when I hold the button for several seconds. When I press and release mouse button immediately I never see the hover image. onSourceChanged is executed immediately and outputs to console the right image source. This strange bug happens only when I use QQuickWidget. When I don't use widgets, but qml only everything works as expected.
I found the issue. I am using QOpenGLWidget in the MainWindow. And I called update method in paintGL.
void Workspace::paintGL() {
QOpenGLWidget::paintGL();
workspaceDrawer.draw();
update();
}
I replaced update call with a timer, running every 1000 / 60 milliseconds.
And the issue was gone. It's strange that it was reproduced only when a mouse button was pressed, otherwise everything was updated correctly.
I want to create a QML item which disappears when the mouse moves outside of it. Here is my code:
Item {
id: disappearing_element
ListView { ... }
MouseArea {
id: collapser
anchors.fill: parent
propagateComposedEvents: true
hoverEnabled: true
onExited: {
disappearing_element.visible = false
}
}
}
It works well, but MouseArea propagates events like onClicked() onDoubleClicked() only (as said in Qt docs).
Is there a way to notify disappearing_element's childrens about mouse enter and mouse exit events (without using a Popup element)?
I think this is one of the common needs when developing QtQuick apps. One solution we currently use quite often is to add MouseArea in each of the children that need check mouse containment, and emit signals (and catch these signals in your main item) when the mouse enters or exits.
Things go a bit complicated when the children items also need such mechanism to manage their children. However, for common usage, this approach is enough for us right now.