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
Related
I'm using Qt Creator 4.6 on Linux. My problem can be reduced to the setup that is essentially the example provided in the documentation with some small changes:
https://doc.qt.io/qt-5/qml-qtquick-positioner.html
If I run the below code it draws some boxes, and clicking on each box should output its index. The code below works correctly for me as written. However, if I comment out TEXT 1 and uncomment TEXT 2, then clicking on the boxes outputs -1 for every box.
It seems like I have to use the Positioner in some way before the MouseArea or it won't work correctly (it can be used in the Text item or you can use it at the Rectangle level). I'm guessing it has something to with the MouseArea not being fully resolved until the actual click, and maybe if the compiler feels like nothing uses the Positioner it doesn't create it?
Is this behavior expected, and if so is it documented anywhere? In my real use case the workaround is to just use the Positioner to assign an index to an unused property or variable at the parent level so it's not too big a deal, but I'd like to understand it.
Window {
visible: true
width: 640
height: 480
Grid {
Repeater {
model: 16
Rectangle {
id: rect
width: 30; height: 30
border.width: 1
//color: Positioner.isFirstItem ? "yellow" : "lightsteelblue"
color: "green"
Text {
text: rect.Positioner.index //TEXT 1
//text: "test" //TEXT 2
}
MouseArea {
id: dragArea
anchors.fill: parent
onPressed: {console.log(rect.Positioner.index)}
}
}
}
}
}
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!
Hope this makes some sense as a question. In my app, I have a DragArea defined which I use to start dragging things over top of various Rectangles that each contain a DropArea. Everything is working fine in my code except for a cosmetic effect that I would like to change.
In QML, when you start dragging from a DragArea and eventually drop, the animation effect is such that the thing you're dragging animates (while fading out) back to the spot from which you started dragging. This happens even when you drop over a DropArea that successfully captures the drop.
What I would like to do is have the drop effect animate towards the DropArea that received the drop - so that it appears I am dragging-and-dropping things into the Rectangle. Is there any way to do this?
I'm guessing that this in some way involves the .source and .target properties of these areas, but no luck so far in having any effect on where the drop animation goes.
By default, QML will give you no cosmetic behavior for drag and drop whatsoever. The drag target will begin at the drag start location, and will end wherever it is dropped, regardless of whether the drag is accepted or not.
Thus I assume the behavior you describe is implemented in your user code, which you have not disclosed. Regardless, what you want to do is quite easy, it involves tracking the position the drag originates at and it ends at, so you can use the two coordinates to animate the position.
In the following example the red rectangle can be dragged, and if dropped outside of a drop area it will animate from its current to its initial position, whereas if dropped in the yellow rectangle, it will animate from its initial to its drop position.
Window {
width: 600
height: 600
visible: true
Rectangle {
width: 200
height: 200
color: "yellow"
DropArea {
anchors.fill: parent
onEntered: drag.source.accepted = true
onExited: drag.source.accepted = false
}
}
Rectangle {
id: rect
width: 50
height: 50
color: "red"
x: parent.width * 0.5
y: parent.height * 0.5
Drag.active: mouseArea.drag.active
property point begin
property point end
property bool accepted : false
MouseArea {
id: mouseArea
anchors.fill: parent
drag.target: parent
onPressed: rect.begin = Qt.point(rect.x, rect.y)
onReleased: {
rect.end = Qt.point(rect.x, rect.y)
aX.from = rect.accepted ? rect.begin.x : rect.end.x
aX.to = rect.accepted ? rect.end.x : rect.begin.x
aY.from = rect.accepted ? rect.begin.y : rect.end.y
aY.to = rect.accepted ? rect.end.y : rect.begin.y
anim.start()
}
ParallelAnimation {
id: anim
NumberAnimation { id: aX; target: rect; property: "x"; duration: 200 }
NumberAnimation { id: aY; target: rect; property: "y"; duration: 200 }
}
}
}
}
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
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.