Search code examples
c++gtkgtkmmgtkmm3

Adjustment object not a widget type GtkBuilder


I can't use Gtk::Adjustment widget from my glade file. The program builds and runs with the following error:

(test-glade-spinbutton:227780): gtkmm-CRITICAL **: 13:38:45.769: gtkmm: object `adjustment_width' (type=`gtkmm__GtkAdjustment') (in GtkBuilder file) is not a widget type.

(test-glade-spinbutton:227780): gtkmm-CRITICAL **: 13:38:45.769: gtkmm: Gtk::Builder: widget `adjustment_width' was not found in the GtkBuilder file, or the specified part of it.

** (test-glade-spinbutton:227780): CRITICAL **: 13:38:45.769: Gtk::Builder::get_widget(): dynamic_cast<> failed.

However, for this post I've removed interaction with Gtk::Adjustment so the program can actually run. The program crashes if I try to read my adjustment widget's current value.

Below is the C++ code:

#include <gtkmm.h>

using Gtk::Adjustment;
using Gtk::Application;
using Gtk::Builder;
using Gtk::Grid;
using Gtk::SpinButton;
using Gtk::Window;

class MyWindow : public Window
{
    Grid       *main_content;
    Adjustment *adjustment_width;
    SpinButton *width;

public:
    MyWindow()
    {
        auto builder = Builder::create_from_file("test-spinbutton.glade");

        builder->get_widget("main_content"    , main_content);
        builder->get_widget("adjustment_width", adjustment_width);
        builder->get_widget("width"           , width);

        add(*main_content);

        present();
    }
};

int main()
{
    auto app = Application::create("domain.reverse.test-spinbutton");

    MyWindow hello;

    return app->run(hello);
}

and the glade file:

<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.2 -->
<interface>
  <requires lib="gtk+" version="3.20"/>
  <object class="GtkAdjustment" id="adjustment_height">
    <property name="lower">1</property>
    <property name="upper">2147483647</property>
    <property name="value">1</property>
    <property name="step_increment">1</property>
    <property name="page_increment">10</property>
  </object>
  <object class="GtkAdjustment" id="adjustment_width">
    <property name="lower">1</property>
    <property name="upper">2147483647</property>
    <property name="value">1</property>
    <property name="step_increment">1</property>
    <property name="page_increment">10</property>
  </object>
  <object class="GtkGrid" id="main_content">
    <property name="visible">True</property>
    <property name="can_focus">False</property>
    <child>
      <object class="GtkLabel">
        <property name="visible">True</property>
        <property name="can_focus">False</property>
        <property name="margin_left">24</property>
        <property name="margin_top">6</property>
        <property name="label" translatable="yes">Width</property>
      </object>
      <packing>
        <property name="left_attach">0</property>
        <property name="top_attach">1</property>
      </packing>
    </child>
    <child>
      <object class="GtkLabel">
        <property name="visible">True</property>
        <property name="can_focus">False</property>
        <property name="margin_left">24</property>
        <property name="margin_top">6</property>
        <property name="label" translatable="yes">Height</property>
      </object>
      <packing>
        <property name="left_attach">0</property>
        <property name="top_attach">2</property>
      </packing>
    </child>
    <child>
      <object class="GtkSpinButton" id="width">
        <property name="visible">True</property>
        <property name="can_focus">True</property>
        <property name="margin_left">6</property>
        <property name="margin_top">6</property>
        <property name="hexpand">True</property>
        <property name="adjustment">adjustment_width</property>
      </object>
      <packing>
        <property name="left_attach">1</property>
        <property name="top_attach">1</property>
      </packing>
    </child>
    <child>
      <object class="GtkSpinButton" id="height">
        <property name="visible">True</property>
        <property name="can_focus">True</property>
        <property name="margin_left">6</property>
        <property name="margin_top">6</property>
        <property name="hexpand">True</property>
        <property name="adjustment">adjustment_height</property>
      </object>
      <packing>
        <property name="left_attach">1</property>
        <property name="top_attach">2</property>
      </packing>
    </child>
    <child>
      <object class="GtkLabel">
        <property name="visible">True</property>
        <property name="can_focus">False</property>
        <property name="label" translatable="yes">Image Size</property>
        <attributes>
          <attribute name="weight" value="bold"/>
        </attributes>
      </object>
      <packing>
        <property name="left_attach">0</property>
        <property name="top_attach">0</property>
      </packing>
    </child>
    <child>
      <object class="GtkToggleButton" id="toggle_ratio_wh">
        <property name="label">gtk-execute</property>
        <property name="visible">True</property>
        <property name="can_focus">True</property>
        <property name="receives_default">True</property>
        <property name="margin_left">6</property>
        <property name="margin_top">6</property>
        <property name="use_stock">True</property>
        <property name="always_show_image">True</property>
      </object>
      <packing>
        <property name="left_attach">2</property>
        <property name="top_attach">1</property>
        <property name="height">2</property>
      </packing>
    </child>
    <child>
      <placeholder/>
    </child>
    <child>
      <placeholder/>
    </child>
    <style>
      <class name="dialog-main-content"/>
    </style>
  </object>
</interface>


Solution

  • The error says that adjustment_width is not a widget, like its inheritance tree suggest (unlike a grid or a spin button) so get_widget won't work. You need to use get_object. For example:

    #include <iostream>
    #include <gtkmm.h>
    
    using Gtk::Adjustment;
    using Gtk::Application;
    using Gtk::Builder;
    using Gtk::Grid;
    using Gtk::SpinButton;
    using Gtk::Window;
    
    class MyWindow : public Window
    {
        Grid       *main_content;
        SpinButton *width;
        
        Glib::RefPtr<Adjustment> adjustment_width;
    
    public:
        MyWindow()
        {
            auto builder = Builder::create_from_file("test-spinbutton.glade");
    
            // Widgets:
            builder->get_widget("main_content"    , main_content);
            builder->get_widget("width"           , width);
    
            // Other objects (non widgets):
    
            // 1. Get the object from the object three:
            Glib::RefPtr<Glib::Object> adjustmentObject = builder->get_object("adjustment_width");
    
            // 2. At this point, it is a Glib::Object (which is Adjustment's base type), so we need
            //    to cast:
            adjustment_width = Glib::RefPtr<Adjustment>::cast_dynamic(adjustmentObject);
    
            // 3. Then we can access it normally:
            std::cout << "The adjustment value is : " << adjustment_width->get_value() << std::endl;
    
            add(*main_content);
    
            present();
        }
    };
    
    int main()
    {
        auto app = Application::create("domain.reverse.test-spinbutton");
    
        MyWindow hello;
    
        return app->run(hello);
    }