How to set objectName for PopupItem from QML? - qt

QML Popup and derived controls are creating a PopupItem object which is a visual representation of it, but Popup itself is parented to the contentData of the application window. objectName specified for Popup is not applied to PopupItem. For example, the following application:
import QtQuick 2.12
import QtQuick.Controls 2.12
ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("Popup Test")
Button {
text: "Open"
onClicked: dummyPopup.open()
}
Popup {
id: dummyPopup
objectName: "dummyPopup"
x: 100
y: 100
width: 200
height: 300
modal: true
focus: true
}
}
creates PopupItem with empty objectName
Is there a way to set objectName for PopupItem from QML?

Set the objectName of its contentItem upon completion:
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12
ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("Popup Test")
Button {
text: "Open"
onClicked: dummyPopup.open()
}
Popup {
id: dummyPopup
objectName: "dummyPopup"
x: 100
y: 100
width: 200
height: 300
modal: true
focus: true
Component.onCompleted: {
contentItem.objectName = "foo"
print(contentItem)
}
}
}
By the way, if this is for auto tests, I have a hack in C++ that avoids the need to give an objectName to the contentItem:
QObject *TestHelper::findPopupFromTypeName(const QString &typeName) const
{
QObject *popup = nullptr;
foreach (QQuickItem *child, overlay->childItems()) {
if (QString::fromLatin1(child->metaObject()->className()) == "QQuickPopupItem") {
if (QString::fromLatin1(child->parent()->metaObject()->className()).contains(typeName)) {
popup = child->parent();
break;
}
}
}
return popup;
}
You can then use that function like this in your test:
const QObject *newProjectPopup = findPopupFromTypeName("NewProjectPopup");
QVERIFY(newProjectPopup);
QTRY_VERIFY(newProjectPopup->property("opened").toBool());

Related

How can I change a text in a QML from another qml?

I would like to change myText.text from the main.qml but myText is in an another folder. How can I do that?
---main.qml---
import QtQuick 2.14
import QtQuick.Window 2.1
import QtQuick.Controls 2.12
import "qrc:/secondfolder/pagetwo.qml" as PageTwo
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Button {
id: button
x: 63
y: 71
width: 142
height: 66
text: qsTr("Button")
MouseArea{
anchors.fill: parent
onClicked: {
PageTwo.myText.text = "hello world"
}
}
}
}
---pagetwo.qml---
Item {
Text {
id: myText
text: "default text"
}
}
When I run the code I got this error: "qrc:/secondfolder/pagetwo.qml": no such directory
You need to declare your PageTwo in main.qml and give it id, like this:
PageTwo {
id: pageTwo
}
Instend of PageTwo.myText.text = "hello world" you need to write pageTwo.myText.text = "hello world".
Then in file PageTwo.qml you have to write property alias myText: myText.
main.qml
import QtQuick 2.14
import QtQuick.Window 2.12
import QtQuick.Controls 2.12
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
PageTwo {
id: pageTwo
}
Button {
id: button
width: 142
height: 66
text: qsTr("Button")
onClicked: {
pageTwo.myText.text = "hello world"
}
}
}
PageTwo
import QtQuick 2.14
Item {
property alias myText: myText
Text {
id: myText
text: "default text"
}
}
I'd recomend you to read this and check some qml example applications.

Why can't QML key events be intercepted?

I have the following code:
MyTest.qml
import QtQuick 2.0
FocusScope {
anchors.fill: parent
Keys.onReturnPressed: {
console.log("++++++++++")
}
}
main.qml
import QtQuick 2.9
import QtQuick.Window 2.2
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
MyTest {
focus: true
Keys.onReturnPressed: {
console.log("==========")
event.accepted = true
}
}
}
The output is:
++++++++++
==========
What is event.accepted = true invalid?
I want to intercept keystroke events in Window and process the event on ly in Window (only output "=========="). How to do that?
You can't disconnect a method when you use onReturnPressed: {} definition.
You have to use Connections for that.
A quick example:
import QtQuick 2.9
import QtQuick.Controls 1.4
Item {
id: myItem
anchors.fill: parent
property bool acceptEvents: true
signal returnPressed()
Keys.onReturnPressed: returnPressed()
Connections {
id: connection
target: myItem
enabled: acceptEvents
onReturnPressed: {
console.log("++++++++++")
}
}
}
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
VolumeSlider {
id: obj
anchors.fill: parent
focus: true
Keys.onReturnPressed: {
console.log("==========")
event.accepted = true
}
Component.onCompleted: {
obj.acceptEvents = false; // Remove connections
}
}
}

How dynamically creates Popup in QML

When I try to dynamically creates Popup with Qt.createQmlObject(...) or Qt.createComponent(...), I got exception:
QML Popup: cannot find any window to open popup in.
Here is my code:
var popup1 = Qt.createQmlObject('import QtQuick 2.8; import QtQuick.Controls 2.1; Popup { id: popup; x: 100; y: 100; width: 200; height: 300; modal: true; focus: true; closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent; visible: false }',
window,
"DynamicPopup");
popup1.open()
var popupComponent = Qt.createComponent("qrc:/TestPopup.qml")
var popup2 = popupComponent.createObject(window);
popup2.open()
TestPopup.qml:
import QtQuick.Window 2.2
import QtQuick.Controls 2.1
Popup {
x: 100
y: 100
width: 200
height: 300
modal: true
focus: true
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent
visible: false
}
Popup is not inheriting QQuickItem, and by default it is parented by QML Window, which is not instantiated if you are using QQuickWidget. Thus passing parent should be done as follows:
var popupComponent = Qt.createComponent("qrc:/TestPopup.qml")
var popup2 = popupComponent.createObject(window, {"parent" : window});
popup2.open()
The parent must be an element that inherits from QQuickItem
Example:
import QtQuick 2.6
import QtQuick.Window 2.2
import QtQuick.Controls 2.1
Window {
id: win
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Row{
Button{
id: item1
text: "btn1"
onClicked: {
var popup1 = Qt.createQmlObject('import QtQuick 2.8; import QtQuick.Controls 2.1; Popup { id: popup; x: 100; y: 100; width: 200; height: 300; modal: true; focus: true; closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent; visible: false }',
item1,
"DynamicPopup");
popup1.open()
}
}
Button{
id: item2
text: "btn2"
onClicked: {
var popupComponent = Qt.createComponent("qrc:/TestPopup.qml")
var popup2 = popupComponent.createObject(item2);
popup2.open()
}
}
}
}
method 1:
method 2:
A Popup needs to be be parented to an Item, window isn't one.
You should use window.contentItem instead.
A good approach to dynamically load a popup with a Loader:
Loader {
id: popupLoader
active: false
source: "qrc:/TestPopup.qml"
onLoaded: item.open()
}
function openMyPopup() {
if( popupLoader.active )
popupLoader.item.open()
else
popupLoader.active = true
}

QML reference errors

I have a small QML-project and I'm facing a problem with qml component references. So I'm trying to start the NumComponent.qml's numberTimer from startButton in the main.qml.
main.qml
import QtQuick 2.7
import QtQuick.Window 2.2
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
NumComponent{} //my component written in NumComponent.qml
Rectangle{
id: startButton
anchors.centerIn: parent
height: parent.height * 0.2
width: height
color: "lightblue"
MouseArea{
anchors.fill: parent
onClicked: {
numberTimer.start();
}
}
}
}
NumComponent.qml
import QtQuick 2.0
Rectangle {
id: numberRect
color: "red"
height: parent.height * 0.4
width: height
Text{
id: numberText
anchors.centerIn: parent
text: ""
}
Timer{
id: numberTimer
interval: 100
repeat: true
onTriggered: {
numberText.text = Math.floor(Math.random() * 8);
}
}
}
I get this error: "qrc:/main.qml:22: ReferenceError: numberRect is not defined"
Give your NumComponent in main.qml an id:
NumComponent{
id: numComponent
} //my component written in NumComponent.qml
change your onClicked handler to:
numComponent.startTimer();
Another variant:
Add to your numberRect a property alias:
property alias timed: numberTimer.running
Change you onClicked handler in main to:
numComponent.timed = !numComponent.timed;
Add to your NumComponent.qml in your root item:
function startTimer() {
numberTimer.start();
}
Now you can start and stop your timer.

QML2 ApplicationWindow Keys handling

Is there any way to handle key press events in ApplicationWindow of QtQuick.Controls component? Documentation of Qt5.3 does not provide any way to do this. Also, it says that Keys is only exists in Item-objects . When I try to handle key press event it says "Could not attach Keys property to: ApplicationWindow_QMLTYPE_16(0x31ab890) is not an Item":
import QtQuick 2.2
import QtQuick.Controls 1.2
import QtQuick.Controls.Styles 1.1
import QtQuick.Window 2.1
ApplicationWindow {
id: mainWindow
visible: true
width: 720
height: 405
flags: Qt.FramelessWindowHint
title: qsTr("test")
x: (Screen.width - width) / 2
y: (Screen.height - height) / 2
TextField {
id: textField
x: 0
y: 0
width: 277
height: 27
placeholderText: qsTr("test...")
}
Keys.onEscapePressed: {
mainWindow.close()
event.accepted = true;
}
}
ApplicationWindow {
id: mainWindow
Item {
focus: true
Keys.onEscapePressed: {
mainWindow.close()
event.accepted = true;
}
TextField {}
}
}
Maybe this will help some.
Using a Shortcut doesn't require focus to be set.
ApplicationWindow {
id: mainWindow
Shortcut {
sequence: "Esc"
onActivated: mainWindow.close()
}
}
}

Resources