QT QCharts add and remove series - c++

How i should add and remove series from qchart?
The main mess is that QChart some how store QAxis and QSeries, QSeries themselves refer to QAxis.Above that all that objects are heavy connected.
So instead of pseudo code like this:
void someclass::set_series(QLineSeries*someQLineSeries){
somechart->removeAllSeries();
somechart->removeAllAxis();
somechart->addSeries(someQLineSeries);
}
I should use that:
(zlineseries additionaly store 2 pointers to its axis)
void zhplotview::attach_dt_series(ZLineSeries *series)
if(chart)
{
qDebug()<<"NOT DELETED CHART";
if(viewer)
{
qDebug()<<"NOT DELETED VIEWER";
qDebug()<<"Okay. Try to clear old links and create chart again";
//let chart have 1 series
auto slist=chart->series();
ZLineSeries *old_series=dynamic_cast<ZLineSeries*>(slist.at(0));
old_series->detachAxis(old_series->axis_x);
old_series->detachAxis(old_series->axis_y);
chart->removeAxis(old_series->axis_x);
chart->removeAxis(old_series->axis_y);
vbl->removeWidget(viewer);
chart->removeSeries(old_series);
disconnect(viewer);
disconnect(chart);
delete chart;
delete viewer;
}
else
{
qDebug()<<"chart is 0, but viewer not";
return;
}
}
chart=new QChart();
chart->addSeries(series);
chart->addAxis(series->axis_x,Qt::AlignBottom);
chart->addAxis(series->axis_y,Qt::AlignLeft);
series->attachAxis(series->axis_x);
series->attachAxis(series->axis_y);
viewer=new QZChartView(chart,this);
vbl->addWidget(viewer);

I know it's three years later, but I use a little workaround for this, maybe it's interesting for someone.
On every delta I generate a new chart, and just replace the old one. In order to be fast enough, I keep some data pre-calculated in stack.

Related

Error when dynamically creating more than one Frame at runtime (C++, FMX, IDE: C++ Builder)

I would like to dynamically create a series of Frame components, then save the pointers into a vector.
I am able to dynamically create TEdit components with no problem, but if I replace TEdit with the name of the frame component (that contains an edit box) the program will error. The first frame will be created, but errors when creating the second one, stating "External exception EEFFACE"
Here is the relevant code. Note that if I replace TFrame2 with TEdit, it works.
class TForm1 : public TForm
{
...
public: // User declarations
std::vector<TFrame2*> fields;
...
};
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TFrame2* temp = new TFrame2 (Layout1);
temp->Parent = Layout1;
temp->Align = TAlignLayout::Top;
fields.push_back(temp);
count++;
}
This is what it looks like after one click.
Error message after 2 clicks.
This is how I want it to look after two clicks.
This is what it looks like when I replace TFrame2 with TEdit, after 3 clicks.
-
EDIT
If I try to hard-code the creation of two Frames, I get the same error on the first click.
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TFrame2* temp = new TFrame2 (Layout1);
temp->Parent = Layout1;
temp->Align = TAlignLayout::Top;
fields.push_back(temp);
count++;
TFrame2* temp1 = new TFrame2 (Layout1);
temp1->Parent = Layout1;
temp1->Align = TAlignLayout::Top;
fields.push_back(temp1);
count++;
}
-
EDIT 2
In this post
Can FireMonkey frames be created dynamically?
I see a comment that states
I should note here that it seems the frame objects need to be assigned a unique Name property manually right after creation, at least when using C++, or the next frame object created of the same type will try to take the same name as the first one.
To fix this issue, I needed to set the name of the Frame at runtime. Adding the following code in the Button1 click method fixes the issue.
temp->Name = std::strcat("TFrame2", std::to_string(count).c_str());
This names every new Frame "TFrame2#" where # is the number frame that has been created.

QLineSeries sigsegv when append a new point

I was developping a datalogging application with Qt Creator (Qt 5.9) and I wanted to add a graph with the help of QtCharts.
I explain what I do:
I begin to declare my line as a global variable:
QLineSeries *serie;
In the loop of creating the mainwindow, I create a chart, standard axis and all I need to view the line where I want.
QChart *chart = new QChart();
chart->setTitle("Données accélération");
chart->setAnimationOptions(QChart::AllAnimations);
QChartView *chartView = new QChartView(chart);
chartView->setMinimumWidth(700);
chartView->setRenderHint(QPainter::Antialiasing);
ui->gridLayout_2->addWidget(chartView,0,3,3,1);
QLineSeries *serie = new QLineSeries();
//QSplineSeries *serie = new QSplineSeries();
serie->append(QPointF(50, 50));
serie->append(QPointF(55, 55));
QPen green(Qt::red);
green.setWidth(3);
serie->setPen(green);
chart->addSeries(serie);
chart->createDefaultAxes();
In another function, I use a serialevent to make some choices depending on a switch:
case acquisition :
reely = (recev_message.toInt())/1000;
reelx = index+1;
qDebug() << reely;
serie->append(reelx, reely);
index++;
After a freeze when I received a serial message, I launched a debug. And it seems that a SIGSEGV append at the step serie->append(reelx, reely);
I don't understand why I can't append a new value when in the example programs for Qtcharts it seems to work.
Thank you for your reading.
I found where is the problem.
I effectively declared the serie as a global variable. But in the mainvindow building function I wrote:
QLineSeries *serie = new QLineSeries();
It seems that the compiler deducted that I was re-declaring the object and changed the scope of it. And when I tried to use one of the members in another function, I wasn't in the right scope
So, I changed by that line:
serie = new QLineSeries();
And everything work like a charm.
Thanks to everybody

QML Map: Large amount of displayed items

I have a performance issue while displaying large amounts MapItems on a Map provided by the QML Location module. I already asked the question here (https://forum.qt.io/topic/79229/large-amount-of-qml-mapitems), but nobody could help me, so I wanted to try it here once. I also found this question (How to use the QML/QtLocation module for displaying a large amount of offline data on a map?), but before adding another dependency, I wanted to see if my code can be improved so that QML can handle this situation without any help.
I am currently trying to plot a large amount of items onto a QML Map (30,000 - 120,000 points). These items shall be updated dependent of the position of a QSlider. Performance decreases strongly from about 1,000 items upwards, when I use 30,000 it takes several minutes until the QML Map has all the data visualized and is responsive again. I have a machine which is absolutely capable of fulfilling this task in general, so I think the problem is QML. I am using Qt 5.8.
Is there any way to improve this performance or is it just not possible with a QML-map to plot so many MapItems at a time? I tried MapCircles, Polylines, Polygons and MapQuickItems with images, but for me it seems like the performance issue just arises from adding this amount of MapItems, as I could not see a significant difference in processing time between these types.
I have more data on the map visualized, which should not be refreshed every time the QSlider is moved. Even though I tried just to clear all MapItems and add the new ones for performance tests, but even this did not improve the performance.
My code (a bit abstracted) looks like this:
///-------------- Widget.cpp-----------------///
void ProcessInput(int qslider_pos) {
QVariantList lat_vec;
QVariantList lon_vec;
// Fill vectors with lateral and longitudinal positions
// ...
// Clean current points on map and draw new ones
SendToQmlFuncRemovePoints();
SendToQmlFuncAddPoints(lat_vec, lon_vec);
}
void QmlConnector::SendToQmlFuncRemovePoints()
{
QVariant returnedValue;
QMetaObject::invokeMethod(QmlMapSingleton::instance()->GetRoot(), "remove_points",
Q_RETURN_ARG(QVariant, returnedValue));
}
void QmlConnector::SendToQmlFuncAddPoints(QVariantList input_one, QVariantList input_two)
{
QVariant returnedValue;
QMetaObject::invokeMethod(QmlMapSingleton::instance()->GetRoot(), "add_points",
Q_RETURN_ARG(QVariant, returnedValue),
Q_ARG(QVariant, QVariant::fromValue(input_one)), Q_ARG(QVariant, QVariant::fromValue(input_two)));
}
.
///-------------- Map.qml -----------------///
Map {
anchors.fill: parent
property variant points: ({})
property int pointCounter: 0
Plugin
{
id: osmplugin
name: "osm"
PluginParameter { name: "osm.mapping.highdpi_tiles"; value: true }
}
Component.onCompleted: {
points = new Array();
}
id: map
plugin: osmplugin
//Javascript functions
function add_points(array_lat, array_lon) {
var myArray = new Array()
var component = Qt.createComponent("mapcircle.qml");
for (var i=0; i<array_lat.length; i++)
{
var object = component.createObject(map, { "center": QtPositioning.coordinate(array_lat[i], array_lon[i]})
map.addMapItem(object)
myArray.push(object)
}
map.points = myArray
}
function remove_points() {
var count = map.points.length
for (var i = 0; i<count; i++){
map.removeMapItem(map.points[i])
map.points[i].destroy()
}
map.points = []
}
}
.
///-------------- mapcircle.qml -----------------///
import QtQuick 2.0
import QtLocation 5.6
MapCircle {
radius: 1
border.width: 0
color: 'green'
}
Qt says that the performance decreases with the number of elements added to the map. Do you need all the points to be visible on the map in the same time, if not you can play around with visibility.
Can't you use QQuickPaintedItem to paint the points in C++ and wrap it into an MapQuickItem, if you have multiple polygonsfor e.g? But also there are some limitation, you cannot have to big images displayed.
If you need all the points maybe you can have different points based on the map zoom level and reduce the number of points added to the map at small zoom level, as was recommended on the other group ...

How do I make a custom event with VTK?

I'm making a thread software with VTK, where I need to change the model itself in real time, while I need to change his method of rendering. Everything is working fine, but, the problem start with the interactor->start(); , the model data gets updated just fine, but it's only showed on screen when I move The camera. Also I have selected some methods for generating a 3D data from a imagedata file, for that I need to close the vtk window (interactor window) and then the code will reopen it and send the new data generated to it...
I would need something like these:
int force close_window = false; int refresh_interactor = false;
I managed to make the Window close, but only with vtkcommand::Keypressed command, but idk how do I do with a new command :S, I tried the vtkcommand::UserEvent but I didn't found a good information about how to deal with that data (like some way to call it)
the way I'm dealing with VTK is with two threads, the first one, is just about the vtk iren loop, and the second one would manage the models and check if iren requires to be updated.
In my dream code it should be something like this:
=======================================================
bool VTKWindow()
{
...
vtkSmartPointer ator = vtkSmartPointer::New();
iren = vtkSmartPointer::New();
RenWindow = vtkSmartPointer::New();
render->SetBackground(.1, .2, .3);
RenWindow->AddRenderer(renderer);
iren->SetRenderWindow(RenWindow);
if(data_type == voxel_type)
{
Render->AddViewProp(VoxelData);
}
else
{
actor->SetMapper(PolyData);
Render->AddActor(Actor);
}
RenWindow->Render();
iren->Start();
}
void ManageVTK()
{
while true loop...
if(force close_window == true)
do some command to exit the iren loop
if(refresh_interactor == true)
do some command to refresh iren
}
Sorry for the english, it's not my native language, and also sorry about the question format, it's the first time I'm using stackoverflow
It may sounds stupid, but, I found a kind of solution for the problem.
I saw on related links this guy vtkRenderWindowInteractor event loop and threading and, it's almost the same problem...
class VTKNewEvent : public vtkCommand{
public:
vtkTypeMacro(VTKNewEvent , vtkCommand);
static VTKNewEvent * New(){
return new VTKNewEvent ;
}
void Execute(vtkObject * caller, unsigned long vtkNotUsed(eventId), void * vtkNotUsed(callData)){
vtkRenderWindowInteractor *iren = static_cast<vtkRenderWindowInteractor*>(caller);
if (iren_close == true){
iren->GetRenderWindow()->Finalize // Stop the interactor
iren->TerminateApp();
iren_close = false;
}
if (iren_update== true){
renderJanela->Render();
iren_update= false;
}
}
};
bool VTKWindow(){
vtkSmartPointer<VTKNewEvent > IrenRefresh= vtkSmartPointer<VTKNewEvent>::New();
...
iren->CreateRepeatingTimer(1);//this makes that IrenRefresh will be called at every 1ms
iren->AddObserver(vtkCommand::TimerEvent, IrenRefresh);
iren->Start();
...
}
it's simple, but, maybe not the best, but it did Th job, I hope this link will help people that are starting into the VTK world, since threads + rendering loop wasn't a simple job to understand what was going on

cocos2d creating dynamic menu lists

How do I create a CCMenuItem list dynamically?
//Returns me an array with my items
Items *items = [ItemParser loadItemsForLevel:selectedLevel fromSuperLevel:selectedSuperLevel];
For an item I have a string with the name of the item that I'd like to display in my CCMenu. The number of items could vary but I want to display only 6 items at a time
and how do I remove it? I'm cleaning up from the CCLayer but I'd like to do it also from the menu list
Anyone?
Cocos2D does not provide a method to do this.
You may create your own initializer based on the original one found in "CCMenu.m".
The original looks like this (I removed code that does not add items here for clarity). Create your own init method based on the original and add a variable amount of items instead. If you like you may also set it up as a category to CCMenu.
-(id) initWithItems: (CCMenuItem*) item vaList: (va_list) args
{
if( (self=[super init]) ) {
// ... code cut for clarity
if (item) {
[self addChild: item z:z];
CCMenuItem *i = va_arg(args, CCMenuItem*);
while(i) {
z++;
[self addChild: i z:z];
i = va_arg(args, CCMenuItem*);
}
}
// ... code cut for clarity
}
return self;
}
Update:
When your menu items change then rebuild the whole menu.