I am working on a simple example of a GUI application written in C++ using gtkmm (version 3.24) and an external XML file.
Thanks to the answer to this other question I managed to create an empty window following the approach that I want (a header myWindow.h
file for a ‘mainWindow’ class declaration, another myWindow.cpp
file for the class definition, a main.cpp
file, and a builder.ui
file with the widgets).
My goal is to populate the window with widgets, maybe starting with a simple button.
But due to my poor knowledge of C++ I can’t.
After some research, I tried to incorporate code from similar examples, in particular from here, and this is what I have so far:
myWindow.h
#pragma once
#include <gtkmm/window.h>
#include <gtkmm/builder.h>
#include <gtkmm/box.h>
#include <gtkmm/button.h>
class MainWindow : public Gtk::Window
{
public:
MainWindow(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>& p_builder);
protected:
Glib::RefPtr<Gtk::Builder> m_builder;
};
myWindow.cpp
#include "myWindow.h"
MainWindow::MainWindow(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>& p_builder)
: Gtk::Window(cobject)
{
this->m_builder = p_builder;
auto pButton = p_builder->get_widget<Gtk::Button>("button1");
}
main.cpp
#include <iostream>
#include <cstring>
#include <gtkmm/application.h>
#include <gtkmm/builder.h>
#include "myWindow.h"
int main(int argc, char** argv)
{
auto app = Gtk::Application::create(argc, argv);
auto builder = Gtk::Builder::create_from_file("builder.ui");
MainWindow* window = nullptr;
builder->get_widget_derived("mainWindow", window);
try
{
// You then show the window by using you handle (i.e window).
app->run(*window);
}
catch(const Gtk::BuilderError& bdre)
{
// speciffic handling for BuilderError
std::cout << "Builder error: " << bdre.what() << std::endl;
}
catch(const std::runtime_error& re)
{
// speciffic handling for runtime_error
std::cout << "Other runtime error: " << re.what() << std::endl;
}
catch(const std::exception& ex)
{
// speciffic handling for all exceptions extending std::exception, except
// std::runtime_error which is handled explicitly
std::cout << "Error occurred: " << ex.what() << std::endl;
}
catch(...)
{
// catch any other errors (that we have no information about)
std::cout << "Unknown failure occurred. Possible memory corruption" << std::endl;
}
return 0;
}
builder.ui
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<requires lib="gtk+" version="3.22"/>
<object class="GtkWindow" id="mainWindow">
<property name="title">Grid</property>
<property name="default-width">600</property>
<property name="default-height">400</property>
<child>
<object id="button1" class="GtkButton">
<property name="label">Button</property>
<layout>
<property name="column">1</property>
<property name="row">1</property>
</layout>
</object>
</child>
</object>
</interface>
When I build this code I get the following error:
myWindow.cpp:14:54: error: no matching function for call to ‘Gtk::Builder::get_widget<Gtk::Button>(const char [8])’
14 | auto pButton = p_builder->get_widget<Gtk::Button>("button1");
If I add
Gtk::Button *addButton;
as protected pointer in the header file myWindow.h
, and I use the get_widget()
function in the following way
p_builder->get_widget("button1", addButton);
in the constructor definition in file myWindow.cpp
, then I am able to build the executable, but then I get the following runtime error:
terminate called after throwing an instance of 'Gtk::BuilderError'
Aborted (core dumped)
with no further information (i.e. the ‘try / catch’ can not catch the error details).
The syslog reports the following:
systemd-coredump[826232]: Process 826227 (base) of user 1000 dumped core.#012#012Module libzstd.so.1 from deb libzstd-1.5.5+dfsg2-2build1.1.amd64#012Module libsystemd.so.0 from deb systemd-255.4-1ubuntu8.4.amd64#012Stack trace of thread 826227:#012#0 0x000073d024a9eb1c __pthread_kill_implementation (libc.so.6 + 0x9eb1c)#012#1 0x000073d024a4526e __GI_raise (libc.so.6 + 0x4526e)#012#2 0x000073d024a288ff __GI_abort (libc.so.6 + 0x288ff)#012#3 0x000073d024ea5ffe n/a (libstdc++.so.6 + 0xa5ffe)#012#4 0x000073d024ebae9c n/a (libstdc++.so.6 + 0xbae9c)#012#5 0x000073d024ea5a49 _ZSt9terminatev (libstdc++.so.6 + 0xa5a49)#012#6 0x000073d024ebb128 __cxa_throw (libstdc++.so.6 + 0xbb128)#012#7 0x000073d025614130 _ZN3Gtk12BuilderError10throw_funcEP7_GError (libgtkmm-3.0.so.1 + 0x214130)#012#8 0x000073d0253dc34c _ZN4Glib5Error15throw_exceptionEP7_GError (libglibmm-2.4.so.1 + 0x6834c)#012#9 0x000073d02564819e _ZN3Gtk7Builder13add_from_fileERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE (libgtkmm-3.0.so.1 + 0x24819e)#012#10 0x000073d0256481ee _ZN3Gtk7Builder16create_from_fileERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE (libgtkmm-3.0.so.1 + 0x2481ee)#012#11 0x000055e7fb40e6c8 n/a (/home/fabio/Documents/programming/C++/Esperimenti_GTK/GTK4/simple_button/build/base + 0x76c8)#012#12 0x000073d024a2a1ca __libc_start_call_main (libc.so.6 + 0x2a1ca)#012#13 0x000073d024a2a28b __libc_start_main_impl (libc.so.6 + 0x2a28b)#012#14 0x000055e7fb40e565 n/a (/home/fabio/Documents/programming/C++/Esperimenti_GTK/GTK4/simple_button/build/base + 0x7565)#012ELF object binary architecture: AMD x86-64
What am I doing wrong?
Where should I ‘call’ the widgets defined in the XML file, and how?
10