Gtkmm:创建一个 Gtk::ComboBox,其中列出 Gtk::DrawingArea
Gtkmm: create a Gtk::ComboBox which lists Gtk::DrawingArea
我正在尝试创建一个 Gtk::ComboBox
列表 Gtk::DrawingArea
小部件。我关注了this tutorial。到目前为止,这是 Gtkmm3 的最小工作示例(即可用于重现问题):
#include <gtkmm.h>
class NewPlayerRow : public Gtk::ListBoxRow
{
public:
NewPlayerRow();
private:
// Model for the combobox row: a disc with the appropriate player color...
struct NewPlayerDiscColorComboRowModel : public Gtk::TreeModel::ColumnRecord
{
NewPlayerDiscColorComboRowModel()
{
add(m_discColorIcon);
}
Gtk::TreeModelColumn<Gtk::DrawingArea> m_discColorIcon;
};
NewPlayerDiscColorComboRowModel m_comboRowModel;
Glib::RefPtr<Gtk::ListStore> m_listStore;
Gtk::ComboBox m_comboBox;
};
NewPlayerRow::NewPlayerRow()
{
// First, create and register the TreeModel:
m_listStore = Gtk::ListStore::create(m_comboRowModel);
m_comboBox.set_model(m_listStore);
// Then, populate the TreeModel:
Gtk::TreeModel::Row row = *(m_listStore->append());
row[m_comboRowModel.m_discColorIcon] = Gtk::DrawingArea();
row = *(m_listStore->append());
row[m_comboRowModel.m_discColorIcon] = Gtk::DrawingArea();
// Add the model columns to the Combo:
m_comboBox.pack_start(m_comboRowModel.m_discColorIcon);
add(m_comboBox);
}
int main(int argc, char** argv)
{
Glib::RefPtr<Gtk::Application> app{Gtk::Application::create(argc, argv, "com.github.bobmorane22.connectx")};
NewPlayerRow np;
Gtk::Window w;
w.add(np);
w.show_all();
return app->run(w);
}
当我编译它时,出现以下错误:
In file included from /usr/include/glibmm-2.4/glibmm/value.h:196:0,
from /usr/include/glibmm-2.4/glibmm/propertyproxy_base.h:25,
from /usr/include/glibmm-2.4/glibmm/propertyproxy.h:25,
from /usr/include/glibmm-2.4/glibmm/objectbase.h:24,
from /usr/include/glibmm-2.4/glibmm/object.h:29,
from /usr/include/pangomm-1.4/pangomm/context.h:32,
from /usr/include/gtkmm-3.0/gtkmm/widget.h:32,
from /usr/include/gtkmm-3.0/gtkmm/actiongroup.h:29,
from /usr/include/gtkmm-3.0/gtkmm/application.h:32,
from src/main.cpp:32:
/usr/include/glibmm-2.4/glibmm/value_custom.h: In instantiation of ‘static void Glib::Value<T>::value_copy_func(const GValue*, GValue*) [with T = Gtk::DrawingArea; GValue = _GValue]’:
/usr/include/glibmm-2.4/glibmm/value_custom.h:257:9: required from ‘static GType Glib::Value<T>::value_type() [with T = Gtk::DrawingArea; GType = long unsigned int]’
/usr/include/gtkmm-3.0/gtkmm/treemodelcolumn.h:134:64: required from ‘Gtk::TreeModelColumn<T>::TreeModelColumn() [with T = Gtk::DrawingArea]’
src/main.cpp:50:9: required from here
/usr/include/glibmm-2.4/glibmm/value_custom.h:283:33: error: use of deleted function ‘Gtk::DrawingArea::DrawingArea(const Gtk::DrawingArea&)’
dest_value->data[0].v_pointer = new(std::nothrow) T(source);
^
In file included from /home/morane/Programming/cpp/ConnectX/cxgui/include/GeometricShape.h:35:0,
from /home/morane/Programming/cpp/ConnectX/cxgui/include/Disc.h:35,
from src/../include/../include/CXDisc.h:35,
from src/../include/../include/GBDisc.h:37,
from src/../include/GameBoard.h:41,
from src/../include/GameWindow.h:17,
from src/main.cpp:34:
/usr/include/gtkmm-3.0/gtkmm/drawingarea.h:64:3: note: declared here
DrawingArea(const DrawingArea&) = delete;
这似乎表明组合框行模型中的类型必须是可复制的才能工作。我已经尝试在上面的代码中将类型 Gtk::DrawingArea
替换为 std::string
(可复制)并且它构建良好并且运行良好。我可以看到带有文本行的组合框。
有办法解决这个问题吗?我真的很想创建一个列出绘图区域的组合框。
EDIT 深入研究错误,我发现问题出在 Glibmm 中的文件 value_custom.h
中。以下两个函数似乎解决了这个问题,因为它们试图访问模板化类型的复制成员操作(在我的例子中 Gtk::DrawingArea
,如上所述,它是不可复制的)。
// static
template <class T>
GType Value<T>::value_type()
{
if(!custom_type_)
{
custom_type_ = Glib::custom_boxed_type_register(
typeid(CppType).name(),
&Value<T>::value_init_func,
&Value<T>::value_free_func,
&Value<T>::value_copy_func);
}
return custom_type_;
}
// static
template <class T>
void Value<T>::value_copy_func(const GValue* src_value, GValue* dest_value)
{
// Assume the source is not NULL. See value_init_func().
const T& source = *static_cast<T*>(src_value->data[0].v_pointer);
dest_value->data[0].v_pointer = new(std::nothrow) T(source);
}
我开始觉得没有办法解决这个问题...Glib::Value<T>
的 documentation 甚至提到类型 T
必须实现复制 assignment/construction.
如果你有想法,我洗耳恭听。
经过更多的研究,我得出的结论是 Gtk::ComboBox
es 根本不是为了容纳小部件而设计的(因此 Gtk::DrawingArea
s),因为它在其 TreeModel
,其中 T
需要可复制。
换句话说,构成组合框模型的类型(即当您单击它时它实际列出的类型)必须是可复制的,否则框架将不允许您的代码编译。
起初,无法复制小部件这一事实对我来说毫无意义,但经过一番研究,我发现 this article,这清楚地解释了一些(棘手的)问题,当使用可复制的小部件。
总而言之,我似乎正在努力完成一些事情,但回想起来,这在 UI 方面有点奇怪,我将尝试找到一些更简洁的方式来表达我的意图。
我正在尝试创建一个 Gtk::ComboBox
列表 Gtk::DrawingArea
小部件。我关注了this tutorial。到目前为止,这是 Gtkmm3 的最小工作示例(即可用于重现问题):
#include <gtkmm.h>
class NewPlayerRow : public Gtk::ListBoxRow
{
public:
NewPlayerRow();
private:
// Model for the combobox row: a disc with the appropriate player color...
struct NewPlayerDiscColorComboRowModel : public Gtk::TreeModel::ColumnRecord
{
NewPlayerDiscColorComboRowModel()
{
add(m_discColorIcon);
}
Gtk::TreeModelColumn<Gtk::DrawingArea> m_discColorIcon;
};
NewPlayerDiscColorComboRowModel m_comboRowModel;
Glib::RefPtr<Gtk::ListStore> m_listStore;
Gtk::ComboBox m_comboBox;
};
NewPlayerRow::NewPlayerRow()
{
// First, create and register the TreeModel:
m_listStore = Gtk::ListStore::create(m_comboRowModel);
m_comboBox.set_model(m_listStore);
// Then, populate the TreeModel:
Gtk::TreeModel::Row row = *(m_listStore->append());
row[m_comboRowModel.m_discColorIcon] = Gtk::DrawingArea();
row = *(m_listStore->append());
row[m_comboRowModel.m_discColorIcon] = Gtk::DrawingArea();
// Add the model columns to the Combo:
m_comboBox.pack_start(m_comboRowModel.m_discColorIcon);
add(m_comboBox);
}
int main(int argc, char** argv)
{
Glib::RefPtr<Gtk::Application> app{Gtk::Application::create(argc, argv, "com.github.bobmorane22.connectx")};
NewPlayerRow np;
Gtk::Window w;
w.add(np);
w.show_all();
return app->run(w);
}
当我编译它时,出现以下错误:
In file included from /usr/include/glibmm-2.4/glibmm/value.h:196:0,
from /usr/include/glibmm-2.4/glibmm/propertyproxy_base.h:25,
from /usr/include/glibmm-2.4/glibmm/propertyproxy.h:25,
from /usr/include/glibmm-2.4/glibmm/objectbase.h:24,
from /usr/include/glibmm-2.4/glibmm/object.h:29,
from /usr/include/pangomm-1.4/pangomm/context.h:32,
from /usr/include/gtkmm-3.0/gtkmm/widget.h:32,
from /usr/include/gtkmm-3.0/gtkmm/actiongroup.h:29,
from /usr/include/gtkmm-3.0/gtkmm/application.h:32,
from src/main.cpp:32:
/usr/include/glibmm-2.4/glibmm/value_custom.h: In instantiation of ‘static void Glib::Value<T>::value_copy_func(const GValue*, GValue*) [with T = Gtk::DrawingArea; GValue = _GValue]’:
/usr/include/glibmm-2.4/glibmm/value_custom.h:257:9: required from ‘static GType Glib::Value<T>::value_type() [with T = Gtk::DrawingArea; GType = long unsigned int]’
/usr/include/gtkmm-3.0/gtkmm/treemodelcolumn.h:134:64: required from ‘Gtk::TreeModelColumn<T>::TreeModelColumn() [with T = Gtk::DrawingArea]’
src/main.cpp:50:9: required from here
/usr/include/glibmm-2.4/glibmm/value_custom.h:283:33: error: use of deleted function ‘Gtk::DrawingArea::DrawingArea(const Gtk::DrawingArea&)’
dest_value->data[0].v_pointer = new(std::nothrow) T(source);
^
In file included from /home/morane/Programming/cpp/ConnectX/cxgui/include/GeometricShape.h:35:0,
from /home/morane/Programming/cpp/ConnectX/cxgui/include/Disc.h:35,
from src/../include/../include/CXDisc.h:35,
from src/../include/../include/GBDisc.h:37,
from src/../include/GameBoard.h:41,
from src/../include/GameWindow.h:17,
from src/main.cpp:34:
/usr/include/gtkmm-3.0/gtkmm/drawingarea.h:64:3: note: declared here
DrawingArea(const DrawingArea&) = delete;
这似乎表明组合框行模型中的类型必须是可复制的才能工作。我已经尝试在上面的代码中将类型 Gtk::DrawingArea
替换为 std::string
(可复制)并且它构建良好并且运行良好。我可以看到带有文本行的组合框。
有办法解决这个问题吗?我真的很想创建一个列出绘图区域的组合框。
EDIT 深入研究错误,我发现问题出在 Glibmm 中的文件 value_custom.h
中。以下两个函数似乎解决了这个问题,因为它们试图访问模板化类型的复制成员操作(在我的例子中 Gtk::DrawingArea
,如上所述,它是不可复制的)。
// static
template <class T>
GType Value<T>::value_type()
{
if(!custom_type_)
{
custom_type_ = Glib::custom_boxed_type_register(
typeid(CppType).name(),
&Value<T>::value_init_func,
&Value<T>::value_free_func,
&Value<T>::value_copy_func);
}
return custom_type_;
}
// static
template <class T>
void Value<T>::value_copy_func(const GValue* src_value, GValue* dest_value)
{
// Assume the source is not NULL. See value_init_func().
const T& source = *static_cast<T*>(src_value->data[0].v_pointer);
dest_value->data[0].v_pointer = new(std::nothrow) T(source);
}
我开始觉得没有办法解决这个问题...Glib::Value<T>
的 documentation 甚至提到类型 T
必须实现复制 assignment/construction.
如果你有想法,我洗耳恭听。
经过更多的研究,我得出的结论是 Gtk::ComboBox
es 根本不是为了容纳小部件而设计的(因此 Gtk::DrawingArea
s),因为它在其 TreeModel
,其中 T
需要可复制。
换句话说,构成组合框模型的类型(即当您单击它时它实际列出的类型)必须是可复制的,否则框架将不允许您的代码编译。
起初,无法复制小部件这一事实对我来说毫无意义,但经过一番研究,我发现 this article,这清楚地解释了一些(棘手的)问题,当使用可复制的小部件。
总而言之,我似乎正在努力完成一些事情,但回想起来,这在 UI 方面有点奇怪,我将尝试找到一些更简洁的方式来表达我的意图。