QML: Cannot access signal - qt

I just started out with Qt. I've written a little QML-Button, and there's a problem which drives me crazy. I just can't get it to work.
// import QtQuick 1.0 // to target S60 5th Edition or Maemo 5
import QtQuick 1.1
Item {
id: bluebutton
property alias labeltext: label.text
signal pressed()
width: 130
height: 40
Rectangle {
id: rect
anchors.fill: parent
color: "darkblue"
Text {
id: label
scale: 2
color: "white"
anchors.centerIn: parent
}
MouseArea {
id: mousefield
anchors.fill: parent
onClicked: bluebutton.pressed() //.pressed() doesn't appear in the suggestions
}
}
}
So here's the problem:
apparently, i cant refer to any kind of signal defined in the Item-Element. I tried to refer to the property "labeltext" (bluebutton.labeltext) and it worked. But i can't refer to pressed() ! Why? Needless to say, the Button doesn't work...
Rectangle {
width: 250
height: 200
color: "lightblue"
Button {
labeltext: "Quit"
onPressed: Qt.quit
}
}
Does anybody know whats going on?
EDIT: Ok, signals do work... -.-
But Qt.quit doesn't work for some reason...

I finally found the solution:
I forgot braces...
wrong: Qt.quit
right: Qt.quit()
There you go. Conclusion: Always check if you forgot braces =D

Related

Top round transparent window

I'm currently learning QML and I want to create a top round transparent window.
I've build something that looks like that, but it seems wrong for multiple reason.
Here's my code:
Window {
id: app
visible: true
width: 70
height: 70
flags: Qt.Window | Qt.FramelessWindowHint | Qt.WA_TranslucentBackground
Rectangle {
anchors.fill: parent
radius: parent.width / 2.0
color: "black"
MouseArea {
property point clickPos: "1,1"
anchors.fill: parent
drag.target: parent
onPressed: {
clickPos = Qt.point(mouse.x,mouse.y)
}
onPositionChanged: {
var delta = Qt.point(mouse.x-clickPos.x, mouse.y-clickPos.y)
app.x += delta.x;
app.y += delta.y;
}
onDoubleClicked: app.close()
}
}
}
using these flags in the main :
QQuickWindow::setDefaultAlphaBuffer(true);
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
The main problem is that the background is not transparent.
I think it is because the 'round' rectangle is fully painted !?
I've tried multiple flags (Qt.Tool, Qt.Transparent, ...) but none works.
I was wondering if I started well to do what I want (I think I don't) and what is the best way to do it.
I've seen the clipping property for the qml item but I also see there's performance issues. I don't know if it's a good idea to use that property.
I'm running on Qt 5.10 and Win7 using MSVC as compiler.
Thank you
EDIT: Adding transparent background color to the window
Adding an answer, just so I can post an image to prove to you that all you need is to set the color:
Window {
id: app
visible: true
width: 70
height: 70
flags: Qt.Window | Qt.FramelessWindowHint
color: "#00000000"
Rectangle {
anchors.fill: parent
radius: parent.width / 2.0
color: ma.pressed ? "red" : "black"
MouseArea {
id: ma
property point clickPos: "1,1"
anchors.fill: parent
drag.target: parent
onPressed: {
clickPos = Qt.point(mouse.x,mouse.y)
}
onPositionChanged: {
var delta = Qt.point(mouse.x-clickPos.x, mouse.y-clickPos.y)
app.x += delta.x;
app.y += delta.y;
}
onDoubleClicked: app.close()
}
}
}
And the result:
I didn't use any of the flags you are setting from C++, maybe setDefaultAlphaBuffer() is breaking it for you.
I've figured it out.
Searching more deeply on the net and thx to #dtech, I found this article
It was the exact same problem as me. But without #dtech, I would never have thought about the graphic card problem, which led me to this solution.
It seems that you need to have the aero mode enable on windows in order to be able to use transparency on Qt.
I activated the aero mode and then retried the given solution (the one of #dtech), it works very nice.
EDIT: It's a well known "bug" on Qt
Now that I have the solution, it seems obvious but I didn't think about it before.
Thx everyone

QML Scroll View does not allow scrolling of its content

I need to create components dynamically add added to an area of the screen that, of course, needs to be scrollable. I found out that no matter how many of components I added with the scroll bar as its parent, the scroll bars would not appear and the element would not be scrollable.
I did a little fiddling and I think I came up with a minum working example of what I am talking about:
import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 2.2
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
ScrollView {
width: 200
height: 200
clip: true
Label {
text: "ABC"
font.pixelSize: 224
}
// Rectangle {
// color: "#ff0000"
// width: 100
// height: 100
// }
}
}
This is a modified version of the example used int he official documentation. However when I uncomment the square the screen is no longer scrollable (scroll bars never appear).
If I remove the label and leave the rectangle (making it larger so that there is something to scroll to) it still doesn't work.
I am using Qt 5.10.
So the code below worked for me. I defined a rectangle as a backgroud to get border lines to a scrollable table that I need to create.
Rectangle {
id: tableBackground
color: "#ffffff"
border.width: 2
border.color: "#EDEDEE"
radius: 4
anchors.top: tableHeader.bottom
anchors.left: tableHeader.left
width: vmTableWidth
height: vmTableHeight - tableHeader.height
ScrollView {
id: tableArea
anchors.fill: parent
clip: true
ListView {
id: patientListView
anchors.fill: parent
model: patientList
delegate: VMPatientEntry {
onFetchReport: {
// This is a signal emitted by my VMPatientEntry.
}
}
onCurrentIndexChanged: {
// Do stuff when the current index changes.
}
}
}
}
So I hope this answer allows someone to fix their problem as well.

QtQuick QML. Cannot assign properties to object loaded with Loader

I want to write an app in QtQuick that dynamically loads content. I decided to use Loader. Now I have a problem, which overwhelms me. I thought I would spend two minutes on that, but it took me two days and my problem is still unresolved.
I want to load an object from a .qml file, when the button is clicked. Clicking different buttons will set different properties to that object. The object is a simple rectangle with text within it. It has properties like width, height, text, color of rectangle and color of text. The problem is that loading the rectangle with different parameters DOESN'T change anything else than the color of the rectangle. I tried so many combinations of naming, property aliases etc, but it gave me nothing. Only color changes. Let me introduce you my code:
//StartStateContent.qml --> I wish to use Loaders in my Finite States Machine, hence the name
import QtQuick 2.0
import QtQuick.Controls 2.0
Rectangle {
id: startStateContent
property int myWidth
property int myHeight
property color myColor
property alias myText: name.text
property string myText2
property alias myTextColor: name.color
property color myTextColor2
// width: myWidth
// height: myHeight
color: kolor
Text {
anchors.centerIn: parent
id: name
text: "test"
//text: myText2
color: "yellow"
//color: myTextColor2
}
}
And a snippet of main.qml
Window {
visible: true
id: root
width: 500
height: 500
title: qsTr("Hello World")
Loader
{
id: pageLoader
anchors.top: root.top
anchors.left: root.left
width: root.width
height: root.height/2
}
Button{
id: but1
text: "red"
anchors.top: pageLoader.bottom
anchors.left: root.left
height: root.height/2
onClicked: {
pageLoader.setSource("StartStateContent.qml", {"myColor": "red"}, {"myTextColor" : "white"})
console.log("button red clicked")
}
}
Button{
id: but2
text: "green"
anchors.top: pageLoader.bottom
anchors.left: but1.right
height: root.height/2
width: root.width/2
onClicked: {
pageLoader.setSource("StartStateContent.qml", {"myColor": "green"}, {"myTextColor" : "green"})
console.log("button green clicked")
}
}
DSM.StateMachine{
id: stateMachine
initialState: startState
running:true
onStarted: {
pageLoader.setSource("StartStateContent.qml", {"myColor": "blue"}, {"myTextColor" : "orange"})
console.log("App started")
}
Here I try to set only color and text.color, but earlier I tried to change text rectangle size too. At first, I tried to just write {"height" : 100}. Then {"height" : "100"}, {"height" = 100}, etc. Then I added property myHeight (commented in first file), but with no luck. Then I did the same to text. Later I tried to create an alias property of text. I did that to every property (but cut that out of that example to spare space), without any success. Of course I changed also the anchors of loader. I tried to use anchors, to use explicitly set x,y, width, height; to use centering. Independently of attempts, the very thing that is being changed when I click buttons is color of the rectangle. Unfortunately, the only example of using Loader with properties in official Qt Documentation changes only the color property, so it doesn't help me.
My question is: how can I change properties (other than color) of a loaded object, using Loader.setProperty() method? Thank you in advance.
Btw, that is my first post here, so Hello Qt World:)
And sorry for possible lingual mistakes, as english isn't my native language.
I got the answer from official QtForum:
Instead of using
pageLoader.setSource("StartStateContent.qml", {"myColor": "red"}, {"myTextColor" : "white"})
one should use
pageLoader.setSource("StartStateContent.qml", {"myColor": "red", "myTextColor" : "white"})
because the setSource method expects an object. Works 100% that way!

New drag-and-drop mechanism does not work as expected in Qt-Quick (Qt 5.3)

I've tried to implement drag and drop in Qt 5.3 using the new QML types Drag, DragEvent and DropArea. This is the original example from the documentation of the QML Drag type with some small modifications:
import QtQuick 2.2
Item {
width: 800; height: 600
DropArea {
width: 100; height: 100; anchors.centerIn: parent
Rectangle {
anchors.fill: parent
color: parent.containsDrag ? "red" : "green"
}
onEntered: print("entered");
onExited: print("exited");
onDropped: print("dropped");
}
Rectangle {
x: 15; y: 15; width: 30; height: 30; color: "blue"
Drag.active: dragArea.drag.active
// Drag.dragType: Drag.Automatic
Drag.onDragStarted: print("drag started");
Drag.onDragFinished: print("drag finished");
MouseArea {
id: dragArea
anchors.fill: parent
drag.target: parent
}
}
}
Expected behaviour: The small blue rectangle (drag target) can be dragged around with the mouse. If dragged over the larger green rectangle in the center of the window, this rectangle turns red and back to green when leaving. In addition, the signals dragStarted, entered, exited, dropped and dragFinished are emitted in time and the corresponding signal handlers print out their messages.
Experienced behaviour:
Depends on Drag.dragType (see commented line above):
Drag.dragType is NOT set (default is Drag.Internal):
Drag and drop works as described, but only the signals entered and exited are emitted. The other signals (dragStarted, dragFinished and dropped) are suppressed. So there is no way to react to the drop in the DropArea.
Drag.dragType is set to Drag.Automatic:
All of the signals are emitted now, but the blue rectangle (drag target) does not move with the mouse. Instead, the mouse cursor changes its shape to visualize possible drop targets. After the mouse has been released, the blue rectangle jumps to the latest mouse position.
Neither of these two variants are pleasing. How can I get all signals and still be able to drag around the drag target? Unfortunately the documentation is everything but clear about drag-and-drop in QML, especially about the ominous Drag.dragType.
If you open the QQuickDrag source code and look at the differences between start(), which is used by Drag.Internal, and startDrag() which is used by Drag.Automatic, the difference is pretty obvious. start() sets up an event change listener, which it then uses to update the position of the attached object. startDrag() doesn't do this.
Why does it work this way? I have no idea! The QtQuick 2 drag and drop documentation certainly has room for improvement here.
There is a fairly simple workaround: take the best from both worlds. Use Drag.Automatic, but instead of setting Drag.active, call start() and drop() manually. It won't invoke Drag.onDragStarted() and Drag.onDragFinished() but you essentially get those for free anyway by listening for a change in the MouseArea's drag.active.
Here's the concept in action:
import QtQuick 2.0
Item {
width: 800; height: 600
DropArea {
width: 100; height: 100; anchors.centerIn: parent
Rectangle {
anchors.fill: parent
color: parent.containsDrag ? "red" : "green"
}
onEntered: print("entered");
onExited: print("exited");
onDropped: print("dropped");
}
Rectangle {
x: 15; y: 15; width: 30; height: 30; color: "blue"
// I've added this property for simplicity's sake.
property bool dragActive: dragArea.drag.active
// This can be used to get event info for drag starts and
// stops instead of onDragStarted/onDragFinished, since
// those will neer be called if we don't use Drag.active
onDragActiveChanged: {
if (dragActive) {
print("drag started")
Drag.start();
} else {
print("drag finished")
Drag.drop();
}
}
Drag.dragType: Drag.Automatic
// These are now handled above.
//Drag.onDragStarted: print("drag started");
//Drag.onDragFinished: print("drag finished");
MouseArea {
id: dragArea
anchors.fill: parent
drag.target: parent
}
}
}
I realize it's not a completely satisfying solution, but it does match your expected behavior.
This solution offers:
Notifications for all of the desired events: drag started, drag finished, enter drag area, exit drag area, and dropped in drag area.
The drag animation is automatically handled by QtQuick. The square doesn't freeze in place like it does when running the sample code with Drag.Automatic.
What it doesn't offer:
An explanation as to why QtQuick's drag and drop functionality works this way, or whether it's even the intended behavior by the developers. The current documentation seems ambiguous.
Just ran into this myself (using Qt 5.2, but the same problem exists there). I've got a 'slider box' on the X-axis and just wanted to know when the drag was finished... instead of responding to every position change along the way. My workaround involved hacking the states/transitions, with a ScriptAction to provide the logic. This is the simplified version for mimicking a response to the "onDragFinished" signal. So while it doesn't cover all your drag/drop signals, it might get you pointed in the right direction.
Rectangle {
id: sliderControl
height: coordinates.height
width: 80
color: "#F78181"
border.color: "#FE2E2E"
border.width: 1
opacity: 0.4
MouseArea {
id: mouseArea
anchors.fill: parent
drag.target: sliderControl
drag.axis: Drag.XAxis
drag.minimumX: 0
drag.maximumX: view.width - sliderControl.width
hoverEnabled: true
}
states: [
State {
name: "dragging"
when: mouseArea.drag.active
},
State {
name: "finished_dragging"
when: !mouseArea.drag.active
}
]
transitions: [
Transition {
from: "dragging"
to: "finished_dragging"
ScriptAction {
script: console.log("finished dragging script");
}
}
]
}
ps - I know that such a 'workaround' doesn't qualify for the bounty parameters, but I was pretty bummed to find only your question (no solutions) when I searched for help on the issue. Hopefully anyone else stumbling down this path will find this useful. Unfortunately, I've got no clue what's going on with QML's Drag.dragType either.

QML Keys.onEnterPressed issue

I have a QtQuick project for Desktop. It is very simple:
// import QtQuick 1.0 // to target S60 5th Edition or Maemo 5
import QtQuick 1.1
Rectangle {
width: 360
height: 360
Grid
{
id: xGrid
width: parent.width
height: parent.height
columns: 2
spacing: 1
Rectangle
{
height: parent.height
width: 10
color: "#ff0000"
Text {
id: xText
text: qsTr("t\na\ns")
}
}
TextEdit
{
id: xTextEdit
height: parent.height
width: 350
Keys.onEnterPressed: {
console.log(event.key)
xText.text = (qsTr("A"))
}
}
}
}
My code does not run like I want. The Keys.onEnterPressed seem never be captured, so I try Keys.onPressed it work but not sure why when I press Enter, the even.key returns 16777220.
Any one get this issue? How can I solve it?
Thanks for your answer!
I got the same problem with a TextInput item. I tried
onPressed
onEnterPressed
onReturnPressed
Only the latter one worked (onReturnPressed). I guess, the underlying implementation of the TextInput captures the 'Enter' key so it doesn't get processed by the onPressed signal in a regular way.
By the way: the key code is correct. It's an abstraction on the platform specific key codes.
A better way to handle users entering a text value is to use TextInput.onAccepted
Here's an example:
TextInput {
onAccepted: processText()
}
When the user presses Enter, the processText() method will be called.
This approach is simpler and should improve cross-platform portability.
TextArea {
id: messageField
Layout.fillWidth: true
placeholderText: qsTr("Message")
wrapMode: TextArea.Wrap
inputMethodHints: Qt.ImhNoPredictiveText
function _onEnterPressed(event)
{
if ((event.modifiers & Qt.ControlModifier))
{
sendMessage()
}
else
{
event.accepted = false;
}
}
Keys.onReturnPressed: { _onEnterPressed(event) }
Keys.onEnterPressed: { _onEnterPressed(event) }
}
I'd say use onReturnPressed as well. Otherwise you can also check the key value in onPressed() and react there. onReturn/EnterPressed are just convenience functions.
Potentially relevant context taken from the docs:
[...] the order of key event
processing is:
Items specified in forwardTo
specific key handlers, e.g. onReturnPressed
onPressed, onReleased handlers
Item specific key handling, e.g. TextInput key handling
parent item

Resources