Apply transformation to PolyData - c++

I want to be able to apply tranformations to Polydata but no matter how I try to do it, it just doesn't work.
Here is what I have for "drawing" my polydata in a class call Drawing.cpp:
Drawing.h
vtkSmartPointer<vtkPlane> clipPlane;
vtkSmartPointer<vtkImplicitPlaneRepresentation> planeRep;
vtkSmartPointer<vtkActor> actorPlaneSource;
vtkSmartPointer<vtkActor> mainActor;
vtkSmartPointer<vtkTransformPolyDataFilter> transformFilter;
vtkSmartPointer<vtkTransform> translation ;
vtkContextView* ctxView ;
vtkRenderWindow* win ;
vtkRenderer* ren ;
vtkCamera* cam ;
vtkSmartPointer<vtkPolyData> inputPolyData;
Then the read function is called and starts the rendering, here is the function in drawing.cpp:
void Drawing::read(){
std::string filename = BUNNY;
// Read all the data from the file
vtkSmartPointer<vtkXMLPolyDataReader> reader =vtkSmartPointer<vtkXMLPolyDataReader>::New();
reader->SetFileName(filename.c_str());
reader->Update();
inputPolyData = reader->GetOutput();
cout << "File Found and Loaded : " << filename << endl ;
vtkSmartPointer<vtkTransform> translation = vtkSmartPointer<vtkTransform>::New();
translation->Translate(0.3, -0.05, 0);
transformFilter = vtkSmartPointer<vtkTransformPolyDataFilter>::New();
//transformFilter->SetInputConnection(reader->GetOutputPort());
transformFilter->SetInputData(inputPolyData);
transformFilter->SetTransform(translation);
//transformFilter->Update();
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInputConnection(transformFilter->GetOutputPort());
mainActor = vtkSmartPointer<vtkActor>::New();
mainActor->SetMapper(mapper);
ren->AddActor(mainActor);
vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New();
iren->SetRenderWindow(win);
vtkInteractorStyleMultiTouchCamera *style =
vtkInteractorStyleMultiTouchCamera::New();
iren->SetInteractorStyle(style);
//Start the event loop
iren->Initialize();
iren->Start();
defineClipping();
win->PolygonSmoothingOn();
win->Render();
win->Start();
}
From this, I have an other thread running a server that gets messages and has a pointer to my drawing object and is supposed to call one of these three functions depending on the message it gets from its clients:
void Drawing::scale(float k){
vtkSmartPointer<vtkTransform> transform =vtkSmartPointer<vtkTransform>::New();
transform->Scale(5,1,1);
vtkSmartPointer<vtkTransformFilter> transformFilter = vtkSmartPointer<vtkTransformFilter>::New();
transformFilter->SetInputConnection(cone->GetOutputPort());
transformFilter->SetTransform(transform);
mapper->SetInputConnection(transformFilter->GetOutputPort());
ren->GetActiveCamera();
}
void Drawing::translate(float x, float y, float z){
cout << "Translate: " << x << " - " << " - " << y << " - " << z << endl ;
vtkSmartPointer<vtkTransform> transform1a = vtkSmartPointer<vtkTransform>::New();
//transform1a->Translate(x,y,z);
//transformFilter->SetTransform(transform1a);
//transformFilter->Update();
double* position = mainActor->GetPosition();
mainActor->SetPosition(position[0]+x,position[1]+y,position[2]+z);
}
void Drawing::rotate(float x, float y, float z){
cout << "Rotate: " << x << " - " << " - " << y << " - " << z << endl ;
vtkSmartPointer<vtkTransform> transform1a = vtkSmartPointer<vtkTransform>::New();
//transform1a->PostMultiply();
//transform1a->RotateX(x);
//transform1a->RotateY(y);
//transform1a->RotateZ(z);
//mainActor->SetUserTransform(transform1a);
mainActor->RotateWXYZ(20,1,0,0);
}
None of these functions work because nothing is changing in the rendering windows unless I click in the rendering window itself.
So I thought maybe I should try and add to every transformation functions: ctxView->Render();
But when I do I get:
Error the ressource is already busy.
I'm a newbie in VTK but I find it weird that I can't even do a simple transformation to an object. Would really like to get some help with that.
EDIT:
Ok so after hours of trying different things I have notices that if I comment out the line iren->Start(); my rotations and translations are called. However, the program closes as soon as there done and I cannot interact with my window anymore. Would you have some insights on that?
Thanks in advance.

Yes, I could try to give a little code that made rotations to a polydata, but I guess that is something different from your pipeline (I am using vtkImageReslice object as m_pReslice):
int nExtent[3];
double dSpacing[3];
double dOrigin[3];
m_pReader->GetOutput()->GetSpacing(dSpacing);
m_pReader->GetOutput()->GetOrigin(dOrigin);
m_pReader->GetOutput()->GetDimensions(nExtent);
double dCenter[3];
dCenter[0] = dOrigin[0] + dSpacing[0] * 0.5 * nExtent[0]; // nExtent[0] is width
dCenter[1] = dOrigin[1] + dSpacing[1] * 0.5 * nExtent[1]; // nExtent[1] is height
dCenter[2] = dOrigin[2] + dSpacing[2] * 0.5 * nExtent[2]; // nExtent[2] is depth
vtkSmartPointer<vtkTransform> pTransform = vtkSmartPointer<vtkTransform>::New();
pTransform->PreMultiply();
int nDirection = CDirectionDlg::GetDirection();
if(CDirectionDlg::DIR_AXIAL == nDirection)
{
pTransform->Translate(dCenter[0], 0, dCenter[2]);
pTransform->RotateY(180);
pTransform->Translate(-dCenter[0], 0, -dCenter[2]);
}
else
{
pTransform->Translate(dCenter[0], dCenter[1], 0);
pTransform->RotateZ(180);
pTransform->Translate(-dCenter[0], -dCenter[1], 0);
}
m_pReslice->SetResliceTransform(pTransform);
m_pReslice->SetInterpolationModeToLinear();
m_pReslice->Update();
Consider that another way to rotate an object in a view is to moving camera ... I hope it help you.

As flaviu2 wrote, you absolutely need to call
ren->Render();
after updating your vtkTransform. Renderers do not watch VTK objects that are being rendered to see if anything has been updated. You need to call the Render() member function explicitly.
Beware threading. It is possible to use threading, but most of VTK is not thread safe, and it is probably going to cause you some headaches. To separate this problem from potential problems caused by using different threads to update objects, I would try to get this working without threading, and update this question if you still encounter problems.

Since your problem is the interactor, try doing this hack. Waht it does is create a timer for the interactor that will help get out of the start blocking method :
class CommandSubclass2 : public vtkCommand
{
public:
vtkTypeMacro(CommandSubclass2, vtkCommand);
static CommandSubclass2 *New()
{
return new CommandSubclass2;
}
void Execute(vtkObject *vtkNotUsed(caller), unsigned long vtkNotUsed(eventId),
void *vtkNotUsed(callData))
{
std::cout << "timer callback" << std::endl;
renderWindowInteractor->ExitCallback();
}
};
// in your main
vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New();
iren->SetRenderWindow(win);
iren->CreateRepeatingTimer(1);
vtkSmartPointer<CommandSubclass2> timerCallback =
vtkSmartPointer<CommandSubclass2>::New();
iren->AddObserver ( vtkCommand::TimerEvent, timerCallback );
vtkInteractorStyleMultiTouchCamera *style =
vtkInteractorStyleMultiTouchCamera::New();
iren->SetInteractorStyle(style);
while(true)
{
iren->Start();
ren->Render();
}
Probably not the good way of doing it, but I don't know any other way to get out of the interactor blocking method start()

So thanks to the help of people here and some research with the code and documentation I've figured that this part in my code was responsible for nothing happening when trying to rotate/translate/scale my Polydata:
//Start the event loop
iren->Initialize();
iren->Start();
Indeed the start() method of the vtkRenderWindowInteractor is blocking and therefore no matter what I could call afterward was not processed. Getting rid of it allows me to call my transformation functions. Yet with the loss of the possible interaction with the data and the window closing right after every transformation is applied.

Related

Problems Displaying Mat Image in Windows Forms C++ Visual Studio 2019

I am new to C++ gui design and I am not too familiar with using pointers. Recently I have run into a few problems when trying to get an OpenCV Mat Image to display in a PictureBox in a constructed gui. I have searching online and even found a very similar post to my question but when trying to implement the guidance I ran into an exception when trying to operate the gui.
A very similar post
Displaying webcam feed in cv::Mat format in a picturebox
Code I grabbed from this post to save you a click:
void DrawCVImage(System::Windows::Forms::Control^ control, cv::Mat& colorImage)
{
System::Drawing::Graphics^ graphics = control->CreateGraphics();
System::IntPtr ptr(colorImage.ptr());
System::Drawing::Bitmap^ b = gcnew System::Drawing::Bitmap(colorImage.cols,colorImage.rows,colorImage.step,System::Drawing::Imaging::PixelFormat::Format24bppRgb,ptr);
System::Drawing::RectangleF rect(0,0,control->Width,control->Height);
graphics->DrawImage(b,rect);
delete graphics;
}
Now I am trying to display a "video" feed (really an array of cv::Mat Objects) but I am having a
"Source Not Available"/System.ArgumentException: 'Parameter is not valid.'
screen come up when I attempt to call the function that houses that playback. I also know specific line of code that throws the issue is the line
System::Drawing::Bitmap^ b = gcnew System::Drawing::Bitmap(colorImage.cols,colorImage.rows,colorImage.step,System::Drawing::Imaging::PixelFormat::Format24bppRgb,ptr);
Now for specifics, the form has an event (currently the click on the picture box, but I want to move to a "play" button in the future) and on this event, the code:
private: System::Void leftEyeImage_Click(System::Object^ sender, System::EventArgs^ e) {
std::cout << "Click Received" << std::endl;
cv::Mat& frame = cv::imread("Desktop/testcapture.png");
std::cout << "Import successful" << std::endl;
drawLeftEye(this, frame);
}
This code does get execute on click and starts the function drawLeftEye. The function is a modified version of the code from the other post and is below:
This is on the ShowResults.cpp file
namespace DevProject {
void ShowResults::drawLeftEye(System::Windows::Forms::Control^ control, cv::Mat& framebmp) {
System::Drawing::Graphics^ graphics = control->CreateGraphics();
std::cout << "Now Here" << std::endl;
System::IntPtr ptr(framebmp.data);
// Issue line
System::Drawing::Bitmap^ b = gcnew System::Drawing::Bitmap(framebmp.cols, framebmp.rows, framebmp.step, System::Drawing::Imaging::PixelFormat::Format32bppRgb, ptr);
std::cout << "Converted successfully" << std::endl;
System::Drawing::RectangleF rect(0, 0, control->Width, control->Height); //No issue
graphics->DrawImage(b, rect);
std::cout << "Now Here before delete" << std::endl;
delete graphics;
//delete b;
}
}
I know based on my cout statements that I do make it into my function and I know my code compiles and runs through the function if I comment out the line:
System::Drawing::Bitmap^ b = gcnew System::Drawing::Bitmap(framebmp.cols, framebmp.rows, framebmp.step, System::Drawing::Imaging::PixelFormat::Format32bppRgb, ptr);
//As well as (but only because b is defined in the line above^
graphics->DrawImage(b, rect);
I am not quite sure how to fix this, my friend mentioned this could be a memory issue but I don't know how I would go about fixing it. It is also very possible I have made a simple mistake in the design of this or where my pointers are going and I am just not competent enough to know the error.
By the way the pointer for "this" that is called in the function is linked to the Windows Autogenerated code (from gui construction) of:
this->leftEyeImage->Anchor = System::Windows::Forms::AnchorStyles::None;
this->leftEyeImage->BorderStyle = System::Windows::Forms::BorderStyle::FixedSingle;
this->leftEyeImage->Location = System::Drawing::Point(11, 836);
this->leftEyeImage->Name = L"leftEyeImage";
this->leftEyeImage->Size = System::Drawing::Size(991, 646);
this->leftEyeImage->TabIndex = 4;
this->leftEyeImage->TabStop = false;
this->leftEyeImage->Click += gcnew System::EventHandler(this, &ShowResults::leftEyeImage_Click);
Any and all advice or tests would be very appreciated as I am both interested in the answer and the reasoning. Thanks in advance!

In GTKMM, on_draw method stops being called after invalidate occurs in separated thread

Using GTKMM, I'm extending the DrawingArea widget with the idea that an external process provides it with images. My CameraDrawingArea will then display the images at the right size using Cairo.
Each time an image arrives, I store it and I call the invalidate method, which eventually ends up in a call to on_draw, where I can resize and display the image.
My problem is the following:
The first 10 or 20 images are displayed as I expected.
After a while, the images keep coming from the provider process, I keep calling invalidate
but on_draw is not called any more.
To show it here, I've simplified the code so that there is nothing external to the class, and no link with other libraries. I've replaced the process providing the images by a method with for-loops, and the display of the image by printing a simple text in the middle of the widget area:
In the constructor I launch a new std::thread to call the doCapture method in the same instance. I also set up a font description, to use it later.
The doCapture method is a silly CPU eater, that does nothing except calling from time to time the refreshDrawing method, as long as keepCapturing is not false.
refreshDrawing invalidates the whole window's rectangle via a call to invalidate.
Gtk's magic is suppose to call on_draw and provide a Cairo context to draw whatever. In my case, for tests purposes, I draw a brownish centered integer.
The class destructor stops the thread by set keepCapturing to false, and waits for termination with a join.
#include "camera-drawing-area.hpp"
#include <iostream>
CameraDrawingArea::CameraDrawingArea():
captureThread(nullptr) {
fontDescription.set_family("Monospace");
fontDescription.set_weight(Pango::WEIGHT_BOLD);
fontDescription.set_size(30 * Pango::SCALE);
keepCapturing = true;
captureThread = new std::thread([this] {
doCapture();
});
}
void CameraDrawingArea::doCapture() {
while (keepCapturing) {
float f = 0.0;
for (int n = 0; n < 1000; n++) {
for (int m = 0; m < 1000; m++) {
for (int o = 0; o < 500; o++) {
f += 1.2;
}
}
}
std::cout << "doCapture - " << f << std::endl;
refreshDrawing();
}
}
void CameraDrawingArea::refreshDrawing() {
auto win = get_window();
if (win) {
win->invalidate(false);
std::cout << "refreshDrawing" << std::endl;
}
}
bool CameraDrawingArea::on_draw(const Cairo::RefPtr<Cairo::Context>& cr) {
std::cout << "on_draw" << std::endl;
static char buffer[50];
static int n = 0;
sprintf(buffer, "-%d-", n++);
Gtk::Allocation allocation = get_allocation();
const int width = allocation.get_width();
const int height = allocation.get_height();
auto layout = create_pango_layout(buffer);
layout->set_font_description(fontDescription);
int textWidth, textHeight;
layout->get_pixel_size(textWidth, textHeight);
cr->set_source_rgb(0.5, 0.2, 0.1);
cr->move_to((width - textWidth) / 2, (height - textHeight) / 2);
layout->show_in_cairo_context(cr);
cr->stroke();
return true;
}
CameraDrawingArea::~CameraDrawingArea() {
keepCapturing = false;
captureThread->join();
free(captureThread);
}
And this is my header file:
#ifndef CAMERA_DRAWING_AREA_HPP
#define CAMERA_DRAWING_AREA_HPP
#include <gtkmm.h>
#include <thread>
class CameraDrawingArea : public Gtk::DrawingArea {
public:
CameraDrawingArea();
virtual ~CameraDrawingArea();
protected:
bool on_draw(const Cairo::RefPtr<Cairo::Context>& cr) override;
private:
bool keepCapturing;
void doCapture();
void refreshDrawing();
std::thread* captureThread;
Pango::FontDescription fontDescription;
};
#endif
The problem manifests itself as follows:
When starting the application, it faithfully displays 1, 2, 3...
Between 5th and 20th iteration (it's random, but rarely outside these ranges), it stops refreshing.
Because of the cout, I can see that refreshDrawing is called be sure that invalidate is also called, but on_draw isn't.
Also, if I stop the application before it stops refreshing, then it ends up nicely. But, if I stop the application after it stops refreshing, then I see this message below (the ID value varies):
GLib-CRITICAL **: 10:05:04.716: Source ID 25 was not found when attempting to remove it
I'm quite sure that I do something wrong, but clueless about what. Any help would be appreciated.
I also checked the following questions, but they don't seem to be related with my case:
Draw signal doesn't get fired in GTKMM, when derived class doesn't call a superclass's constructor
You can't use GTK methods from any other thread than the one in which you started the GTK main loop. Probably the win->invalidate() call is causing things to go wrong here.
Instead, use Glib::Dispatcher to communicate with the main thread, or use gdk_threads_add_idle() for a more C-style solution.
Based on the answer form #ptomato, I've rewritten my example code. The golden rule is do not call GUI functions from another thread, but if you do, then acquire some specific GDK locks first. That's the purpose of Glib::Dispatcher :
If a Glib::Dispatcher object is constructed in the main GUI thread (which will therefore be the receiver thread), any worker thread can emit on it and have the connected slots safely execute gtkmm functions.
Based on that, I've added a new private member Glib::Dispatcher refreshDrawingDispatcher that will allow threads to safely the invalidate the windows area:
#ifndef CAMERA_DRAWING_AREA_HPP
#define CAMERA_DRAWING_AREA_HPP
#include <gtkmm.h>
#include <thread>
class CameraDrawingArea :
public Gtk::DrawingArea {
public:
CameraDrawingArea();
virtual ~CameraDrawingArea();
protected:
bool on_draw(const Cairo::RefPtr<Cairo::Context>& cr) override;
private:
bool keepCapturing;
void doCapture();
void refreshDrawing();
Glib::Dispatcher refreshDrawingDispatcher;
std::thread* captureThread;
Pango::FontDescription fontDescription;
};
#endif
Then, I've connected the dispatcher to the refreshDrawing method. I do this in the class constructor, which is called during GUI start up and therefore in the main GUI thread:
CameraDrawingArea::CameraDrawingArea():
refreshDrawingDispatcher(),
captureThread(nullptr) {
fontDescription.set_family("Monospace");
fontDescription.set_weight(Pango::WEIGHT_BOLD);
fontDescription.set_size(30 * Pango::SCALE);
keepCapturing = true;
captureThread = new std::thread([this] {
doCapture();
});
refreshDrawingDispatcher.connect(sigc::mem_fun(*this, &CameraDrawingArea::refreshDrawing));
}
Finally, the thread has to call the dispatcher:
void CameraDrawingArea::doCapture() {
while (keepCapturing) {
float f = 0.0;
for (int n = 0; n < 1000; n++) {
for (int m = 0; m < 1000; m++) {
for (int o = 0; o < 500; o++) {
f += 1.2;
}
}
}
std::cout << "doCapture - " << f << std::endl;
refreshDrawingDispatcher.emit();
}
}
And now, this works without further problems.

Qt double buffering behaviour

I am converting some code from using QWidget to QOpenGLWidget, I want to use double buffering to render the widget, so far:
void clsElevStrip::initializeGL() {
qDebug() << "clsElevStrip::initializeGL()";
initializeOpenGLFunctions();
//Get the openGL context
mpobjContext = context();
if ( mpobjContext != NULL ) {
//Setup surface
mobjFormat.setDepthBufferSize(24);
mobjFormat.setSamples(4);
mobjFormat.setVersion(3, 0);
mobjFormat.setProfile(QSurfaceFormat::NoProfile);
mobjFormat.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
int intSB = (int)mobjFormat.swapBehavior();
qDebug() << "swapBehavour as set-up in format: " << QString::number(intSB);
mpobjContext->setFormat(mobjFormat);
intSB = (int)mpobjContext->format().swapBehavior();
qDebug() << "swapBehavour as set-up in context: " << QString::number(intSB);
}
}
I can see in the debugger that intSB is 2 when checking swap behaviour from the format, but when I check intSB as set in the context it is 0, not 2?
As a result of this anything I render to the context is visible.
Resolved:
I modified the code, adding
mpobjContext->create();
After:
mpobjContext->setFormat(mobjFormat);
Now it works!

XQueryTree is detecting a window twice

I'm working on a feature in my Qt program where you have the option to store the locations of your application's windows in a profile manner and load that profile later. After some research I found QSettings quite handy and useful for storing UI info like x, y etc. For detecting the windows I decided to use XLib.
I'm very beginner to using Xlib, I found this code which recursively query any open window starting from ":0.0". Inside the foreach loop I did this save function:
int x, y;
int xGeo, yGeo;
int width, height, border, depth;
Display *disp = XOpenDisplay(":0.0");
Window rootWin = XDefaultRootWindow(disp);
QList<Window> windows = listXWindowsRecursive(disp, rootWin);
char* name = NULL;
XWindowAttributes* attributes;
foreach(Window win, windows)
{
attributes = new XWindowAttributes;
// Enumerate through all windows
if(XFetchName(disp, win, &name) && name != NULL)
{
if(strcmp(name, "Secondary Window") == 0)
{
Window child;
qDebug() << (name);
XTranslateCoordinates(disp, win, rootWin, 0, 0, &x, &y, &child);
qDebug() << "XC = " << x << " - " << "YC = " << y;
if(XGetGeometry(disp, win, &rootWin, &xGeo, &yGeo, &width, &height, &border, &depth))
qDebug() << "XGeo= " << x - xGeo << " - " << "YGeo= " << y - yGeo;
settings.setValue("secondaryWindow/x", x - xGeo);
settings.setValue("secondaryWindow/y", y - yGeo);
settings.setValue("secondaryWindow/width", width);
settings.setValue("secondaryWindow/height", height);
if(XGetWindowAttributes(disp, win, attributes))
{
qDebug() << "X = " << x - attributes->x << " - " << "Y = " << y - attributes->y;
}
}
}
}
This portion gets the Qt UI info like X and Y and stores them using QSettings
First thing I'm not sure if what I wrote is the right way to get the X and Y for the window because of these facts. Also I'm not sure if I'm correctly passing the required parameters.
Second thing, this is the load function:
if(settings.contains("secondaryWindow/x") && settings.contains("secondaryWindow/y"))
{
SecondaryWindow* win = new SecondaryWindow;
win->setGeometry(settings.value("secondaryWindow/x").toInt(),
settings.value("secondaryWindow/y").toInt(),
settings.value("secondaryWindow/width").toInt(),
settings.value("secondaryWindow/height").toInt());
win->show();
}
Here is the weird scenario, there is a button that opens the secondary window (using new and show) which works fine. Back to the main window clicking the save function, I get the correct secondary window info.
Now If I closed the secondary window and then clicked the load function, the secondary window opens correctly in the previous position BUT, clicking the save function again here will tell me that there are two "Secondary Window" instances but the second one has X and Y = 0.
By "closing the window" I mean using either the "X" button and using the close() slot. Could it be that the window is not closed correctly? I already implemented the closeEvent handler:
event->accept();
QWidget::closeEvent(event);
Any help is appreciated, Thanks!

QTreeView insertRows via method crushs / direct call works

I have following strange problem.
I've implemented a QAbstractItemModel to the point that I can insert child nodes to the tree view but something strange occurs when I try to add the nodes via the insertRows() method.
First where all is called:
QApplication a(argc, argv);
QResource::registerResource("Qt5Tutorial.rcc");
QTreeView *treeView = new QTreeView();
treeView->show();
Node rootNode("rootNode");
CameraNode childNode0("childNode0", &rootNode);
CameraNode childNode1("childNode1", &rootNode);
LightNode childNode2("childNode2", &rootNode);
CameraNode childNode3("childNode3", &childNode0);
TransformNode childNode4("childNode4", &childNode2);
TransformNode tryNode("potato");
// setup model
ObjectTreeModel model(&rootNode);
treeView->setModel(&model);
// insert directly via the insert child method
// this works!
childNode0.insertChild(1, &tryNode);
// get the QModelIndex of childNode1
// must be passed in the insertRows() method
QModelIndex index(model.index(1, 0, QModelIndex()));
// the output is "childNode1" what is totally right
qDebug() << "index: "<<static_cast<Node*>(index.internalPointer())->getName();
// output see posted beneath
qDebug() << rootNode.log();
// should insert in "childNode1" -> at 0th position and just 1 Node object
// see the method beneath
model.insertRows(0, 1, index);
// if i try to call the method rootNode.log(); now again, it crashes
return a.exec();
This is the output from the rootNode.log() call:
---rootNode
---childNode0
---childNode3
---potato
---childNode1
---childNode2
---childNode4
As you can see the "Potato" Node is correctly inserted.
View an image
http://www10.pic-upload.de/04.01.13/m65huuqq4ruu.png
But once I try to expand the childNode1 node it crashes. But look at the last comment in the code above. As i mentioned -> if i try to output the tree view now (it iterates through all nodes) it crashes.
When the method is called everything seems to be ok - just when i try to expend the tree view it crashes -> the debug output let me think that all should be ok
The actual error message is a access violation when reading at position ... (translated from German - don't know if its called the same in English)
bool ObjectTreeModel::insertRows(int position, int row, const QModelIndex &parent)
{
beginInsertRows(parent, position, position + row - 1);
Node *parentNode = getNode(parent);
qDebug() << "parentName: " << parentNode->getName();
bool success = false;
for(int i = position; i < row; i++)
{
qDebug() << "inside loop";
qDebug() << "position: " << position << "row: " << row;
TransformNode childNode("insertedNode");
success = parentNode->insertChild(i, &childNode);
qDebug() << "success: " << success;
}
endInsertRows();
return success;
}
The debug output for the method above:
getNode: successful
parentName: "childNode1"
inside loop
position: 0 row: 1
called inserchild
success: true
I have no idea why this happens becuase the debug output seems right and it should be basically the same as insert the node directly via the insertChild method.
I hope that someone has an idea why it doesn't work.
Best regards, Michael
Almost everything is correct. Just this two lines not:
TransformNode *childNode = new TransformNode("insertedNode");
success = parentNode->insertChild(i, childNode);