Gtkmm: Using RefPtr with widgets kept in std::vect

2019-07-15 11:27发布

问题:

I am trying to keep a std::vector of Gtk::Widgets that I am showing (and will potentially be) moving around between Gtk::Containers.

At the moment I keep a Gtk::Notebook which is basically a one-to-one map to the std::vector, but if I use Glib::RefPtr around the widgets I get problems when removing the widget from the notebook. I already have to use a 'hack' to get a pointer to the underlying Gtk object when adding it to the notebook and I suspect that the Notebook container frees/deletes the object when I remove it from the container.

I have defined my vector of widgets something like this: std::vector<Glib::RefPtr<Gtk::Widget>> widgets;

When I add a widget to the vector and the notebook I do:

Glib::RefPtr<Gtk::Widget> w (new Gtk::Widget());
widgets.push_back (w);
Gtk::Widget *wptr = w.operator->(); // hack
notebook.append_page (*wptr);

when I try to remove it I do:

int c = 1; // widget no. to remove
notebook.remove_page (c);
auto it = widgets.begin() + c;
widgets.erase (it);

but this results in a G_IS_OBJECT fail assertion when (I think) the element in the std::vector is cleaned up at the end of the iterator (end of function), since possibly notebook.remove_page() already freed the object. How can I do this? Is it possible with RefPtr's?

Related (same assertion failure): Destructing Glib::RefPtr causes failed assertions in the GTK 3 core

回答1:

Unfortunately you can't do this because the Gtk::Notebook takes ownership of the child objects. You have to refactor your code to use the Gtk::Notebook itself to access the widgets instead of the vector, for example with Gtk::Notebook::get_nth_page().



回答2:

Glib::RefPtr<> should not be used with widgets. It is not a general purpose smartpointer. It should only be used with classes that force you to use it - by having no public constructor but having public create*() methods.