I have two questions which are somehow related.
I have created a route on an open street map and I want to extract a list of points that correspond to the way points of the generated route (not just the start and the finish). How can this be achieved? For example I want to extract way points for the generated red route from the image bellow (of course I do not want to extract all the points from a route but from 10 in 10 meters).
How do I erase the generated route with red, and have the original map (without the red route)
I have tried many function on the map item but non of them worked. For example I have tried the code below but the red route remains.
function clearMapDataForSession()
{
mapview.clearData();
routeModel.update()
}
You can get a list of coordinates from the Route by using the properties path or segments. The path property directly gives you a list of coordinates on the given Route, the segments property on the other hand gives you a list of RouteSegments which in turn contain a list of coordinates given by its path property.
Print the list of Route coordinates via segments:
var segments = routeModel.get(0).segments
for (var i = 0; i < segments.length; i++) {
var path = segments[i].path
for (var j = 0; j < path.length; j++)
console.log(path[j])
}
Print the list of Route coordinates via path:
var path = routeModel.get(0).path
for (var i = 0; i < path.length; i++) {
console.log(path[i])
}
If you compare the list of coordinates given by the two options, they are the same. The benefit of RouteSegments is that you get the distance of the segment as a property. So if you want to generate a list of coordinates/points on the Route at the same distance, this would help you in writing some sort of an algorithm.
In order to erase a generated Route you need to call reset() on the RouteModel. If you want to also clear the waypoints of a RouteQuery you should call clearWaypoints() as well.
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import QtLocation 5.15
import QtPositioning 5.15
ApplicationWindow {
id: window
width: 800
height: 600
visible: true
title: qsTr("Map")
header: ToolBar {
RowLayout {
anchors.fill: parent
ToolButton {
text: qsTr("Reset")
onClicked: {
routeQuery.clearWaypoints()
routeModel.reset()
}
}
}
}
Plugin {
id: mapPlugin
name: "osm"
}
RouteQuery {
id: routeQuery
}
RouteModel {
id: routeModel
plugin: mapPlugin
query: routeQuery
autoUpdate: false
}
Map {
id: map
anchors.fill: parent
plugin: mapPlugin
center: QtPositioning.coordinate(59.91, 10.75) // Oslo
zoomLevel: 14
MapItemView {
model: routeModel
delegate: MapRoute {
route: routeData
line.color: "blue"
line.width: 5
smooth: true
opacity: 0.8
}
}
MapItemView {
model: routeModel.status == RouteModel.Ready ? routeModel.get(0).path : null
delegate: MapQuickItem {
anchorPoint.x: pathMarker.width / 2
anchorPoint.y: pathMarker.height / 2
coordinate: modelData
sourceItem: Rectangle {
id: pathMarker
width: 8
height: 8
radius: 8
border.width: 1
border.color: "black"
color: "yellow"
}
}
}
MapItemView {
model: routeQuery.waypoints
delegate: MapQuickItem {
anchorPoint.x: waypointMarker.width / 2
anchorPoint.y: waypointMarker.height / 2
coordinate: modelData
sourceItem: Rectangle {
id: waypointMarker
width: 10
height: 10
radius: 10
border.width: 1
border.color: "black"
color: "red"
}
}
}
MouseArea {
anchors.fill: parent
onClicked: {
routeQuery.addWaypoint(map.toCoordinate(Qt.point(mouse.x,mouse.y)))
routeModel.update()
}
}
}
}
Related
I'm trying to find a means of creating dynamic chartviews using QML. The general idea is for a user to click an element on a ComboBox and click a button to either add a chartview to the screen or remove it.
Currently I'm able to display my charts statically in a RowLayout like so:
import QtQuick 2.15
import QtCharts 2.15
import QtQuick.Layouts 1.15
import QtQuick.Controls 2.12
Item{ property int firstModel : 1
property int secondModel : 2
property int maxVal : 8
property int minVal: -8
RowLayout {
anchors.fill: parent
spacing: 10
ChartView{
id: firstModelChartView
animationOptions: ChartView.NoAnimation
theme: ChartView.ChartThemeLight
antialiasing: true
Layout.fillHeight: true
Layout.fillWidth: true
DateTimeAxis{
id:axisXValues
min:new Date(SensorManager.audioStream[firstModel].xMin)
max:new Date(SensorManager.audioStream[firstModel].xMax)
format: "hh:mm:ss:zzz"
}
ValueAxis {
id: axisYValues
min: gLinkMin
max: gLinkMax
}
LineSeries {
id: innerChamberLineSeries
useOpenGL: true
name: "Inner Chamber"
axisX: axisXValues
axisY: axisYValues
}
VXYModelMapper {
id: innerChamberLineSeriesModelMapper
model: SensorManager.audioStream[firstModel]
series: innerChamberLineSeries
firstRow: 1
xColumn: 0
yColumn: 1
}
}
/// SEcond Model ...... Etc You get the gist
}
}
The model is a QAbstractModel Type from C++ and I'm able to display this in realtime. My problem is I've got 20 of these data streams and I don't want to show them all at once. so I want to give the user the ability to be able to add or remove multiple of these chartviews from the screen.
I'm trying to use a GridView and basically adapt this snippet from this post but I'm not really getting far with it.
My Idea is to initially create a chartview and then attach a lineseries to that chartview, here's what I've got so far but I'm stumped on how to attach a specific lineseries model to a chartview and how you remove a specific chartview from the Gridview.
import QtQuick 2.15
import QtCharts 2.15
import QtQuick.Layouts 1.15
import QtQuick.Controls 2.12
Item{ property int firstModel : 1
property int secondModel : 2
property int maxVal : 8
property int minVal: -8
ListModel{
id: chartsModel
Component.onCompleted: {
chartsModel.append({"name": qsTr("Inner Vinration Chamber"), value: firstModel })
chartsModel.append({"name": qsTr("Extruder Vibration Y"), value: secondModel })
///////
}
}
ListModel{
id:chartViewModel
}
Row {
id: chartControlsRow
anchors.fill: parent
anchors{
leftMargin: 10
topMargin: 10
}
spacing:0
CustomComboBox {
id: chartSelector
model: chartsModel
textRole: "name"
onCurrentIndexChanged: {
var model = SensorManager.audioStream[chartsModel.get(currentIndex).value]
}
}
CustomButton
{
id: addChartButton
text: "Add Chart"
onClicked: {
modelId.append({'mColor': 'blue'})
var chartViewModel = Qt.createQmlObject('import QtQuick 2.14; ListModel { }',
Qt.application, 'dynamicChartViewModel');
}
}
CustomButton
{
id:removeChartButton
text: "Remove Chart"
onClicked: {
console.log(chartSelector.currentIndex)
chartViewModel.remove(chartSelector.currentIndex);
}
}
}
Rectangle{
anchors.fill: parent
anchors.topMargin: 55
color: "black"
GridView {
id: mGridViewId
anchors.fill: parent
cellWidth: 400; cellHeight: 400
model: chartViewModel
delegate: Rectangle {
width: mGridViewId.cellWidth;
height: mGridViewId.cellHeight
color: mColor
ChartView {
id: mChartView
width: parent.width;
height: parent.height
DateTimeAxis{
id:axisXValues
format: "hh:mm:ss:zzz"
}
ValuesAxis{
id:axisYValues
min:gLinkMin
max:gLinkMax
}
LineSeries {
name: "Lineseries"
id: mLineSeries
useOpenGL: true
axisX: axisXValues
axisY: axisYValues
}
VXYModelMapper{
id: modelMapper
series: mLineSeries
firstRow: 1
xColumn: 0
yColumn: 1
}
}
}
function getDelegateInstanceAt(index) {
return contentItem.children[index];
}
}
}
}
How do I Achieve this? Any tips or pointers would be helpful
I have a ListView which has dynamically added Items, and what I kinda want to know is how I could access items for example by index. Specifically, I want to have the color of the item rectangle change when I change the color using the Color Dialog. I guessed it should be maybe possible to first set a variable to the current item before calling the color dialog and then in the onAccepted method change the color of that item using the variable, but I don't know how to achieve anything of this in QML, because I am rather new to QML. Maybe you can offer even a cleaner way to change the color of the item's rectangle when the color dialog was closed (onAccepted). Thx for any help! :)
import QtQuick 2.0
import QtQuick.Window 2.2
import QtQuick.Controls 1.4
import QtQuick.Dialogs 1.2
import QtQuick.Controls.Styles 1.4
Rectangle {
id: listViewContainer
width: parent.width/10*9;
height: 50
Behavior on height {
NumberAnimation {
duration: 100;
}
}
gradient: Gradient {
GradientStop {position: 0.0; color: "white" }
GradientStop {position: 1.0; color: "silver" }
}
radius: 5
ColorDialog {
id: colorDialog
title: "Please choose a color"
onAccepted: {
console.log("You chose: " + colorDialog.color)
Qt.quit()
}
onRejected: {
console.log("Canceled")
Qt.quit()
}
}
Component {
id: playerDelegate
Item {
anchors.left: parent.left
anchors.right: parent.right
height: 50
Column {
Text { text: '<b>Name:</b> ' + name }
Row {
MouseArea {
width: 20
height: 20
onClicked: {
colorDialog.visible = true;
playerColor = colorDialog.color;
//open color dialog
}
Rectangle {
radius: 3
anchors.fill: parent
color: playerColor
}
}
}
}
}
}
ListView {
id: playerListView
anchors.fill: parent
model:
ListModel {
id: playerListViewModel;
ListElement {
name: "Bill Smith"
playerColor: "red"
}
}
delegate: playerDelegate
}
Button {
id: addPlayerButton
anchors.top: playerListView.bottom
anchors.left: playerListView.left
anchors.right: playerListView.right
style: ButtonStyle {
label: Text {
text: "Add new player"
horizontalAlignment: Text.Center
}
}
onClicked: {
root.addnewPlayer(playerListView); //dont worry about this method
playerListViewModel.append({name: "Billy", playerColor: "blue"});
listViewContainer.height += 50;
}
}
}
Here is a sure fire way to make a working colorDialog --
in playerDelegate
Component {
id: playerDelegate
Item {
anchors.left: parent.left
anchors.right: parent.right
height: 50
Column {
Text {
text: '<b>Name:</b> ' + name
}
/* Object to store value from color selector */
Item {
id: colorSelector
property color color: "#000000"
onColorChanged: { playerColor = color; }
}
/* box to display color */
Rectangle {
//Layout.fillWidth: true
height: 120
width: 120
anchors.left: button.right
//Layout.alignment: Qt.AlignHCenter
color: colorSelector.color
border.width: 1
border.color: "#000000"
}
/* button to open dialog -- can be mousearea or other clickable object */
Button {
id: button
text: "Browse..."
onClicked: {
colorDialog.color = colorSelector.color
colorDialog.open()
}
}
/* actual color dialog for this delegate */
ColorDialog {
id: colorDialog
modality: Qt.ApplicationModal
title: "Please choose a color"
onAccepted: colorSelector.color = currentColor
}
}
}
}
I want to do something very similar to this image in Qt where I can click in any square and change the color of it.
It's pretty simple to do this with QML. Look at the code below:
import QtQuick 2.1
import QtQuick.Window 2.0
Window {
id: root
visible: true
width: 360
height: 500
Column{
Repeater{
model: getRowsNumber(root.height)
delegate: Row{
property int externalIdx: index
Repeater{
model: getColumnsNumber(root.width)
delegate: Rectangle{
property bool selected: false
property color originalColor: (index + externalIdx) % 2 == 0 ? "black" : "white"
width:20
height: 20
color: selected ? "red" : originalColor
border.width: 1
border.color: "black"
MouseArea{
anchors.fill: parent
onClicked: parent.selected = !parent.selected
}
}
}
}
}
}
function getColumnsNumber(width){
return width/20;
}
function getRowsNumber(height){
return height/20;
}
}
That's all you need to have a rectangular chess-like grid where each cell changes its color when it is clicked on. Of course, you will need to adapt it to your needs but that should be enough for you to start.
I`m try to get control under cursor. At my example i can get only red rectangle, but i need get other also.
import QtQuick 2.4
import QtQuick.Controls 1.3
import QtQuick.Window 2.2
import QtQuick.Dialogs 1.2
ApplicationWindow {
id: mainWindow
title: qsTr("Hello World")
width: 640
height: 480
Item {
id: parentPanel
anchors.fill: parent
MouseArea {
anchors.fill: parent
hoverEnabled: true
onMouseXChanged: moveMouse()
onMouseYChanged: moveMouse()
function moveMouse()
{
currentControl.text = parentPanel.childAt(mouseX, mouseY).color ? parentPanel.childAt(mouseX, mouseY).color : "not colored"
}
}
Rectangle {
id: redRect
anchors {
fill: parent
leftMargin: 50
bottomMargin: 50
}
color: "red"
Rectangle {
id: yellowRect
anchors {
fill: parent
leftMargin: 50
bottomMargin: 50
}
color: "yellow"
Rectangle {
id: greenRect
anchors {
fill: parent
leftMargin: 50
bottomMargin: 50
}
color: "green"
}
}
}
Text {
id: currentControl
anchors.left: parent.left
anchors.bottom: parent.bottom
}
}
}
I have screenshot from running program. Green rect inside yellow, yellow inside red. I need get control ref when mouse cursor over control.
I'm not familiar with QML, so I don't know the exact syntax for this, but it seems like you want to loop until you find the inner-most control and get the color of that. Here's some C++ish pseudo-code
auto control = parentPanel.childAt(mouseX, mouseY);
while (control)
{
currentControl.text = control.color ? control.color : "not colored";
control = control.childAt(mouseX, mouseY);
}
Of course, this code assumes that the X and Y passed are absolute, not relative. If the are relative, you would need to decrement them by the location of control in each consecutive loop.
I have to implement TreeView in qml. Basically because each subtree is just TreeView itself, i want to use TreeView component in TreeView definition (this is that Repeater on the end).
This is part of code where i reference the component i am defining.
You can see that rootDelegate is actually id of the Component.
Problem is Qt gives error Unable to assign QQuickRow to QQmlComponent
Repeater {
model: childrens
delegate: rootDelegate
}
TreeView.qml
import QtQuick 2.0
Component {
id: rootDelegate
Column {
Row {
id: itemControl
spacing: 2
Rectangle {
anchors.verticalCenter: parent.verticalCenter
gradient: Gradient {
GradientStop { position: 0.0; color: "#EEEEEE" }
GradientStop { position: 1.0; color: "#404040" }
}
width: openChar.implicitWidth
height: openChar.implicitHeight - 6
radius: 3
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
}
Text {
id: openChar
text: "+"
color: "black"
anchors.centerIn: parent
}
}
Rectangle {
height: 1
color: "#A0A0A0"
width: 10
anchors.verticalCenter: parent.verticalCenter
}
Text {
text: model.text
color: "white"
}
}
Repeater {
model: childrens
delegate: rootDelegate
}
}
}
You are trying to use a Сomponent recursively in itself, it is not allowed in Qml