wxDataViewListCtrl and wxVariant Topic is solved

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
refaelsh
Knows some wx things
Knows some wx things
Posts: 29
Joined: Tue Feb 05, 2019 7:25 pm

wxDataViewListCtrl and wxVariant

Post by refaelsh »

I have a simple setup, a wxDataViewListCtrl, the first column uses wxDataViewCustomRenderer and the second column is just text.

Code: Select all

class MyCustomRenderer : public wxDataViewCustomRenderer
I add a line to the wxDataViewListCtrl like this:

Code: Select all

wxVector<wxVariant> item;
item.push_back(wxVariant(/*a raw pointer of MyClass goes here*/));
item.push_back(wxVariant("some string goes here"));
m_data_view_list_ctrl->AppendItem(item);
item.clear();
And this is MyClass:

Code: Select all

class MyClass final : public wxObject
And this is how my SetValue method looks like:

Code: Select all

bool MyCustomRenderer::SetValue(const wxVariant& value)
{
	MyClass* temp = static_cast<MyClass*>(value.GetWxObjectPtr());

	/*Do stuff with temp here...*/

	return true;
}
It worked, now it does not. It fails with the following error:
https://www.dropbox.com/s/acxbzthp3ltad ... s.png?dl=0

The only thing I changed is that I updated my static libs of wxWidgets from 3.0.4 to 3.1.2.
Why has it stopped working? What am I missing here?
Please help me :-)
ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 7459
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Re: wxDataViewListCtrl and wxVariant

Post by ONEEYEMAN »

Hi,
Looking at the SO question: are you populating the data in a thread? Maybe its just a timing issue?

Thank you.
refaelsh
Knows some wx things
Knows some wx things
Posts: 29
Joined: Tue Feb 05, 2019 7:25 pm

Re: wxDataViewListCtrl and wxVariant

Post by refaelsh »

ONEEYEMAN wrote:Hi,
Looking at the SO question: are you populating the data in a thread? Maybe its just a timing issue?

Thank you.
No, I am not populating it in a thread. I am populating it in the wxApp::OnInit method.
ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 7459
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Re: wxDataViewListCtrl and wxVariant

Post by ONEEYEMAN »

Hi,
Where the data is coming from? External device? Internet? File?

Right after you populated the data, is it good?

Thank you.
refaelsh
Knows some wx things
Knows some wx things
Posts: 29
Joined: Tue Feb 05, 2019 7:25 pm

Re: wxDataViewListCtrl and wxVariant

Post by refaelsh »

ONEEYEMAN wrote: Hi,
Where the data is coming from? External device? Internet? File?
Its kinda hard to explain, but a good approximation would be "Internal" and/or "File".
I execute some shell command and parse the output to get the data.
ONEEYEMAN wrote: Right after you populated the data, is it good?
Yes, it does. I've verified it.

Code: Select all

wxVector<wxVariant> item;
for (unsigned int i = 0; i < 400; ++i)
{
	item.push_back(wxVariant(/*Raw pointer to an instance of MyClass*/));
	item.push_back(wxVariant("some string goes here"));
	frame->m_data_view_list_ctrl->AppendItem(item);
	item.clear();
}
The data is good after the loop and in between iterations of the loop.
User avatar
doublemax
Moderator
Moderator
Posts: 19116
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxDataViewListCtrl and wxVariant

Post by doublemax »

Based on the callstack, i would suspect an error in MyCustomRenderer. I guess it's called before the control is filled with data and your code doesn't handle the situation properly.

But it's only a guess.

I don't know why it happened after the switch to 3.1.2.
Use the source, Luke!
ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 7459
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Re: wxDataViewListCtrl and wxVariant

Post by ONEEYEMAN »

Hi,
So this "Raw pointer to an instance of MyClass" is a good pointer and not NULL?

Thank you.
refaelsh
Knows some wx things
Knows some wx things
Posts: 29
Joined: Tue Feb 05, 2019 7:25 pm

Re: wxDataViewListCtrl and wxVariant

Post by refaelsh »

ONEEYEMAN wrote:Hi,
So this "Raw pointer to an instance of MyClass" is a good pointer and not NULL?

Thank you.
Correct.
refaelsh
Knows some wx things
Knows some wx things
Posts: 29
Joined: Tue Feb 05, 2019 7:25 pm

Re: wxDataViewListCtrl and wxVariant

Post by refaelsh »

doublemax wrote:Based on the callstack, i would suspect an error in MyCustomRenderer. I guess it's called before the control is filled with data and your code doesn't handle the situation properly.

But it's only a guess.

I don't know why it happened after the switch to 3.1.2.
Your answer got me thinking. Since I did not change my code, something else must have changed. And now I notice a subtle change in the constructor of `wxDataViewCustomRenderer`.
Here is how I use it in my code:

Code: Select all

MyCustomRenderer::MyCustomRenderer() : wxDataViewCustomRenderer("commit", wxDATAVIEW_CELL_INERT, wxALIGN_CENTER)
They changed the constructor. Especially the first parameter. The documnantation for version 3.0.x says this:
https://docs.wxwidgets.org/3.0/classwx_ ... 89f70af50c
And fot version 3.1.x it says this:
https://docs.wxwidgets.org/3.1/classwx_ ... 350e1e3e6f
Notice the difference in the first parameter of the constructor? Maybe this causes the problem? Maybe I discovered a bug? Should I post it on https://trac.wxwidgets.org?
PB
Part Of The Furniture
Part Of The Furniture
Posts: 4193
Joined: Sun Jan 03, 2010 5:45 pm

Re: wxDataViewListCtrl and wxVariant

Post by PB »

FWIW, the change was made here
https://github.com/wxWidgets/wxWidgets/ ... 42eed7bcf2

I wonder if it makes an actual difference here, since wxDataViewCustomRenderer::GetDefaultType() still returns "string".

TBH, I am not familiar with the class so I have no idea if "commit" was actually a correct value for wxDataViewCustomRenderer's ctor...
refaelsh
Knows some wx things
Knows some wx things
Posts: 29
Joined: Tue Feb 05, 2019 7:25 pm

Re: wxDataViewListCtrl and wxVariant

Post by refaelsh »

PB wrote:FWIW, the change was made here
https://github.com/wxWidgets/wxWidgets/ ... 42eed7bcf2

I wonder if it makes an actual difference here, since wxDataViewCustomRenderer::GetDefaultType() still returns "string".
I agree, it does seems to make no difference.
PB wrote: TBH, I am not familiar with the class so I have no idea if "commit" was actually a correct value for wxDataViewCustomRenderer's ctor...
After I've seen the difference in documentation of this class between v3.0 and v3.1, I also now understand that "commit" was wrong, bit it worked.
I've tried changing it to "string" (after updating to v3.1.2), it did not help.
User avatar
doublemax
Moderator
Moderator
Posts: 19116
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxDataViewListCtrl and wxVariant

Post by doublemax »

Set a breakpoint in MyCustomRenderer::SetValue(), single step through the code and see what happens.
Use the source, Luke!
refaelsh
Knows some wx things
Knows some wx things
Posts: 29
Joined: Tue Feb 05, 2019 7:25 pm

Re: wxDataViewListCtrl and wxVariant

Post by refaelsh »

Here is an mcve (https://stackoverflow.com/help/mcve):

Code: Select all

#include <wx/wxprec.h>
#include <wx/dataview.h>
#include "MyCustomRenderer.h"
#include <wx/wx.h>


class MyApp : public wxApp
{
public:
	virtual bool OnInit();
};

class MyFrame : public wxFrame
{
public:
	MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size);
};

wxIMPLEMENT_APP(MyApp);

bool MyApp::OnInit()
{
	MyFrame* frame = new MyFrame("Hello World", wxPoint(50, 50), wxSize(450, 340));
	frame->Show(true);
	return true;
}

MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size)
	: wxFrame(NULL, wxID_ANY, title, pos, size)
{
	wxDataViewListCtrl* data_view_list_ctrl = new wxDataViewListCtrl(this, wxID_ANY, wxDefaultPosition, wxSize(-1, -1), wxDV_ROW_LINES | wxDV_SINGLE);

	MyCustomRenderer* custom_renderer = new MyCustomRenderer();
	wxDataViewColumn* data_view_column = new wxDataViewColumn("Some title goes here", custom_renderer,0);
	data_view_list_ctrl->AppendColumn(data_view_column);
	data_view_list_ctrl->AppendTextColumn("Some cool column title goes here");

	wxVector<wxVariant> data;
	data.push_back(wxVariant(42));
	data.push_back(wxVariant("row 1"));
	data_view_list_ctrl->AppendItem(data);

	data.clear();
	data.push_back(wxVariant(43));
	data.push_back(wxVariant("row 3"));
	data_view_list_ctrl->AppendItem(data);
}
And here is the `MyCustomRenderer` class:

Code: Select all

#include "MyCustomRenderer.h"
#include <wx/wx.h>


MyCustomRenderer::MyCustomRenderer() : wxDataViewCustomRenderer("string", wxDATAVIEW_CELL_INERT, wxALIGN_CENTER)
{
}

bool MyCustomRenderer::SetValue(const wxVariant& value)
{
	if (value.IsNull() == true)
	{
		return false;
	}

	return true;
}

bool MyCustomRenderer::GetValue(wxVariant& value) const
{
	return true;
}

wxSize MyCustomRenderer::GetSize() const
{
	return wxSize(42, 42);
}

bool MyCustomRenderer::Render(wxRect cell, wxDC* dc, int state)
{
	// Do lots of stuff here ...	

	return true;
}
All of the above works on 3.0.4 but not in 3.1.2.
The `return true` statement in `MyCustomRenderer::SetValue` is never hit.
I think its a bug in 3.1.2. What do you think guys?
refaelsh
Knows some wx things
Knows some wx things
Posts: 29
Joined: Tue Feb 05, 2019 7:25 pm

Re: wxDataViewListCtrl and wxVariant

Post by refaelsh »

doublemax wrote:Set a breakpoint in MyCustomRenderer::SetValue(), single step through the code and see what happens.
I tried it, `value.IsNull()` is always true.
User avatar
doublemax
Moderator
Moderator
Posts: 19116
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxDataViewListCtrl and wxVariant

Post by doublemax »

When does it crash? Directly at the start?

I tested with this code and it worked fine:

Code: Select all

#include <wx/wxprec.h>
#include <wx/dataview.h>
#include <wx/wx.h>

class MyCustomRenderer : public wxDataViewCustomRenderer
{
public:

  MyCustomRenderer(const wxString &varianttype = "string", wxDataViewCellMode mode = wxDATAVIEW_CELL_INERT, int align = wxDVR_DEFAULT_ALIGNMENT )
    :wxDataViewCustomRenderer(varianttype, mode, align )
  {
  };

  bool SetValue(const wxVariant& value)
  {
     if (value.IsNull() == true)
     {
        return false;
     }

     return true;
  }

  bool GetValue(wxVariant& value) const
  {
     return true;
  }

  wxSize GetSize() const
  {
     return wxSize(42, 42);
  }

  bool Render(wxRect cell, wxDC* dc, int state)
  {
     // Do lots of stuff here ...   

     return true;
  }
};


class MyApp : public wxApp
{
public:
   virtual bool OnInit();
};

class MyFrame : public wxFrame
{
public:
   MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size);
};

wxIMPLEMENT_APP(MyApp);

bool MyApp::OnInit()
{
   MyFrame* frame = new MyFrame("Hello World", wxPoint(50, 50), wxSize(450, 340));
   frame->Show(true);
   return true;
}

MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size)
   : wxFrame(NULL, wxID_ANY, title, pos, size)
{
   wxDataViewListCtrl* data_view_list_ctrl = new wxDataViewListCtrl(this, wxID_ANY, wxDefaultPosition, wxSize(-1, -1), wxDV_ROW_LINES | wxDV_SINGLE);

   MyCustomRenderer* custom_renderer = new MyCustomRenderer();
   wxDataViewColumn* data_view_column = new wxDataViewColumn("Some title goes here", custom_renderer,0);
   data_view_list_ctrl->AppendColumn(data_view_column);
   data_view_list_ctrl->AppendTextColumn("Some cool column title goes here");

   wxVector<wxVariant> data;
   data.push_back(wxVariant(42));
   data.push_back(wxVariant("row 1"));
   data_view_list_ctrl->AppendItem(data);

   data.clear();
   data.push_back(wxVariant(43));
   data.push_back(wxVariant("row 3"));
   data_view_list_ctrl->AppendItem(data);
}
Use the source, Luke!
Post Reply