I have a very simple code for drag and drop in qml.
But when you are dragging the rectangle while holding mouse the screen of window is glitched! and sometimes the color of some Rectangle vanishes.
Like this bug is reported, but not answered.
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.14
import QtQml.Models 2.1
Window {
id: mainWindow
width: 700
height: 800
visible: true
color: 'grey'
Item {
anchors.fill: parent
GridView {
id: root
width: 320; height: 480
cellWidth: 80; cellHeight: 80
pixelAligned: true
displaced: Transition {
NumberAnimation { properties: "x,y"; easing.type: Easing.OutQuad }
}
model: DelegateModel {
id: visualModel
model: ListModel {
id: colorModel
ListElement { color: "blue" }
ListElement { color: "green" }
ListElement { color: "red" }
ListElement { color: "yellow" }
ListElement { color: "orange" }
ListElement { color: "purple" }
ListElement { color: "cyan" }
ListElement { color: "magenta" }
ListElement { color: "chartreuse" }
ListElement { color: "aquamarine" }
ListElement { color: "indigo" }
ListElement { color: "black" }
ListElement { color: "lightsteelblue" }
ListElement { color: "violet" }
ListElement { color: "grey" }
ListElement { color: "springgreen" }
ListElement { color: "salmon" }
ListElement { color: "blanchedalmond" }
ListElement { color: "forestgreen" }
ListElement { color: "pink" }
ListElement { color: "navy" }
ListElement { color: "goldenrod" }
ListElement { color: "crimson" }
ListElement { color: "teal" }
}
delegate: DropArea {
id: delegateRoot
width: 80; height: 80
onEntered: visualModel.items.move(drag.source.visualIndex, icon.visualIndex)
property int visualIndex: DelegateModel.itemsIndex
Binding { target: icon; property: "visualIndex"; value: visualIndex }
Rectangle {
id: icon
property int visualIndex: 0
width: 72; height: 72
anchors {
horizontalCenter: parent.horizontalCenter;
verticalCenter: parent.verticalCenter
}
radius: 3
color: model.color
Text {
anchors.centerIn: parent
color: "white"
text: parent.visualIndex
}
DragHandler {
id: dragHandler
}
Drag.active: dragHandler.active
Drag.source: icon
Drag.hotSpot.x: 36
Drag.hotSpot.y: 36
states: [
State {
when: icon.Drag.active
ParentChange {
target: icon
parent: root
}
AnchorChanges {
target: icon
anchors.horizontalCenter: undefined
anchors.verticalCenter: undefined
}
}
]
}
}
}
}}
}
Before:
After:
With add attribute of open-gl in main.cpp
QCoreApplication::setAttribute(Qt::AA_UseOpenGLES);
#SAt looks like you found the issue with your rendering engine. Sometimes there are quirks like that in your graphics card and may require updating your graphics driver. Otherwise, as you found, see the other rendering options with QCoreApplication::setAttribute() or by setting the QT_OPENGL environment variable:
Qt::AA_UseDesktopOpenGL Equivalent to setting QT_OPENGL to desktop.
Qt::AA_UseOpenGLES Equivalent to setting QT_OPENGL to angle.
Qt::AA_UseSoftwareOpenGL Equivalent to setting QT_OPENGL to software.
References:
https://doc.qt.io/qt-6/qcoreapplication.html#setAttribute
https://doc.qt.io/qt-6/qt.html#ApplicationAttribute-enum
https://doc.qt.io/qt-5/windows-requirements.html#graphics-drivers
I test your code in my system and it works well.
My OS is Ubuntu 20.04.
My Qt Version is 5.15.2 and 6.2.3 I checked in both.
This is the Result:
Related
I need to ensure that the ListView scrolls not only when hovering over it, but also in the area around it. As in the picture
I tried to do it like this, but scrolling with the mouse wheel still doesn't work
import QtQuick 2.0
import QtQuick.Controls 2.3
Rectangle {
height: 400
width: 300
color: "steelblue"
ScrollView {
anchors.fill: parent
wheelEnabled: true
ListView {
id: listView
anchors { fill: parent; margins: 40}
clip: true
model: appModel
delegate: Rectangle {
height: 50
width: listView.width
color: colorR
}
}
}
ListModel {
id: appModel
ListElement { colorR: "red"}
ListElement { colorR: "green"}
ListElement { colorR: "blue"}
ListElement { colorR: "cyan"}
ListElement { colorR: "yellow"}
ListElement { colorR: "blue"}
ListElement { colorR: "lightgray"}
ListElement { colorR: "red"}
ListElement { colorR: "green"}
ListElement { colorR: "blue"}
ListElement { colorR: "cyan"}
ListElement { colorR: "yellow"; }
ListElement { colorR: "lightgray"}
}
}
You can use WheelHandler outside the ListView
import QtQuick
import QtQuick.Controls
Rectangle {
height: 400
width: 300
color: "green"
function getRandomColor() {
var letters = '0123456789ABCDEF';
var color = '#';
for (var i = 0; i < 6; i++) {
color += letters[Math.floor(Math.random() * 16)];
}
return color;
}
WheelHandler {
onWheel: (event)=>{listView.flick(0, event.angleDelta.y*event.y)}
}
ListView {
id: listView
anchors { fill: parent; margins: 40}
model: 50
spacing: 10
delegate: Rectangle {
height: 50
width: listView.width
color: getRandomColor()
}
}
}
You can try this online.
This demo is from official demo of drag and drop.
I have changed a little. Now when other rectangle enterd the mousearea including the yellow rectangle, the yellow rectangle won't move. And yellow rectangle itself can't be draged too.
but when I drag cyan into the area between the green rec and the red one or other rectangle which is not in the area including the yellow rec, the yellow rectangle will move. It's not OK.
how can I fix that?
I already google, don't know which keyword to google.
import QtQuick 2.10
import QtQuick.Window 2.10
import QtQml.Models 2.1
import QtQuick.Controls 2.1
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
GridView {
id: root
width: 320; height: 480
cellWidth: 80; cellHeight: 80
displaced: Transition {
NumberAnimation { properties: "x,y"; easing.type: Easing.OutQuad
}
}
//! [0]
model: DelegateModel {
//! [0]
id: visualModel
model: ListModel {
id: colorModel
ListElement { color1: "blue" }
ListElement { color1: "green" }
ListElement { color1: "red" }
ListElement { color1: "yellow" }
ListElement { color1: "orange" }
ListElement { color1: "purple" }
ListElement { color1: "cyan" }
ListElement { color1: "magenta" }
ListElement { color1: "chartreuse" }
ListElement { color1: "aquamarine" }
ListElement { color1: "indigo" }
ListElement { color1: "black" }
ListElement { color1: "lightsteelblue" }
ListElement { color1: "violet" }
ListElement { color1: "grey" }
ListElement { color1: "springgreen" }
ListElement { color1: "salmon" }
ListElement { color1: "blanchedalmond" }
ListElement { color1: "forestgreen" }
ListElement { color1: "pink" }
ListElement { color1: "navy" }
ListElement { color1: "goldenrod" }
ListElement { color1: "crimson" }
ListElement { color1: "teal" }
}
//! [1]
delegate: MouseArea {
id: delegateRoot
//property int visualIndex: DelegateModel.itemsIndex
property int visualIndex: DelegateModel.itemsIndex
width: 80;
height: 80
drag.target: icon
Rectangle {
id: icon
width: 72; height: 72
anchors {
horizontalCenter: parent.horizontalCenter;
verticalCenter: parent.verticalCenter
}
color: model.color1
radius: width/2
Drag.active: delegateRoot.drag.active
Drag.source: delegateRoot
Drag.hotSpot.x: 36
Drag.hotSpot.y: 36
states: [
State {
when: icon.Drag.active
ParentChange {
target: icon
parent: delegateRoot //root
}
AnchorChanges {
target: icon;
anchors.horizontalCenter: {
if(color1 === "yellow"){
return parent.horizontalCenter;
}
else
undefined
}
anchors.verticalCenter: {
if(color1 === "yellow"){
return parent.verticalCenter
}
else
undefined
}
}
}
]
}
DropArea {
anchors { fill: parent; margins: 15 }
onEntered:{
console.log("enter " + color1)
if(color1 === "yellow")
return //console.log("enter " + iconname)
else
visualModel.items.move(drag.source.visualIndex, delegateRoot.visualIndex)
}
}
}
//! [1]
}
}
}
offical demo name is draganddrop. gridview.qml
EDIT
so this is kind of a hacky solution, but it is simple and it gets the job done.
What I basically did, is to iterate over the items after each movement and put yellow back in case it changed position.
DropArea {
anchors { fill: parent; margins: 15 }
onEntered:{
console.log("enter " + color1)
if(color1 === "yellow")
return //console.log("enter " + iconname)
else {
visualModel.items.move(drag.source.visualIndex, delegateRoot.visualIndex)
for (var i = 0; i< visualModel.items.count; i++)
{
if (visualModel.items.get(i).model.color1 === "yellow") {
visualModel.items.move(i, 3)
return;
}
}
}
}
}
I have more horizontal listview. For example let's take two of them. Items of each list are not the same length, when one list is scrolling - the other one does, too. I've solved that with contentX property. But, when I want to navigate between each other (when I press key "down" I need to force focus second listview). The problem is that focus is on horizontalna2.currentIndex that is remembered, and I want to go on first visible item in listview.
In android is that very simple, but to solve that here, huh..
Here is sketch of the code:
Rectangle {
width: 500
height: 200
ListModel {
id: model1
ListElement { itemwidth: 100 }
ListElement { itemwidth: 200 }
ListElement { itemwidth: 50 }
ListElement { itemwidth: 70 }
ListElement { itemwidth: 90 }
ListElement { itemwidth: 90 }
ListElement { itemwidth: 90 }
ListElement { itemwidth: 90 }
ListElement { itemwidth: 90 }
ListElement { itemwidth: 90 }
}
ListModel {
id: model2
ListElement { itemwidth: 300 }
ListElement { itemwidth: 50 }
ListElement { itemwidth: 70 }
ListElement { itemwidth: 100 }
ListElement { itemwidth: 90 }
ListElement { itemwidth: 30 }
ListElement { itemwidth: 90 }
ListElement { itemwidth: 90 }
ListElement { itemwidth: 90 }
ListElement { itemwidth: 90 }
}
ListView {
clip: true
id: horizontalna
boundsBehavior: Flickable.StopAtBounds
width: 500
height: 60;
focus: true
model: model1
orientation: ListView.Horizontal
KeyNavigation.down: horizontalna2
onContentXChanged: {
if (horizontalna.activeFocus === true)
{
horizontalna2.contentX = horizontalna.contentX
}
}
delegate: Item {
id: containerHorizontal
width: itemwidth; height: 60;
Rectangle {
id: contentHorizontal
anchors.centerIn: parent; width: containerHorizontal.width; height: containerHorizontal.height - 10
color: "transparent"
antialiasing: true
Rectangle { id: insideConHorizontal; anchors.fill: parent; anchors.margins: 3; color: "grey"; antialiasing: true; radius: 5
Text {
id: labelHorizontal
text: "name"
color: "white"
}
}
}
states: State {
name: "active"; when: containerHorizontal.activeFocus
PropertyChanges { target: contentHorizontal; color: "#FFFF00"; scale: 1}
PropertyChanges { target: insideConHorizontal; color: "#F98F06" }
PropertyChanges { target: labelHorizontal; color: "#0E2687"}
}
}
}
ListView {
id: horizontalna2
anchors.top: horizontalna.bottom
boundsBehavior: Flickable.StopAtBounds
width: 500
height: 60;
focus: true
model: model2
orientation: ListView.Horizontal
onContentXChanged: {
if (horizontalna2.activeFocus === true)
{
horizontalna.contentX = horizontalna2.contentX
}
}
delegate: Item {
id: containerHorizontal2
width: itemwidth; height: 60;
Rectangle {
id: contentHorizontal2
anchors.centerIn: parent; width: containerHorizontal2.width; height: containerHorizontal2.height - 10
color: "transparent"
antialiasing: true
Rectangle { id: insideConHorizontal2; anchors.fill: parent; anchors.margins: 3; color: "grey"; antialiasing: true; radius: 5
Text {
id:labelHorizontal2
color: "white"
text: "name"
}
}
}
states: State {
name: "active"; when: containerHorizontal2.activeFocus
PropertyChanges { target: contentHorizontal2; color: "#FFFF00"; scale: 1}
PropertyChanges { target: insideConHorizontal2; color: "#F98F06" }
PropertyChanges { target: labelHorizontal2; color: "#0E2687"}
}
}
}
}
EDIT[SOLVED] :
Get index of first visible item of second list depending on contentX --> function indexAt()
onCurrentIndexChanged: {
if (horizontalna.activeFocus === true)
{
horizontalna2.currentIndex = horizontalna2.indexAt((horizontalna2.contentX),0)
}
}
Get index of first visible item of second list depending on contentX --> function indexAt()
onCurrentIndexChanged: {
if (horizontalna.activeFocus === true)
{
horizontalna2.currentIndex = horizontalna2.indexAt((horizontalna2.contentX),0)
}
}
In my ui.qml I have:
RowLayout {
id: rowLayout2
x: 0
y: 397
width: 640
height: 50
clip: false
Text {
id: text4
width: 105
height: 32
text: qsTr("房间类型")
font.pixelSize: 17
wrapMode: Text.WordWrap
}
ComboBox {
id: comboBox1
activeFocusOnPress: false
model: ListModel {
id: cbItems
ListElement { text: "标准间"; color: "Yellow" }
ListElement { text: "三人间"; color: "Green" }
ListElement { text: "大床房"; color: "Brown" }
ListElement { text: "豪华套房"; color: "Blue" }
}
}
}
And I want to make a button that when clicked on duplicates this RowLayout below the original one, how do I do that?
Put it inside a Repeater and increment the model count when the button is clicked.
Button {
onClicked: {
repeater.model += 1;
}
}
...
Column {
Repeater {
model: 1
// Your rowLayout2 code
}
}
I'm using Qt5.2 anc C++ to implement an application and need to display a list with sections similar to the example image below:
(source: ngo-hung.com)
Please note I'm not implementing a mobile app and I don't need the alphabet index on the right. Any suggestions how I can achieve this other than implementing a QTreeView?
Thanks.
ListView in QML has built-in support for sections. In the following example, I have a ListModel where the section is defined via a "sec" role. The ListModel defines a section delegate as well as a contact delegate:
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
Page {
id: page
header: Frame {
background: Rectangle {
color: "red"
}
RowLayout {
width: parent.width
Item {
Layout.preferredWidth: 32
Layout.preferredHeight: 32
Button {
anchors.centerIn: parent
background: Item {}
icon.source: "https://raw.githubusercontent.com/Esri/calcite-ui-icons/master/icons/address-book-32.svg"
icon.width: 32
icon.height: 32
icon.color: "white"
}
}
Text {
Layout.fillWidth: true
text: qsTr("All Contacts")
color: "white"
}
}
}
anchors.fill: parent
ListView {
anchors.fill: parent
model: contacts
delegate: Frame {
width: ListView.view.width
RowLayout {
width: parent.width
Item {
Layout.preferredWidth: 32
Layout.preferredHeight: 32
Button {
anchors.centerIn: parent
background: Item {}
icon.source: "https://raw.githubusercontent.com/Esri/calcite-ui-icons/master/icons/user-32.svg"
icon.width: 32
icon.height: 32
icon.color: "green"
}
}
ColumnLayout {
Layout.fillWidth: true
Text {
Layout.fillWidth: true
text: fn
}
Text {
Layout.fillWidth: true
text: qsTr("Full name: %1 %2").arg(fn).arg(sn)
}
}
}
}
section.property: "sec"
section.delegate: Frame {
width: ListView.view.width
background: Rectangle {
color: "lightsteelblue"
}
Text {
text: section
color: "white"
}
}
}
ListModel {
id: contacts
ListElement {
sec: "B"; fn: "Branda"; sn: "Respass"
}
ListElement {
sec: "C"; fn: "Chana"; sn: "Hollin"
}
ListElement {
sec: "D"; fn: "Delisa"; sn: "Deak"
}
ListElement {
sec: "D"; fn: "Demetrius"; sn: "Zona"
}
ListElement {
sec: "D"; fn: "Dwain"; sn: "Mark"
}
}
}
You can Try it Online!