1

我正在尝试创建一个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.hGlibmm 中的文件。以下两个函数似乎解决了这个问题,因为它们尝试访问模板类型的复制成员操作(在我的例子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必须实现复制分配/构造。

如果你有一个想法,我会全力以赴。

4

1 回答 1

0

经过更多研究,我得出的结论是Gtk::ComboBoxes 根本不是为了容纳小部件(因此Gtk::DrawingAreas)而设计的,因为Gtk::TreeModelColumn<T>它在其中使用 a TreeModelT需要可复制。

换句话说,构成组合框模型的类型(即单击它时实际列出的类型)必须是可复制的,否则框架不会让您的代码编译。

起初,无法复制小部件这一事实对我来说毫无意义,但经过一番研究,我发现了这篇文章,它清楚地解释了使用可复制小部件时可能面临的一些(棘手的)问题。

总之,我似乎正在努力完成一些事情,回想起来,无论如何,在 UI 方面有点奇怪,我会尝试找到一些更简洁的方式来表达我的意图。

于 2018-08-03T13:19:01.187 回答