I have problem in binding item in QML, for example:
Rectangle{
id: thetarget
width:100
height:100
}
Item{
id: container
MouseArea{
id:mousearea
drag.target: thetarget //not work
anchors.fill: thetarget //not work
property int foo: thetarget.width //work
}
}
What I want is to make the bindings for drag.target, anchors.fill work without changing the structure (mousearea is not the sibling or child of thetarget). I have used Binding, function to return thetarget, but they are all useless. Could someone tell me what's wrong?
Set the parent of the mousearea to thetarget.
import QtQuick 1.1
Item {
Rectangle {
id: thetarget
width: 100
height: 100
}
Item {
id: container
MouseArea {
id: mousearea
parent: thetarget
drag.target: thetarget
anchors.fill: thetarget
property int foo: thetarget.width
}
}
}
Related
For my Custom window, shown in the answer, I've created a Component named PathButton
import QtQuick 2.0
import QtQuick.Shapes 1.12
Item {
property alias pathData: svg.path
width: 24
height: 24
Shape {
ShapePath {
fillColor: "black"
PathSvg {
id: svg
path: pathData
}
}
}
}
and used it to minimize, maximize and close the window like this:
RowLayout{
Layout.preferredWidth: 100
anchors.right: title.right
PathButton{
pathData: ViewModel.minimizeIcon
MouseArea{
anchors.fill: parent
onClicked: mainWindow.showMinimized()
}
}
PathButton{
pathData: ViewModel.maximizeIcon
MouseArea{
anchors.fill: parent
//this doesn't restore the window to its Normal state, showMaximized() is called always
onClicked: mainWindow.Maximized? mainWindow.showNormal() : mainWindow.showMaximized()
}
}
PathButton{
pathData: ViewModel.closeIcon
MouseArea{
anchors.fill: parent
onClicked: mainWindow.close()
}
}
}
in all those I've a MouseArea. What I want is to have that MouseArea in my Custom Component and declare a property of type eventhandler/signal/slot and assign that handler for onClicked like this:
import QtQuick 2.0
import QtQuick.Shapes 1.12
Item {
property alias pathData: svg.path
property alias handler: mouse.onClicked
width: 24
height: 24
Shape {
ShapePath {
fillColor: "black"
PathSvg {
id: svg
path: pathData
}
}
}
MouseArea{
id: mouse
anchors.fill: parent
onClicked: handler
}
}
and in its usage I want to assign the relevant function like this:
PathButton{
pathData: ViewModel.minimizeIcon
handler: mainWindow.showMinimized()
}
EDIT
Here's what I've in PathButton.qml:
import QtQuick 2.0
import QtQuick.Shapes 1.12
Item {
id: root
property alias pathData: svg.path
signal onClicked()
width: 24
height: 24
Shape {
ShapePath {
fillColor: "black"
PathSvg {
id: svg
path: pathData
}
}
}
MouseArea{
anchors.fill: parent
onClicked: root.onClicked()
}
}
and in main.qml I get that error and when I hit run with that error, in Application Output I get another error:
I think what you're looking for is simply a signal:
// PathButton.qml
Item {
id: root
signal clicked()
...
MouseArea {
onClicked: root.clicked()
}
}
Then you would use it like this:
PathButton {
onClicked: mainWindow.showMinimized()
}
This is the basic example I found on qt doc. In tile Rectangle, i add anchors.fill: parent and commented all 3 lines below that because I feel like all those 3 line can be covered by anchors.fill: parent. But once I do that I cannot drag the element anymore.
import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.3
ApplicationWindow {
visible: true
Item {
id: root
width: 64; height: 64
MouseArea {
id: mouseArea
anchors.fill: parent
anchors.centerIn: parent
drag.target: tile
onReleased: parent = tile.Drag.target !== null ? tile.Drag.target : root
Rectangle {
id: tile
anchors.fill: parent
// width: 64; height: 64
// anchors.verticalCenter: parent.verticalCenter
// anchors.horizontalCenter: parent.horizontalCenter
color: "red"
Drag.active: mouseArea.drag.active
Drag.hotSpot.x: 32
Drag.hotSpot.y: 32
states: State {
when: mouseArea.drag.active
ParentChange { target: tile; parent: root }
AnchorChanges { target: tile; anchors.verticalCenter: undefined; anchors.horizontalCenter: undefined }
}
}
}
}
}
Why filling the rectangle of the parent disables the drag and drop functionality?
You anchor a boat so that it is fixed at something. If you want to move it, you will need to break the anchor or pull the thing you anchored it to, with you.
That is what an anchor is for - to fix the anchored object to some other object. If you want to have it movable, you can't anchor it.
You still have the dragged object the same size as your parent, by setting:
width: parent.width
height: parent.height
But though it is the same size, once you move it, it will obviously not fill the parent anymore.
Now you might say:
"But hey! They do anchor the object, too!"
Yes, they do, but there are also the lines:
states: State {
when: mouseArea.drag.active
ParentChange { target: tile; parent: root }
AnchorChanges { target: tile; anchors.verticalCenter: undefined; anchors.horizontalCenter: undefined }
}
which will lift the anchor when the tile is being dragged.
The following code works and shows my items correctly, but I get the warning
qrc:/TableDelegate.qml:24: ReferenceError: name is not defined
I think it is because the ListView tries to access the model when it is empty and can not reference the item properties. I assume I am not doing to it correctly but I do not know how to do it better.
So my question is: how to get rid of the warning by doing it the right way?
TableDelegate.qml:
import QtQuick 2.0
import QtQuick.Layouts 1.1
Item {
property color bgcolor: 'transparent'
property alias box: rowBox
height: 40
width: parent.width
Rectangle {
id: rowBox
anchors.fill: parent
color: bgcolor
RowLayout {
anchors.fill: parent
Rectangle {
id: tableNameColumn
color: 'transparent'
Layout.fillHeight: true
Layout.fillWidth: true
Text {
anchors.centerIn: parent
color: textcolor
text: name // <--- here is `name`
}
}
// More Columns ...
}
}
MouseArea {
anchors.fill: parent
onClicked: {
view.currentIndex = index
}
}
}
And I use it like this
TableView.qml:
// ...
ListModel {
id: model
}
ListView {
id: view
model: model
anchors.fill: parent
highlight: delegate_highlighted
highlightFollowsCurrentItem: true
delegate: delegate
}
Component {
id: delegate
TableDelegate {
bgcolor: 'transparent';
}
}
Component {
id: delegate_highlighted
TableDelegate {
bgcolor: 'lightsteelblue'
box.border.color: 'black'
box.radius: 3
}
}
// ...
You use a TableDelegate for the highlight. That is wrong.
The ListView creates 1 instance of the highlight item, that will be drawn as a background for the currently selected item, It may also move between items as transition when the current item changes. It should only be a rectangle or whatever you want to use.
In your example, the highlight item is a full delegate, that wants to access model data, which it cannot.
I want to apply the QtGraphicalEffect ColorOverlay to an Image in a Repeater delegate. The problem is that I have to set the id of the Image as the source of the ColorOverlay, but I don't know the id, because it is dynamically created by the Repeater.
import QtQuick 2.4
import QtGraphicalEffects 1.0
Item {
id:mainItem
width: 800
height: 400
property string vorneColor: "red"
ListModel {
id: safeRailModel
ListElement {name: "vorne"; imageSource:"images/saferail/ring_vorne.png";}
ListElement {name: "vorneLinks"; imageSource:"images/saferail/ring_vorne_links.png"; }
}
Component {
id: imageDelegate
Image {
source: imageSource
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom
fillMode: Image.PreserveAspectFit
opacity: 1
visible: true
}
}
Repeater {
id: safeRailRepeater
model: safeRailModel
delegate: imageDelegate
}
Component {
id: effectsDelegate
Item{
id:effectsItem
ColorOverlay {
anchors.fill: safeRailRepeater.itemAt(index)// <-- This doesn't work
source: safeRailRepeater.itemAt(index)// <-- This doesn't work
color: vorneColor
}
}
}
Repeater {
id: safeRailEffectsRepeater
model: safeRailModel
delegate: effectsDelegate
}
}
How can I set source and anchors.fill properties?
I searched everywhere, but I've only found something along the lines of safeRailRepeater.itemAt(index) or safeRailRepeater.itemAt(index).item but neither the former nor the latter works.
Side note: the ColorOverlay doesn't need to be in a seperate delegate and Repeater.
It would be great if somebody has a solution for this problem or could point me in the right direction.
Thank you very much!
The problem is that the itemAt() function call returns null because the other Repeater hasn't loaded its items yet. Also, the function call won't ever be reevaluated, because none of its arguments ever change, so you'll always get null.
The design is a bit odd though; I'd suggest moving the ColorOverlay into the same delegate, as you mentioned that it doesn't have to be in a separate Repeater:
import QtQuick 2.0
import QtQuick.Window 2.0
import QtGraphicalEffects 1.0
Window {
id: mainItem
width: 800
height: 400
visible: true
property string vorneColor: "red"
ListModel {
id: safeRailModel
ListElement { name: "vorne"; vorneColor: "salmon"; }
ListElement { name: "vorneLinks"; vorneColor: "steelblue"; }
}
Component {
id: imageDelegateComponent
Rectangle {
id: delegate
color: "grey"
opacity: 1
visible: true
width: 64
height: 64
layer.enabled: true
layer.effect: ColorOverlay {
color: vorneColor
}
}
}
Row {
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom
Repeater {
id: safeRailRepeater
model: safeRailModel
delegate: imageDelegateComponent
}
}
}
Using the layer API of Item is a convenient way of specifying graphical effects.
I also changed the Image to a Rectangle, since we don't have access to those images, and put the Repeater within a row, so that you can see all of the delegates.
I have code like this:
GridView {
// ... declarations ...
model: theModel
delegate: MouseArea {
id: cellMouseArea
onClicked: // open the cell
}
MouseArea {
id: gridViewMouseArea
// here process horizontal mouse press/release actions
}
}
with a MouseArea defined in each delegate and an overall MouseArea covering my GridView. In the cellMouseArea I want to perform an open item action whereas in the gridViewMouseArea I want to implement mouseX handle to open/close a sidebar. However, the two MouseAreas do not work together. How can I carry it out?
You can exploit propagateComposedEvents:
If propagateComposedEvents is set to true, then composed events will
be automatically propagated to other MouseAreas in the same location
in the scene. Each event is propagated to the next enabled MouseArea
beneath it in the stacking order, propagating down this visual
hierarchy until a MouseArea accepts the event. Unlike pressed events,
composed events will not be automatically accepted if no handler is
present.
You can set the property to true on the GridView MouseArea. In this way click events are propagated to the MouseAreas in the delegates whereas the outer MouseArea can implement other behaviours such as drag or hoven.
Here is an example in which outer MouseArea defines drag property to slide in/out a Rectangle ( simulating your sidebar) and thanks to the propagateComposedEvents clicks are managed by the single delegates.
import QtQuick 2.4
import QtQuick.Window 2.2
ApplicationWindow {
width: 300; height: 400
color: "white"
Component {
id: appDelegate
Item {
width: 100; height: 100
Text {
anchors.centerIn: parent
text: index
}
MouseArea {
anchors.fill: parent
onClicked: {
parent.GridView.view.currentIndex = index
console.info("Index clicked: " + index)
}
}
}
}
Component {
id: appHighlight
Rectangle { width: 80; height: 80; color: "lightsteelblue" }
}
GridView {
anchors.fill: parent
cellWidth: 100; cellHeight: 100
highlight: appHighlight
focus: true
model: 12
delegate: appDelegate
MouseArea {
anchors.fill: parent
z:1
propagateComposedEvents: true // the key property!
drag.target: dragged
drag.axis: Drag.XAxis
drag.minimumX: - parent.width
drag.maximumX: parent.width / 2
onMouseXChanged: console.info(mouseX)
}
}
Rectangle{
id: dragged
width: parent.width
height: parent.height
color: "steelblue"
x: -parent.width
}
}