Posts made by Brian Gyetko

Added the InputPanel to my own custom dialog (File Save) to the bottom of it.

When showing the dialog, I center the dialog on screen, making the InputPanel visible at the bottom of the dialog.

After the user inputs the file name to save to and clicks "Save", the dialog is made invisible.

In the dialog's "onVisibleChanged" signal handler, I set dialog.y = 5000, making the dialog move way offscreen even though it is invisible. Now any other component click events are not interfered with.

I found the Charting to be a problem if you are trying to use QML to lay it out and C++ to load the data. I ended up building my own charting.

First, forcing users to invoke Java like reflection on methods and properties is really cumbersome. Why? Because not all the methods are exposed in the DeclarativeChart C++ class. You need Q_INVOKABLE everywhere. The developers should do one thing on the qml ChartView's C++ representation DeclarativeChart. Expose a method called getChartView() or getChart() so users can get at the C++ class entirely. Or allow users to static cast the QObject findObject by objectName reference into a DeclarativeChart (DeclarativeChart's header file should be exposed to the end user). Make the C++ equivalent of what the QML maps to obvious to the user. Document it. Rather than shimming a proxy datasource into the example (Oscilloscope), give the end user of the API full access to the Visual component.

Second. If you load date time stamps that are very large in size (in ms since 1970) say for the year 2015, and set the delta time between points to something small, say 1 second or 1000 ms, set OpenGL to true on the series, you get jagged lines on the screen. Some values display 2 points directly above each other. (Bug) I can't use this.

Third, I was having problems defining a series in QML, adding a few points in the QML markup, and then clearing the points out of series in C++. This all worked. However, when the number of points changed, the points wouldn't render and the axes didn't update. I seemed to be hunting down how to fire signals on series count changed, or axes changed and spent a day doing this. Since I was invoking methods, in a reflection style, maybe some of the signals associated with the methods and properties were not automatically being fired. It was so frustrating that I gave up. I figured that the Charting tool would go through many modifications in the next few updates and I couldn't risk investing my IP in something that might change rapidly from a maintenance perspective, even if I could get things working now. They might get broken in a chart update.

Fourth. I built my own plot component. I subclass QQuickPaintedItem. I render all my data using a inline QPainter to an offscreen image (not attached to the SceneGraph) ON A BACKGROUND THREAD, then transfer the image from the background thread to a slot across the thread boundary and use the following one liner on the UI thread QQuickPaintedItem to render the image.

void MyChart::paint(QPainter *painter){
painter->drawImage(0,0,_qImage,0,0,_qImage.width(),_qImage.height());
}
Since the QPainter has a nice API that is simple to use, the code was easy and therefore straightforward to maintain.

My CPU stays fairly flat no matter how many points I render, since the background thread is doing all the work, blowing away even the fastest OpenGL rendering performance. My UI is so snappy on an ARM processor, people wonder how I did it. The total time to build my plot component was 2 days. I have 1000 points in up to 7 or 8 series updating possibly 2 to 5 times per second.

I have done this in plotting 50000 points (scatter like chart) at a rate of 15 frames per second on an ARM processor using only 15 % of the CPU. OpenGL libraries are not consistent across X86, ARM and others. So you never know what you are going to get when you trust OpenGL. Painting to an offscreen buffer on a background thread always works consistently because it is simple.

It's always good to push as much of the rendering to the background thread as possible.

UI's only have one UI thread. Leave that thread to the user to mouse move, click, drag etc.

However, when using the ChartView in C++, I am trying to set the data I have acquired in C++ on the "series" method, not property.

The Qt documentation provided athttp://doc.qt.io/qt-5/qchart.html
is
QList<QAbstractSeries *> QChart::series() const
Returns all series that are added to the chart.
See also addSeries(), removeSeries(), and removeAllSeries().

So setting and getting properties will not suffice on "METHOD" invocations, unless I am missing something.

If I have a C++ reference to a series defined in qml, or if I can manually added them with addSeries in C++, things will work.

The methods are there, but I can't get a reference to the series objects I need, since I need to invoke methods.

What is the best way forward for accessing the series objects in C++ so I can set the data on them?

There are several examples on how to bind chart data from C++ to a QML ChartView.

My problem with the examples, is I need the following:

Take advantage of the declarative nature of QML to do the layouts. I have many charts, about 60 in an application. I have all my UI laid out in QML thinking I could reference the charts in C++ easily. I don't want to have to to a major redesign. I little is OK.

I need to load the data from C++ for speed. I don't want to render 1000 points in JavaScript 2 or 3 times a second, driving my CPU load high.

I don't want a QML timer to pull the data and load it in JavaScript.

I don't want a global datasource in C++ since I have 60 charts. That would mean 60 global variables.

What I would like is to get a reference to the QML ChartView in C++ by finding the object in C++ and manipulating the LineSeries in C++.

Class QObject

objectName

So I attempt to #include <QtCharts/DeclarativeChart> and oh, oh. Qt doesn't expose this class to be included. So I can't static cast the QObject* into a DeclarativeChart*.

So I then tried to set object names on my LineSeries, exposing those so they can be manipulated. Finding those using _applicationWindow->findChild<QObject*>( "myLineSeries" ); came up null, which sort of makes sense. It's not a visual object.

My questions to Qt are,
A. "Is there an elegant solution where I can either get a reference to the QML based QtChart or QtChartView in C++ elegantly?"
B. "Another thought would be to subclass the QtChart and expose this as a new QML metatype. This seems elegant and I am willing to do this if this is the right way to go."