我正在编写一个gtkmm-4应用程序,并希望在GtkBuilder XML中使用自定义小部件。如果小部件是由C++构造的,那么它可以正常工作。但是,当使用XML构造时,它不会呈现。
注意:这个问题可能被认为是 的重复。我并不是要在我的小部件中使用Glade;我的小部件只是不适用于普通的手写XML.。
我很抱歉发布了这么多代码,但我相信这是我所能得到的最低限度的代码。
自定义小部件代码
#ifndef _TASDI2_JOYSTICK_HPP_
#define _TASDI2_JOYSTICK_HPP_
#include <gtkmm.h>
namespace tasdi2 {
class Joystick : public Gtk::Widget {
public:
Joystick();
virtual ~Joystick() {}
virtual Gtk::SizeRequestMode get_request_mode_vfunc() const override {
return Gtk::Widget::get_request_mode_vfunc();
}
virtual void measure_vfunc(
Gtk::Orientation orientation, int for_size, int& minimum, int& natural,
int& minimum_baseline, int& natural_baseline) const override;
void on_map() override;
void on_unmap() override;
void snapshot_vfunc(const Glib::RefPtr<Gtk::Snapshot> &snapshot) override;
Glib::PropertyProxy<int> property_xpos() {
return prop_xpos.get_proxy();
}
Glib::PropertyProxy_ReadOnly<int> property_xpos() const {
return prop_xpos.get_proxy();
}
Glib::PropertyProxy<int> property_ypos() {
return prop_ypos.get_proxy();
}
Glib::PropertyProxy_ReadOnly<int> property_ypos() const {
return prop_ypos.get_proxy();
}
private:
Glib::Property<int> prop_xpos;
Glib::Property<int> prop_ypos;
};
} // namespace tasdi2
#endif#include "joystick.hpp"
#include <gdkmm.h>
#include <gtkmm.h>
#include <iostream>
#include <numbers>
namespace {
inline void circle(
const Glib::RefPtr<Cairo::Context>& cairo, double cx, double cy, double r) {
cairo->arc(cx, cy, r, 0, 2 * std::numbers::pi);
}
inline void line(
const Glib::RefPtr<Cairo::Context>& cairo, double x1, double y1, double x2,
double y2) {
cairo->move_to(x1, y1);
cairo->line_to(x2, y2);
}
} // namespace
namespace tasdi2 {
Joystick::Joystick() :
Glib::ObjectBase("Tasdi2Joystick"),
Gtk::Widget(),
prop_xpos(*this, "xpos", 0),
prop_ypos(*this, "ypos", 0) {
set_hexpand();
set_hexpand_set();
set_vexpand();
set_vexpand_set();
}
void Joystick::measure_vfunc(
Gtk::Orientation orientation, int for_size, int& minimum, int& natural,
int& minimum_baseline, int& natural_baseline) const {
minimum = 128;
natural = 160;
minimum_baseline = -1;
natural_baseline = -1;
return;
}
void Joystick::on_map() { Gtk::Widget::on_map(); }
void Joystick::on_unmap() { Gtk::Widget::on_unmap(); }
void Joystick::snapshot_vfunc(const Glib::RefPtr<Gtk::Snapshot>& snapshot) {
const auto space = get_allocation();
const Gdk::Rectangle rect(0, 0, space.get_width(), space.get_height());
std::cout << "Allocation area: " << space.get_x() << ", " << space.get_y() << ", " << space.get_width() << ", " << space.get_height() << "\n";
auto cairo = snapshot->append_cairo(rect);
const double w = space.get_width();
const double h = space.get_height();
const double cx = w / 2;
const double cy = h / 2;
// colors
const Gdk::RGBA color_bg0("#7F7F7F");
const Gdk::RGBA color_bg1("#FFFFFF");
const Gdk::RGBA color_oln("#000000");
const Gdk::RGBA color_cln("#0000FF");
const Gdk::RGBA color_dot("#FF0000");
cairo->rectangle(0, 0, w, h);
Gdk::Cairo::set_source_rgba(cairo, color_bg0);
cairo->fill();
circle(cairo, cx, cy, cx);
Gdk::Cairo::set_source_rgba(cairo, color_bg1);
cairo->fill_preserve();
line(cairo, cx, 0, cx, h);
line(cairo, 0, cy, w, cy);
Gdk::Cairo::set_source_rgba(cairo, color_oln);
cairo->stroke();
}
} // namespace tasdi2MVE测试代码
#include <gtkmm.h>
#include "joystick.hpp"
static const std::string ui_data = R"(
<interface>
<object class="GtkAspectFrame" id="root">
<property name="margin-start">10</property>
<property name="margin-end">10</property>
<property name="margin-top">10</property>
<property name="margin-bottom">10</property>
<child>
<object class="gtkmm__CustomObject_Tasdi2Joystick" />
</child>
</object>
</interface>
)";
class MainWindow : public Gtk::Window {
public:
MainWindow() :
builder(Gtk::Builder::create_from_string(ui_data)) {
set_child(*builder->get_widget<Gtk::AspectFrame>("root"));
set_size_request(256, 256);
}
protected:
Glib::RefPtr<Gtk::Builder> builder;
};
int main(int argc, char* argv[]) {
auto app = Gtk::Application::create("io.github.jgcodes2020.testapp");
app->signal_startup().connect([&]() {
tasdi2::Joystick joystick;
});
return app->make_window_and_run<MainWindow>(argc, argv);
}

#include <gtkmm.h>
#include "joystick.hpp"
static const std::string ui_data = R"(
<interface>
<object class="GtkAspectFrame" id="root">
<property name="margin-start">10</property>
<property name="margin-end">10</property>
<property name="margin-top">10</property>
<property name="margin-bottom">10</property>
</object>
</interface>
)";
class MainWindow : public Gtk::Window {
public:
MainWindow() :
builder(Gtk::Builder::create_from_string(ui_data)) {
auto& root = *builder->get_widget<Gtk::AspectFrame>("root");
root.set_child(stick);
set_child(root);
set_size_request(256, 256);
}
protected:
Glib::RefPtr<Gtk::Builder> builder;
tasdi2::Joystick stick;
};
int main(int argc, char* argv[]) {
auto app = Gtk::Application::create("io.github.jgcodes2020.testapp");
return app->make_window_and_run<MainWindow>(argc, argv);
}

发布于 2022-05-09 00:58:12
使用上面关于包含派生小部件的注释,我查看了Gnome developer站点上的示例代码,并查看了您的"Joystick“小部件的类构造函数。我没有使用标准构造函数,因为它对于直接构建在代码中的任何小部件都是有用的。然后,使用开发人员站点上的派生小部件示例,将"joystick.hpp“头文件修改为包含构建器构造器原型,如下所示。
Joystick();
Joystick(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>& refGlade); /* New builder function for a derived widget */
virtual ~Joystick() {}然后,在文件"tasdi2“中的"joystick.cpp”命名空间中,我添加了派生的构建器构造函数,基本上是在"Joystick“类的标准构造函数中克隆细节。
Joystick::Joystick(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>& /* refGlade */)
: // To register custom properties, you must register a custom GType. If
// you don't know what that means, don't worry, just remember to add
// this Glib::ObjectBase constructor call to your class' constructor.
// The GType name will be gtkmm__CustomObject_Tasdi2Joystick.
Glib::ObjectBase("Tasdi2Joystick"),
Gtk::Widget(cobject),
prop_xpos(*this, "xpos", 0),
prop_ypos(*this, "ypos", 0)
{
set_hexpand();
set_hexpand_set();
set_vexpand();
set_vexpand_set();
}最后,在"main.cpp“的"XML”版本中,我修改了代码以适应派生的小部件。在XML文本正文中,我添加了一个"ID“属性,以便在程序的后面调用派生的构建器函数时有一个小部件的挂钩。
<object class="gtkmm__CustomObject_Tasdi2Joystick" id="stick_range"/>在添加"ID“属性的同时,我还在"MainWindow”构造函数中包含了自定义操纵杆小部件的构建。
MainWindow() :
builder(Gtk::Builder::create_from_string(ui_data)) {
set_child(*builder->get_widget<Gtk::AspectFrame>("root"));
set_size_request(256, 256);
tasdi2::Joystick * stick_range = nullptr;
stick_range = Gtk::Builder::get_widget_derived<tasdi2::Joystick>(builder, "stick_range");
if (stick_range == nullptr)
printf("Joystick widget definition was not found\n");
}将"XML“版本的"main.cpp”与其他更改组合在一起的净结果显示了小部件。

您可能已经从前面的注释中了解到了这些内容,但是如果没有,这些附加的代码段可能对您有帮助。
致以问候。
https://stackoverflow.com/questions/72157547
复制相似问题