wxPropertyGrid::ChangePropertyValue not work 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.
Post Reply
Ronald
Earned some good credits
Earned some good credits
Posts: 105
Joined: Mon Mar 05, 2018 4:17 am

wxPropertyGrid::ChangePropertyValue not work

Post by Ronald » Fri Sep 13, 2019 12:31 pm

demo in attachment
It's a VS2019 solution, easy to migrate.
ShowBug.VS2019.7z
(3.91 KiB) Downloaded 1 time
main code

Code: Select all

#include "pch.h"
#include "BuggyPropGrid.h"

BEGIN_EVENT_TABLE(BuggyPropGrid, wxPropertyGrid)
EVT_PG_CHANGED(wxID_ANY, BuggyPropGrid::OnPropChanged)
EVT_PG_DOUBLE_CLICK(wxID_ANY, BuggyPropGrid::OnPGDClick)
END_EVENT_TABLE()

BuggyPropGrid::BuggyPropGrid(wxWindow * parent,
                                   wxWindowID id,
                                   const wxPoint & pos,
                                   const wxSize & size,
                                   long style,
                                   const wxString & name) :
    wxPropertyGrid(parent, id, pos, size, style, name)
{
    Init();
}

void BuggyPropGrid::Init()
{
    _pProp_0 = new wxStringProperty(L"Prop_0");
    _pProp_0->SetValue(5);
    Append(_pProp_0);

    _pProp_1 = new wxStringProperty(L"Prop_1");
    Append(_pProp_1);

    _pProp_2 = new wxStringProperty(L"Prop_2");
    Append(_pProp_2);

    FitColumns();
    
    SetSize(250, 200);
}

void BuggyPropGrid::OnPropChanged(wxPropertyGridEvent & event)
{
    wxPGProperty * pProp = event.GetProperty();
    if (pProp == _pProp_1)
    {
        wxString s = _pProp_1->GetValueAsString();
        double n;
        if (s.ToDouble(&n))
        {
            n *= 2;
            bool ok = ChangePropertyValue(_pProp_2, n); // This line will be executed and return true, but UI doesn't change.
                                                        // wxPropertyGrid::SetPropertyValue works
                                                        // wxPGProperty::SetValue  works
                                                        // But these two doesn't emit change event
            wxASSERT(ok);
        }
    }
}

void BuggyPropGrid::OnPGDClick(wxPropertyGridEvent & event)
{
    unsigned int col = event.GetColumn();
    if (col == 1)
    {
        wxPGProperty * pProp = event.GetProperty();
        if (pProp == _pProp_0)
        {
            ChangePropertyValue(_pProp_1, _pProp_0->GetValue());
        }
    }
}

User avatar
doublemax
Moderator
Moderator
Posts: 13985
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxPropertyGrid::ChangePropertyValue not work

Post by doublemax » Sat Sep 14, 2019 9:15 am

This looks like a bug indeed. It works if you use CallAfter for the inner method call:

Code: Select all

if (s.ToDouble(&n))
{
    n *= 2;
    CallAfter([=] {
      bool ok = ChangePropertyValue(_pProp_2, n ); // This line will be executed and return true, but UI doesn't change.
                                                  // wxPropertyGrid::SetPropertyValue works
                                                  // wxPGProperty::SetValue  works
                                                  // But these two doesn't emit change event
      wxASSERT(ok);
    });
}
The problem occurs if you make a ChangePropertyValue call from inside a EVT_PG_CHANGED event handler. I traced through the code a bit and it seems it uses a single m_inDoPropertyChanged flag to remember if the value has already been changed. This is set by the first ChangePropertyValue call and when the second ChangePropertyValue happens, the value will not be updated because this flag is still true.
Use the source, Luke!

Ronald
Earned some good credits
Earned some good credits
Posts: 105
Joined: Mon Mar 05, 2018 4:17 am

Re: wxPropertyGrid::ChangePropertyValue not work

Post by Ronald » Sat Sep 14, 2019 11:29 am

doublemax wrote:
Sat Sep 14, 2019 9:15 am
This looks like a bug indeed. It works if you use CallAfter for the inner method call:

Code: Select all

if (s.ToDouble(&n))
{
    n *= 2;
    CallAfter([=] {
      bool ok = ChangePropertyValue(_pProp_2, n ); // This line will be executed and return true, but UI doesn't change.
                                                  // wxPropertyGrid::SetPropertyValue works
                                                  // wxPGProperty::SetValue  works
                                                  // But these two doesn't emit change event
      wxASSERT(ok);
    });
}
The problem occurs if you make a ChangePropertyValue call from inside a EVT_PG_CHANGED event handler. I traced through the code a bit and it seems it uses a single m_inDoPropertyChanged flag to remember if the value has already been changed. This is set by the first ChangePropertyValue call and when the second ChangePropertyValue happens, the value will not be updated because this flag is still true.
Yes, I think so, a little complicated.
Thank you very much.
I think I should debug it myself, but my hard disk is not so large now, the wx source code is on another machine, I must buy a large harddisk for open source :)

User avatar
doublemax
Moderator
Moderator
Posts: 13985
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxPropertyGrid::ChangePropertyValue not work

Post by doublemax » Sat Sep 14, 2019 6:37 pm

Are you going to open a ticket for this?
Use the source, Luke!

Ronald
Earned some good credits
Earned some good credits
Posts: 105
Joined: Mon Mar 05, 2018 4:17 am

Re: wxPropertyGrid::ChangePropertyValue not work

Post by Ronald » Sun Sep 15, 2019 12:45 am

doublemax wrote:
Sat Sep 14, 2019 6:37 pm
Are you going to open a ticket for this?
OK, to see how fast it will be fixed.
Only if it is not fast enough, or I'll try to do a Pull Request, then I'll really open the source :mrgreen:

Post Reply