I'm new to Qt and i'm starting a new GUI using QML.
I have a map and i want to display a marker. But i'm not able to display the marker using a MapQuickItem.
In my code below the title, the map and the MapCircle are displayed correctly, but the MapQuickItem is not displayed.
The image "marker.png" exists and i'm able to display it.
Thanks for your help.
import QtQuick 2.0
import QtLocation 5.6
import QtPositioning 5.6
import "../items"
SimpleTile {
m_width : 300
m_height : 300
property double m_latitude;
property double m_longitude;
innerObject: Column {
id: colMap
anchors.fill: parent
Plugin {
id: mapPlugin
name: "esri"
}
Text {
id: title
width: colMap.width
height: 25
horizontalAlignment: TextInput.AlignHCenter
font.bold: true
font.pointSize: 15
text: "Position"
}
Map {
id: map
width: colMap.width
height: parent.height - title.height
plugin: mapPlugin
center: QtPositioning.coordinate(m_latitude, m_longitude)
zoomLevel: 14
MapQuickItem {
id: marker
anchorPoint.x: image.width/2
anchorPoint.y: image.height
coordinate {
latitude: m_latitude
longitude: m_longitude
}
sourceItem: Image { id: image; source: "qrc:/images/marker.png" }
}
MapCircle {
radius: 1000
color: "red"
opacity: 0.4
center {
latitude: m_latitude
longitude: m_longitude
}
}
}
}
}
Ok, I solve my problem by changing
...
MapQuickItem {
...
coordinate {
latitude: m_latitude
longitude: m_longitude
}
...
to
...
MapQuickItem {
...
coordinate: QtPositioning.coordinate(m_latitude, m_longitude)
...
Thanks for your answers.
Related
I'm using SwiftUI Charts to make a LineMark chart. Everything seems to work, except I'm getting this error in the console for every data point that the chart tries to plot.
"Error: this application, or a library it uses, has passed an invalid numeric value (NaN, or not-a-number) to CoreGraphics API and this value is being ignored. Please fix this problem."
I've setup a backtrace in the scheme but I can't make any sense of it.
Here's my code for the chart:
private var chart: some View {
Chart(viewModel.weatherArray, id: \.DATETIME) {
LineMark(
x: .value("Date", $0.DATETIME),
y: .value("Temp", $0.TMP)
)
.lineStyle(StrokeStyle(lineWidth: lineWidth))
.foregroundStyle(chartColor.gradient)
// .interpolationMethod(interpolationMethod.mode)
.symbol(Circle().strokeBorder(lineWidth: lineWidth))
.symbolSize(showSymbols ? 60 : 0)
}
//the chart overlay uses the tap gesture to to define the selected element on the chart
.chartOverlay { proxy in
GeometryReader { geo in
Rectangle().fill(.clear).contentShape(Rectangle())
.gesture(
SpatialTapGesture()
.onEnded { value in
let element = findElement(location: value.location, proxy: proxy, geometry: geo)
if selectedElement?.DATETIME == element?.DATETIME {
// If tapping the same element, clear the selection.
selectedElement = nil
} else {
selectedElement = element
}
}
.exclusively(
before: DragGesture()
.onChanged { value in
selectedElement = findElement(location: value.location, proxy: proxy, geometry: geo)
}
)
)
}
}
.chartBackground { proxy in
ZStack(alignment: .topLeading) {
GeometryReader { geo in
//if showlolipop is the toggle, i dont need that but its simpler to keep it.
if showLollipop,
let selectedElement {
let dateInterval = Calendar.current.dateInterval(of: .hour, for: selectedElement.DATETIME)!
let startPositionX1 = proxy.position(forX: dateInterval.start) ?? 0
let lineX = startPositionX1 + geo[proxy.plotAreaFrame].origin.x
let lineHeight = geo[proxy.plotAreaFrame].maxY
let boxWidth: CGFloat = 100
let boxOffset = max(0, min(geo.size.width - boxWidth, lineX - boxWidth / 2))
//this is the part that defines how the lolipop looks
//lolipop stem
Rectangle()
.fill(.red)
.frame(width: 2, height: lineHeight)
.position(x: lineX, y: lineHeight / 2)
//lolipop head
VStack(alignment: .center) {
Text("\(selectedElement.DATETIME, format: .dateTime.year(.twoDigits).month(.twoDigits).day().hour())")
.font(.callout)
.foregroundStyle(.secondary)
Text("\(selectedElement.TMP, format: .number) °C")
.font(.title2.bold())
.foregroundColor(.primary)
}
//This is the background of the lolipop head
.background {
ZStack {
RoundedRectangle(cornerRadius: 8)
.fill(.background)
RoundedRectangle(cornerRadius: 8)
.fill(.quaternary.opacity(0.7))
}
.padding(.horizontal, -8)
.padding(.vertical, -4)
}
.offset(x: boxOffset)
}
}
}
}
}
//This function is what makes the lolipop work. It finds the info for the labels
func findElement(location: CGPoint, proxy: ChartProxy, geometry: GeometryProxy) -> WeatherForecastClass? {
let data = viewModel.weatherArray
let relativeXPosition = location.x - geometry[proxy.plotAreaFrame].origin.x
if let date = proxy.value(atX: relativeXPosition) as Date? {
// Find the closest date element.
var minDistance: TimeInterval = .infinity
var index: Int? = nil
for weatherDataIndex in data.indices {
let nthWeatherDataDistance = data[weatherDataIndex].DATETIME.distance(to: date)
if abs(nthWeatherDataDistance) < minDistance {
minDistance = abs(nthWeatherDataDistance)
index = weatherDataIndex
}
}
if let index {
return data[index]
}
}
return nil
}
}
Here's the Backtrace:
Backtrace:
<CGPathAddLineToPoint+78>
<$sSo16CGMutablePathRefa12CoreGraphicsE4move2to9transformySo7CGPointV_So17CGAffineTransformVtFTm+113>
<_Charts_getAxisMarkWitnessTable+3021427>
<_Charts_getAxisMarkWitnessTable+3022243>
<_Charts_getAxisMarkWitnessTable+3022291>
<__CGPathApplyWithBlock_block_invoke+63>
<_ZNK2CG4Path5applyEU13block_pointerFv17CGPathElementTypePK7CGPointPbE+246>
<CGPathApplyWithBlock+114>
<_Charts_getAxisMarkWitnessTable+3016835>
<_Charts_getAxisMarkWitnessTable+428626>
<_Charts_getAxisMarkWitnessTable+464967>
<__swift_memcpy33_4+28201>
<_Charts_getAxisMarkWitnessTable+425557>
<_Charts_getAxisMarkWitnessTable+415811>
<_Charts_getAxisMarkWitnessTable+462771>
<_Charts_getAxisMarkWitnessTable+416756>
<_Charts_getAxisMarkWitnessTable+416214>
<_Charts_getAxisMarkWitnessTable+413871>
<_Charts_getAxisMarkWitnessTable+462275>
<_Charts_getAxisMarkWitnessTable+416756>
<_Charts_getAxisMarkWitnessTable+412741>
<_Charts_getAxisMarkWitnessTable+422521>
<_Charts_getAxisMarkWitnessTable+464073>
<_Charts_getAxisMarkWitnessTable+417649>
<_Charts_getAxisMarkWitnessTable+421314>
<_Charts_getAxisMarkWitnessTable+432881>
<_Charts_getAxisMarkWitnessTable+434361>
<_Charts_getAxisMarkWitnessTable+434361>
<_Charts_getAxisMarkWitnessTable+434361>
<_Charts_getAxisMarkWitnessTable+444893>
<_callVisitTableColumnType2+31236>
<__swift_memcpy108_8+1328>
<__swift_memcpy12_4+43911>
<__swift_memcpy12_4+34396>
<_callVisitTableColumnType2+30317>
<block_destroy_helper.6215+63949>
<_ZN2AG5Graph11UpdateStack6updateEv+537>
<_ZN2AG5Graph16update_attributeENS_4data3ptrINS_4NodeEEEj+443>
<_ZN2AG5Graph9value_refENS_11AttributeIDEPK15AGSwiftMetadataRh+123>
<AGGraphGetValue+287>
<__swift_memcpy38_4+28770>
<get_witness_table 7SwiftUI19WidgetConfigurationRzAA13PreferenceKeyRd__r__lAA15Modif
<get_witness_table 7SwiftUI19WidgetConfigurationRzAA13PreferenceKeyRd__r__lAA15Modi
<__swift_memcpy106_8+51272>
<__swift_memcpy106_8+51342>
<-[UIView(CALayerDelegate) layoutSublayersOfLayer:]+2305>
<_ZN2CA5Layer16layout_if_neededEPNS_11TransactionE+526>
<-[UIView(Hierarchy) layoutBelowIfNeeded]+1447>
<__swift_memcpy64_4+166111>
<block_destroy_helper.23+59728>
<block_destroy_helper.23+59750>
<+[UIView(Animation) performWithoutAnimation:]+84>
<__swift_memcpy64_4+161134>
<block_destroy_helper.23+59728>
<block_destroy_helper.23+59750>
<+[UIView(Animation) performWithoutAnimation:]+84>
<__swift_memcpy64_4+166410>
<objectdestroy.142Tm+41107>
<block_destroy_helper+36990>
<block_destroy_helper+35295>
<get_witness_table 7SwiftUI19WidgetConfigurationRzAA13PreferenceKeyRd__r__lAA15M
<__swift_memcpy89_8+19524>
<dynamic_cast_existential_0_superclass_conditional+6323>
<block_destroy_helper.89+25608>
<_callVisitStyleContextType2+33683>
<block_destroy_helper.130+8663>
<block_destroy_helper.130+8519>
<-[UIViewController _setViewAppearState:isAnimating:]+1061>
<-[UIViewController __viewDidAppear:]+146>
<-[UINavigationController viewDidAppear:]+173>
<-[UIViewController _setViewAppearState:isAnimating:]+1061>
<__52-[UIViewController _setViewAppearState:isAnimating:]_block_invoke_2+189>
<__52-[UIViewController _setViewAppearState:isAnimating:]_block_invoke+185>
<__NSARRAY_IS_CALLING_OUT_TO_A_BLOCK__+7>
<-[__NSSingleObjectArrayI enumerateObjectsWithOptions:usingBlock:]+80>
<-[UIViewController _setViewAppearState:isAnimating:]+2066>
<__52-[UIViewController _setViewAppearState:isAnimating:]_block_invoke_2+189>
<__52-[UIViewController _setViewAppearState:isAnimating:]_block_invoke+185>
<__NSARRAY_IS_CALLING_OUT_TO_A_BLOCK__+7>
<-[__NSSingleObjectArrayI enumerateObjectsWithOptions:usingBlock:]+80>
<-[UIViewController _setViewAppearState:isAnimating:]+2066>
<-[UIViewController __viewDidAppear:]+146>
<-[UINavigationController viewDidAppear:]+173>
<-[UIViewController _setViewAppearState:isAnimating:]+1061>
<-[UIViewController __viewDidAppear:]+146>
<-[UIViewController _endAppearanceTransition:]+232>
<-[UINavigationController navigationTransitionView:didEndTransition:fromView:toV
<__49-[UINavigationController _startCustomTransition:]_block_invoke+620>
<-[_UIViewControllerTransitionContext completeTransition:]+101>
<__53-[_UINavigationParallaxTransition animateTransition:]_block_invoke.163+841>
<__UIVIEW_IS_EXECUTING_ANIMATION_COMPLETION_BLOCK__+15>
<-[UIViewAnimationBlockDelegate _didEndBlockAnimation:finished:context:]+797>
<-[UIViewAnimationState sendDelegateAnimationDidStop:finished:]+190>
<-[UIViewAnimationState animationDidStop:finished:]+263>
<-[UIViewAnimationState animationDidStop:finished:]+648>
<_ZN2CA5Layer23run_animation_callbacksEPv+318>
<_dispatch_client_callout+8>
<_dispatch_main_queue_drain+1463>
<_dispatch_main_queue_callback_4CF+31>
<__CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__+9>
<__CFRunLoopRun+2482>
<CFRunLoopRunSpecific+560>
<GSEventRunModal+139>
<-[UIApplication _run]+994>
<UIApplicationMain+123>
<__swift_memcpy93_8+11936>
<__swift_memcpy93_8+11597>
<__swift_memcpy195_8+12255>
<$s27SpotWx_MergeBackendFrontend0ab1_cdE3AppV5$mainyyFZ+30>
<main+9>
1079162bf
[Unknown process name] CGPathCloseSubpath: no current point.
I think I've narrowed the problem down to the interactivity of the chart. When I simplify the chart down to this the errors go away:
private var chart: some View {
Chart(viewModel.weatherArray, id: \.DATETIME) {
LineMark(
x: .value("Date", $0.DATETIME),
y: .value("Temp", $0.TMP)
)
}
}
I've managed to deduce the problem was this modifier on the Chart element:
.symbolSize(showSymbols ? 60 : 0)
I'm not sure why this happens, as that modifier worked when I was testing it on a static array of data, although all that data was positive. If someone knows what the root of the problem is I'm pretty curious.
Here is the highchart demo of map with pie charts.
US map with pie charts
But this map is only for US. Here is my js fiddle.
World wide map with pie charts
// Add the pies after chart load, optionally with offset and connectors
Highcharts.each(chart.series[0].points, function (state) {
if (!state.id) {
return; // Skip points with no data, if any
}
var pieOffset = state.pieOffset || {},
centerLat = parseFloat(state.properties.latitude),
centerLon = parseFloat(state.properties.longitude);
// Add the pie for this state
chart.addSeries({
type: 'mappie',
name: state.id,
zIndex: 6, // Keep pies above connector lines
sizeFormatter: function () {
var yAxis = this.chart.yAxis[0],
zoomFactor = (yAxis.dataMax - yAxis.dataMin) /
(yAxis.max - yAxis.min);
return Math.max(
this.chart.chartWidth / 45 * zoomFactor, // Min size
this.chart.chartWidth / 11 * zoomFactor * state.sumVotes / maxVotes
);
},
tooltip: {
// Use the state tooltip for the pies as well
pointFormatter: function () {
return state.series.tooltipOptions.pointFormatter.call({
id: state.id,
hoverVotes: this.name,
demVotes: state.demVotes,
repVotes: state.repVotes,
libVotes: state.libVotes,
grnVotes: state.grnVotes,
sumVotes: state.sumVotes
});
}
},
data: [{
name: 'Democrats',
y: state.demVotes,
color: demColor
}, {
name: 'Republicans',
y: state.repVotes,
color: repColor
}, {
name: 'Libertarians',
y: state.libVotes,
color: libColor
}, {
name: 'Green',
y: state.grnVotes,
color: grnColor
}],
plotOptions: {
pie: {
center: [state.plotX+400, state.plotY]
}
}
}, false);
// Draw connector to state center if the pie has been offset
/* if (pieOffset.drawConnector !== false) {
var centerPoint = chart.fromLatLonToPoint({
lat: centerLat,
lon: centerLon
}),
offsetPoint = chart.fromLatLonToPoint({
lat: centerLat + (pieOffset.lat || 0),
lon: centerLon + (pieOffset.lon || 0)
});
chart.series[2].addPoint({
name: state.id,
path: 'M' + offsetPoint.x + ' ' + offsetPoint.y +
'L' + centerPoint.x + ' ' + centerPoint.y
}, false);
} */
});
I want to show map world wide map where each pie represent a country. Everything is working fine but world.js file dont have lat and long values.due to which i am facing positon issue of pie on each location.i tried using plotx and ploty .but it doesnt works. So is there any way to show pie axactly on the country area the way it is working US map?
You can use plotX & plotY properties of the region when it doesn't have the lat & lon defined.
Replace these two pieces of code:
plotOptions: {
pie: {
center: [state.plotX+400, state.plotY]
}
}
// Handle lat/lon support
if (options.center.lat !== undefined) {
var point = chart.fromLatLonToPoint(options.center);
options.center = [
chart.xAxis[0].toPixels(point.x, true),
chart.yAxis[0].toPixels(point.y, true)
];
}
with these ones:
center: {
plotX: state.plotX,
plotY: state.plotY
}
// Replace lat/lon with plotX/plotY
if (options.center.plotX !== undefined) {
options.center = [options.center.plotX, options.center.plotY];
}
By the way: using plotOptions inside series options is not valid. plotOptions should be placed in the top level of the chart options structure. Here's more info on that: https://api.highcharts.com/highcharts/plotOptions
Live demo: https://jsfiddle.net/BlackLabel/k5mdL6vn/
It is possible to get longitude and latitude in BlackBerry using only qml? I found http://dengineer.com/adding-qml-gps-to-blackberry-10/ but it isnt work. Only black screen on my device.
This is my code:
import bb.cascades 1.0
import QtMobilitySubset.location 1.1
Page {
property string longitude
property string latitude
property variant cord
Container {
layout: DockLayout {}
attachedObjects: [
PositionSource{
id: location
updateInterval: 1000
onPointChanged: {
cord = location.position.coordinate;
longitude = cord.longitude;
latitude = cord.latitude;
result.setText(longitude + " " + latitude)
}
}]
Button {
text: qsTr("Locate me")
horizontalAlignment: HorizontalAlignment.Center
onClicked: {
location.start()
}
}
Label {
id: result
text: qsTr("0 0")
textStyle.base: SystemDefaults.TextStyles.BigText
verticalAlignment: VerticalAlignment.Center
horizontalAlignment: HorizontalAlignment.Center
}
}
}
I have error:
Jun 08 19:31:14.025 com.example.GPS_qml.testDev_ple_GPS_qml341af9aa.30007492 default 9000 WARNING --- errors: (file:///apps/com.example.GPS_qml.testDev_ple_GPS_qml341af9aa/native/assets//main.qml:32:13: Cannot assign to non-existent property "onPointChanged"
onPointChanged: {
^)
My understanding for QML is that it's only for display, you'll have to write some native code to do what you need. See samples at
https://github.com/blackberry/Cascades-Samples
you can check possibly the locationdiagnostics project giving an example of the Location API
I need to display multiple pie charts that are all related to the same data. As such I want them all to be part of the same chart and implement them as individual series.
This all works no problems until I tried to put labels/titles over each individual pie chart. It seems that I can only have a title over the entire group. See jsfiddle
Is there any way to have the titles over each chart?
See above jsfiddle for example
I encountered the same problem, and found this solution via highcharts support forum :
http://highcharts.uservoice.com/forums/55896-general/suggestions/3073133-pie-title
The Highcharts dude has written a plugin that you can see working on the following jsfiddle : http://jsfiddle.net/highcharts/tnSRA/
I have copy-pasted this plugin in a highcharts-plugins.js file that I included in my website, works like a charm!
Here's the plugin code :
/**
* Pie title plugin
* Last revision: 2012-12-21
*/
(function (Highcharts) {
Highcharts.wrap(Highcharts.seriesTypes.pie.prototype, 'render', function (proceed) {
var chart = this.chart,
center = this.center || (this.yAxis && this.yAxis.center),
titleOption = this.options.title,
box;
proceed.call(this);
if (center && titleOption) {
box = {
x: chart.plotLeft + center[0] - 0.5 * center[2],
y: chart.plotTop + center[1] - 0.5 * center[2],
width: center[2],
height: center[2]
};
if (!this.title) {
this.title = this.chart.renderer.label(titleOption.text)
.css(titleOption.style)
.add()
.align(titleOption, null, box);
} else {
this.title.align(titleOption, null, box);
}
}
});
}(Highcharts));
And this is how you configure your title (put this in your series elements) :
title: {
// align: 'left',
// x: 0
// style: { color: XXX, fontStyle: etc }
text: '<b>Pie 1</b><br>Subtext',
verticalAlign: 'top',
y: -40
},
To further improve on this, the code below correctly handles left, center, and right justification for the titles. See fiddle at http://jsfiddle.net/9y4Lj4yr/ for an example.
/**
* Pie title plugin
* Last revision: 2015-5-20
*/
(function (Highcharts) {
Highcharts.wrap(Highcharts.seriesTypes.pie.prototype, 'render', function (proceed) {
var chart = this.chart,
center = this.center || (this.yAxis && this.yAxis.center),
titleOption = this.options.title,
box;
proceed.call(this);
if (center && titleOption) {
box = {
x: chart.plotLeft + center[0] - 0.5 * center[2],
y: chart.plotTop + center[1] - 0.5 * center[2],
width: center[2],
height: center[2]
};
if (!this.title) {
this.title = this.chart.renderer.label(titleOption.text)
.css(titleOption.style)
.add()
}
var labelBBox = this.title.getBBox();
if (titleOption.align == "center")
box.x -= labelBBox.width/2;
else if (titleOption.align == "right")
box.x -= labelBBox.width;
this.title.align(titleOption, null, box);
}
});
} (Highcharts));
You can use renderer which allows to add text in any place.
http://api.highcharts.com/highcharts#Renderer.text()
Improving on Vincent's answer. This is how I used it for simple Text titles.
extendHighcharts = function(){
Highcharts.wrap(Highcharts.seriesTypes.pie.prototype, 'render', function (proceed) {
//Clear the title if added previously
//if your chart data does not change, this reference storage for removal can be left out
if(this.chart.subChartTitleElement){
this.chart.subChartTitleElement[this.id].destroy();
}
proceed.call(this);
if (this.center && this.options.title) {
//first, add the title, at center or anywhere, we need the container width to center it
this.chart.subChartTitleElement[this.id] = this.chart.renderer.text(this.options.title.text,this.center[0],this.center[1]);
this.chart.subChartTitleElement[this.id].css(this.options.title.style)
this.chart.subChartTitleElement[this.id].add();
//Center the title using the container(Bounding Box = BBox) width
var xCenter = this.chart.plotLeft + this.center[0] - (this.chart.subChartTitleElement[this.id].getBBox().width/2),
yCenter = this.chart.plotTop + this.center[1] - 0.6 * this.center[2];
this.chart.subChartTitleElement[this.id].attr(
{
x:xCenter,
y:yCenter
}
);
}
});
}
USAGE
this.chart.addSeries({
type: 'pie',
name: 'pie_chart_1',
data: pieChartData,
center: ['80%','25%'],
size: '35%',
showInLegend: false,
dataLabels: {
enabled: false
},
//this part adds the relevant information
title: {
text:'Pie Chart Title',
verticalAlign: 'top',
y: -40
},
id:'a_unique_id_or_name'
});
I have a select element with some countries, when "change" is fired, I call a function to get the coords then add the marker. It's ok but when the marker is added, the marker isn't centered.
I'm using the latest version 5.0b.
// get coords
$gmap.gmap3({
getlatlng: {
address: complete_address,
callback: function(result){
if(result) {
var i = 0;
$.each(result[0].geometry.location, function(index, value) {
if(i == 0) { lat = value; }
if(i == 1) { lng = value; }
i++;
});
// add marker
$gmap.gmap3({
marker: {
address: complete_address,
options: {
draggable: false,
animation: google.maps.Animation.DROP
}
},
map:{
options:{
center:[lat, lng],
zoom: zoom
}
}
});
}
}
}
});
I get in the console: "Uncaught Error: Incorrect value for : 51.919438,19.14513599999998"
Any tips would by appreciate.
Regards
Just found,
center: new google.maps.LatLng(lat, lng),