Gtkmm: создайте Gtk::ComboBox, который перечисляет Gtk::DrawingArea
Я пытаюсь создать Gtk::ComboBox
список Gtk::DrawingArea
виджеты. Я следовал этому уроку. Итак, вот минимальный рабочий пример (то есть, который можно использовать для воспроизведения проблемы) с 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
(который может быть скопирован) в приведенном выше коде, и он прекрасно работает и работает нормально. Я вижу поле со списком с текстовыми строками.
Это можно обойти? Я действительно хотел бы создать поле со списком, в котором перечислены области рисования.
РЕДАКТИРОВАТЬ Погружаясь немного глубже в ошибку, я обнаружил, что проблема исходит из файла 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>
даже упоминает, что тип T
должен реализовать назначение копирования / строительство.
Если у вас есть идея, я весь слух.
1 ответ
После дополнительных исследований я пришел к выводу, что Gtk::ComboBox
Они просто не предназначены для хранения виджетов (следовательно, Gtk::DrawingArea
s) потому что использует Gtk::TreeModelColumn<T>
в его TreeModel
, где T
должен быть копируемым.
Другими словами, типы, которые составляют вашу модель комбинированного списка (то есть типы того, что она на самом деле перечисляет, когда вы щелкаете по ней), должны быть копируемыми, иначе среда не позволит компилировать ваш код.
Сначала тот факт, что виджеты не могли быть скопированы, не имел для меня никакого смысла, но после некоторого исследования я нашел эту статью, в которой четко объясняются некоторые (сложные) проблемы, с которыми можно столкнуться при использовании копируемых виджетов.
В заключение, мне кажется, что я пытаюсь сделать что-то, что в ретроспективе было бы немного странно с точки зрения пользовательского интерфейса, и я попытаюсь найти какой-то более чистый способ выразить свое намерение.