Hi there I am using GTKmm to write an application, however I cannot access certain menuitem from get_children.
You can see the screen shot and layout in glade designer interface in picture below
The Main GUI GTKApplicationWindow was loaded by a gtkbuilder, then its pointer was past to a recursive function to print everything out.
void loopchildren(Gtk::Widget* parent, int level){
level++;
if (GTK_IS_CONTAINER(parent->gobj())){
std::cout << std::string(level, '.') << "is container level " << level << " name: " <<parent->get_name() << std::endl;
Gtk::Container* contain = dynamic_cast<Gtk::Container*>(parent);
std::vector<Gtk::Widget*> childrens = contain->get_children();
std::cout << std::string(level, '.') << "starts loop level " << level << std::endl;
for(auto const& value: childrens){
loopchildren(value, level);
}
}else{
std::cout << std::string(level, '.') << "is not container level " << level << " name: "<< parent->get_name() << std::endl;
}
}
MyApplicationWindow::MyApplicationWindow(Glib::RefPtr<Gtk::Builder> builder, Glib::ustring baseWidgetName){
thisBaseWidgetPointer = this;
builder->get_widget(baseWidgetName, thisBaseWidgetPointer);
loopchildren(thisBaseWidgetPointer, 0);
}
It produced the output below
.is container level 1 name: gtkmm__GtkApplicationWindow
.starts loop level 1
..is container level 2 name: gtkmm__GtkBox
..starts loop level 2
...is container level 3 name: gtkmm__GtkMenuBar
...starts loop level 3
....is container level 4 name: gtkmm__GtkMenuItem
....starts loop level 4
.....is not container level 5 name: GtkAccelLabel
....is container level 4 name: gtkmm__GtkMenuItem
....starts loop level 4
.....is not container level 5 name: GtkAccelLabel
....is container level 4 name: gtkmm__GtkMenuItem
....starts loop level 4
.....is not container level 5 name: GtkAccelLabel
...is container level 3 name: gtkmm__GtkToolbar
...starts loop level 3
...is container level 3 name: gtkmm__GtkNotebook
...starts loop level 3
........
So I can see that the get_children enters to 1 level below the MenuBar, and found the first level of menuItems, however below the menuitem they only saw an AccelLabel, but not the sub menus
So to further investigate the problem, I connected one of the sub menu item to a function via signal
Gtk::MenuItem* menuItem;
Gtk::MenuItem* menuItem2;
Gtk::MenuBar* mmbar;
void add2(){
std::cout << (menuItem->is_ancestor(*mmbar) ? "is ancestor" : "not ancestor ") <<std::endl;
std::cout << menuItem->get_parent()->get_parent()->get_name() <<std::endl;
loopchildren(menuItem->get_parent()->get_parent(), 0);
}
MyApplicationWindow::MyApplicationWindow(){
builder->get_widget("main_menu_bar", mmbar);
builder->get_widget("menu_basic_company", menuItem);
menuItem->signal_activate().connect(sigc::ptr_fun(&add2));
}
And problem surfaced, the main menubar is "not ancestor" of the sub menu. And instead the parent of the parent of the sub menu item turned out to be a Gtk::Window, for I think no apparent reason, I didn't even specifie a Gtk::window anywhere in the glade ui. That Gtk::window seemed the topmost ancestor as any more ->get_parent() produced error.
.is container level 1 name: GtkWindow
.starts loop level 1
..is container level 2 name: gtkmm__GtkMenu
..starts loop level 2
...is container level 3 name: gtkmm__GtkMenuItem
...starts loop level 3
....is not container level 4 name: GtkAccelLabel
Did they change something in Gtk that caused this problem? Or did I not read some documentation properly? This seemed totally counter intuitive to me. Could the problem be caused by a lack of widget id?
extract of raw .ui file
<object class="GtkApplicationWindow" id="window1">
<property name="can_focus">False</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkMenuBar" id="main_menu_bar">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkMenuItem" id="menu_sys">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">系統</property>
<property name="use_underline">True</property>
<child type="submenu">
<object class="GtkMenu">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkMenuItem">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">系統設定</property>
<property name="use_underline">True</property>
</object>
</child>
<child>
<object class="GtkSeparatorMenuItem">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
</child>
<child>
<object class="GtkMenuItem">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">關閉</property>
<property name="use_underline">True</property>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkMenuItem" id="menu_basic">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">基礎數據</property>
<property name="use_underline">True</property>
<child type="submenu">
<object class="GtkMenu">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkMenuItem" id="menu_basic_company">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">公司</property>
<property name="use_underline">True</property>
</object>
</child>
<child>
<object class="GtkMenuItem" id="menu_basic_supplier">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">供應商</property>
<property name="use_underline">True</property>
</object>
</child>
<child>
<object class="GtkMenuItem" id="menu_basic_supplier_warehouse">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">倉庫</property>
<property name="use_underline">True</property>
</object>
</child>
<child>
<object class="GtkMenuItem" id="menu_basic_shop">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">店舖</property>
<property name="use_underline">True</property>
</object>
</child>
<child>
<object class="GtkMenuItem" id="menu_basic_product2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">商品資料</property>
<property name="use_underline">True</property>
<child type="submenu">
<object class="GtkMenu">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkMenuItem" id="menu_basic_product_brand">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">品牌</property>
<property name="use_underline">True</property>
</object>
</child>
<child>
<object class="GtkMenuItem" id="menu_basic_product_category">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">分類</property>
<property name="use_underline">True</property>
</object>
</child>
<child>
<object class="GtkMenuItem" id="menu_basic_product_line">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">系列</property>
<property name="use_underline">True</property>
</object>
</child>
<child>
<object class="GtkMenuItem" id="menu_basic_product_gender">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">性別</property>
<property name="use_underline">True</property>
</object>
</child>
<child>
<object class="GtkMenuItem" id="menu_basic_product_colour">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">顏色</property>
<property name="use_underline">True</property>
</object>
</child>
<child>
<object class="GtkMenuItem" id="menu_basic_product_sizegroup">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">尺寸組</property>
<property name="use_underline">True</property>
</object>
</child>
<child>
<object class="GtkMenuItem" id="menu_basic_product_sizeratio">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">尺寸比例</property>
<property name="use_underline">True</property>
</object>
</child>
<child>
<object class="GtkMenuItem" id="menu_basic_product_userdefineproperties">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">自訂屬性</property>
<property name="use_underline">True</property>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkMenuItem" id="menu_basic_staff">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">雇員</property>
<property name="use_underline">True</property>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkMenuItem" id="menu_product">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">商品</property>
<property name="use_underline">True</property>
<child type="submenu">
<object class="GtkMenu">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkMenuItem" id="menu_product_main">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">商品主檔案</property>
<property name="use_underline">True</property>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkToolbar">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkNotebook" id="mainnb">
<property name="visible">True</property>
<property name="can_focus">True</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
My Bad, I should use Gtk::MenuItem::get_submenu()
Related
I tried to make simple application using glade and geany ide's but can't do nothing to connect signals set in glade to my handlers. I used this command to build:
"Short" version:
gcc -Wall -w -g `pkg-config --cflags gtk+-3.0 gmodule-2.0 gmodule-export-2.0` -o "%e" "%f" `pkg-config --libs gtk+-3.0 gmodule-2.0 gmodule-export-2.0`
Full comand:
gcc -Wall -w -g -I/usr/include/gtk-3.0 -I/usr/include/pango-1.0 -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -I/usr/include/harfbuzz -I/usr/include/freetype2 -I/usr/include/libpng16 -I/usr/include/libmount -I/usr/include/blkid -I/usr/include/fribidi -I/usr/include/cairo -I/usr/include/lzo -I/usr/include/pixman-1 -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/gio-unix-2.0 -I/usr/include/cloudproviders -I/usr/include/atk-1.0 -I/usr/include/at-spi2-atk/2.0 -I/usr/include/dbus-1.0 -I/usr/lib/dbus-1.0/include -I/usr/include/at-spi-2.0 -pthread -o "%e" "%f" -lgtk-3 -lgdk-3 -lz -lpangocairo-1.0 -lpango-1.0 -lharfbuzz -latk-1.0 -lcairo-gobject -lcairo -lgdk_pixbuf-2.0 -lgio-2.0 -lgobject-2.0 -lglib-2.0 -Wl,--export-dynamic -lgmodule-2.0 -pthread -lglib-2.0 -lglib-2.0
My code (based on russian tutorials): main.cpp
#include <stdio.h>
#include <gtk/gtk.h>
#include <string.h>
#include <stdlib.h>
#include <libintl.h>
#include <locale.h>
#include <locale>
#include <cstdlib>
//main gtk objects
using namespace std;
/* это тот волшебный объект, который сделает за нас окошко */
GtkBuilder *builder;
/* это виджет окна */
GtkWidget *window;
//function to quit the app without data corruption
void safe_quit (GtkWidget* object, gpointer data)
{
gtk_main_quit();
}
void click (GtkButton *button, gpointer label)
{
/* установить метке текст */
gtk_label_set_text ((GtkLabel*)label, "Привет, Хабр!");
}
/* создание окна в этот раз мы вынесли в отдельную функцию */
static GtkWidget* create_window (void)
{
/* сюда будем складывать ошибки */
GError* error = NULL;
/* тут загружаем файл с интерфейсом */
builder = gtk_builder_new ();
//gtk_builder_set_translation_domain(builder,"ru");
if (!gtk_builder_add_from_file (builder, "glade1.glade", &error))
{
/* загрузить файл не удалось */
g_critical ("Не могу загрузить файл: %s", error->message);
g_error_free (error);
}
/* получаем виджет окна, чтобы его показать */
window = GTK_WIDGET (gtk_builder_get_object (builder, "window"));
if (window == NULL)
{
/* что-то не так, наверное, ошиблись в имени */
g_critical ("Ошибка при получении виджета окна");
}
//g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(safe_quit), NULL);
/* помните, мы подключали сигналы вручную? теперь это происходит автоматически! */
gtk_builder_connect_signals (builder, NULL);
gtk_builder_connect_signals (builder, window);
g_object_unref (builder);
return window;
}
int main (int argc, char **argv)
{
setlocale(LC_ALL, "");
auto lang = "";
bindtextdomain(lang, "./locale");
textdomain(lang);
//std::cout << gettext("hello, world!") << std::endl;
auto _ = gettext;
printf(_("help"));
/* виджет окна */
GtkWidget *window;
/* запускаем GTK+ */
gtk_init (&argc, &argv);
/* вызываем нашу функцию для создания окна */
window = create_window();
gtk_widget_show (window);
gtk_window_set_title (GTK_WINDOW(window), "main");
/* передаём управление GTK+ */
gtk_main ();
// printf("f");
return 0;
}
My glade file: glade1.glade
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.38.2 -->
<interface>
<requires lib="gtk+" version="3.24"/>
<object class="GtkApplicationWindow" id="window">
<property name="can-focus">False</property>
<property name="default-width">440</property>
<property name="default-height">250</property>
<signal name="destroy" handler="safe_quit" after="yes" swapped="no"/>
<child>
<object class="GtkBox" id="box1">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkMenuBar">
<property name="visible">True</property>
<property name="can-focus">False</property>
<child>
<object class="GtkMenuItem">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">_File</property>
<property name="use-underline">True</property>
<child type="submenu">
<object class="GtkMenu">
<property name="visible">True</property>
<property name="can-focus">False</property>
<child>
<object class="GtkImageMenuItem">
<property name="label">gtk-new</property>
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="use-underline">True</property>
<property name="use-stock">True</property>
</object>
</child>
<child>
<object class="GtkImageMenuItem">
<property name="label">gtk-open</property>
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="use-underline">True</property>
<property name="use-stock">True</property>
</object>
</child>
<child>
<object class="GtkImageMenuItem">
<property name="label">gtk-save</property>
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="use-underline">True</property>
<property name="use-stock">True</property>
</object>
</child>
<child>
<object class="GtkImageMenuItem">
<property name="label">gtk-save-as</property>
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="use-underline">True</property>
<property name="use-stock">True</property>
</object>
</child>
<child>
<object class="GtkSeparatorMenuItem">
<property name="visible">True</property>
<property name="can-focus">False</property>
</object>
</child>
<child>
<object class="GtkImageMenuItem">
<property name="label">gtk-quit</property>
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="use-underline">True</property>
<property name="use-stock">True</property>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkMenuItem">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">_Edit</property>
<property name="use-underline">True</property>
<child type="submenu">
<object class="GtkMenu">
<property name="visible">True</property>
<property name="can-focus">False</property>
<child>
<object class="GtkImageMenuItem">
<property name="label">gtk-cut</property>
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="use-underline">True</property>
<property name="use-stock">True</property>
</object>
</child>
<child>
<object class="GtkImageMenuItem">
<property name="label">gtk-copy</property>
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="use-underline">True</property>
<property name="use-stock">True</property>
</object>
</child>
<child>
<object class="GtkImageMenuItem">
<property name="label">gtk-paste</property>
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="use-underline">True</property>
<property name="use-stock">True</property>
</object>
</child>
<child>
<object class="GtkImageMenuItem">
<property name="label">gtk-delete</property>
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="use-underline">True</property>
<property name="use-stock">True</property>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkMenuItem">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">_View</property>
<property name="use-underline">True</property>
</object>
</child>
<child>
<object class="GtkMenuItem">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">_Help</property>
<property name="use-underline">True</property>
<child type="submenu">
<object class="GtkMenu">
<property name="visible">True</property>
<property name="can-focus">False</property>
<child>
<object class="GtkImageMenuItem">
<property name="label">gtk-about</property>
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="use-underline">True</property>
<property name="use-stock">True</property>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkAspectFrame">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label-xalign">0</property>
<property name="shadow-type">none</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkSeparator">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="margin-top">2</property>
<property name="margin-bottom">2</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">3</property>
</packing>
</child>
<child>
<object class="GtkBox">
<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="label" translatable="yes">status: normal</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton">
<property name="label" translatable="yes">button</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
<signal name="clicked" handler="click" object="__glade_unnamed_23" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">4</property>
</packing>
</child>
</object>
</child>
</object>
</interface>
When I tried to launch my app I allways get this 3 mesages:
(main:32570): Gtk-WARNING **: 17:41:09.237: Could not find signal handler 'safe_quit'. Did you compile with -rdynamic?
(main:32570): Gtk-WARNING **: 17:41:09.237: Could not lookup object __glade_unnamed_23 on signal clicked of object ___object_24
(main:32570): Gtk-WARNING **: 17:41:09.237: Could not find signal handler 'click'. Did you compile with -rdynamic?
I read a lot of same problems on stackoverflow but nothing helped. I change handlers parameters, names, add static and G_MODULE_EXPORT but ALL of that don't work.
On this site I found this "On Linux and Unices, this is not necessary (G_MODULE_EXPORT); applications should instead be compiled with the -Wl,--export-dynamic CFLAGS, and linked against gmodule-export-2.0." but my app compiled with -Wl and --export-dynamic!!! WHAT I DO WRONG??? Please anyone who knows the answer or have the same problem, help me to find anything that culd be a solution.
Sorry for my bad english and thanks you for your attention...
P.S. (find some kind of solution):
gtk_builder_add_callback_symbol(builder,"safe_quit",G_CALLBACK(safe_quit));
gtk_builder_add_callback_symbol(builder,"click",G_CALLBACK(click));
gtk_builder_connect_signals (builder, NULL);
Is there any solutions how to connect handlers without using gtk_builder_add_callback_symbol? I mean gtk_builder_connect_signals used to auto-connect signals to handle using GModule to look in application’s symbol table, so what's wrong with my app symbol table that signals can't be connected automatically ?
I had to compile your source to get on it by myself, but it seems that you are mixing C and C++ statements in your program, which causes GCC to compile it as a C++ file, just as if you were using g++ instead of gcc. EDIT: actually it will since you named your file: "main .cpp ".
In turn, C++ decorates functions prototypes so you can optionally overload them, which will unable pure C libraries to find them back at run time.
Enclosing your signal header prototypes inside a extern "C" block seems to help:
extern "C"
{
//function to quit the app without data corruption
void safe_quit (GtkWidget* object, gpointer data)
{
gtk_main_quit();
}
void click (GtkButton *button, gpointer label)
{
/* установить метке текст */
gtk_label_set_text ((GtkLabel*)label, "Привет, Хабр!");
}
}
I want to make a useful application with gtkmm/glade and I need to pass a simple Button-signal to another thread. But unfortunately, I don't know how to do this. I made a small piece of software for a better demonstration. which is a button and a progress bar and if you press that button the progress bar gets filled up. It would be great if you modify my code to make the "ClickInterrupt()" function work in another thread.
cheers!
cpp file:
#include <iostream>
#include <gtkmm.h>
using namespace std;
Glib::RefPtr<Gtk::ProgressBar> MyProgressBar;
void ClickInterrupt (void)
{
static float value;
value += 0.2;
if (value > 1.0) value = 0.0;
MyProgressBar->set_fraction (value);
cout << "how do I run this in another thread?" << endl;
}
int main (int argc,char* argv[])
{
auto app = Gtk::Application::create(argc, argv, "org.mylittleapp.uwu");
Glib::RefPtr<Gtk::Builder> builder = Gtk::Builder::create_from_file("mygui.glade");
auto MainWindow = Glib::RefPtr<Gtk::ApplicationWindow>::cast_dynamic(builder->get_object("ApplicationMain"));
auto MyButton = Glib::RefPtr<Gtk::Button>::cast_dynamic(builder -> get_object("MyButton"));
MyButton -> signal_clicked().connect(sigc::ptr_fun(&ClickInterrupt));
MyProgressBar = Glib::RefPtr<Gtk::ProgressBar>::cast_dynamic(builder->get_object("Progress"));
app->run(*(MainWindow.get()));
}
glade file:
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.38.2 -->
<interface>
<requires lib="gtk+" version="3.24"/>
<object class="GtkApplicationWindow" id="ApplicationMain">
<property name="can-focus">False</property>
<property name="title" translatable="yes">N00B :)</property>
<property name="default-width">200</property>
<property name="default-height">100</property>
<property name="icon-name">face-smile-big</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkProgressBar" id="Progress">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="valign">center</property>
<property name="vexpand">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="MyButton">
<property name="label" translatable="yes">Fill the Progressbar</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
</object>
</interface>
In python, there is something here: passing GUI button pressing to a thread controlling countdown in that GUI. perhaps similar can be done in c. for the reason I am not familiar with c, I cannot give you the precise c code. https://github.com/f4iteightiz/UWR_scoreboard
The official documentation (Gtkmm 3.24) has a nice example, with a progress bar being updated by a button. Basically, Glib::Dispatcher is what you are looking for.
For other versions of Gtkmm, see this page
Unfortunately I'm new to programming in C and I'm experiencing many problems with external libraries compatibility between linux and windows.
I'm trying to learn how to use GTK 3, use Glade to create the interface and geany to write the code in GCC
I'm looking for a solution on the internet for 4 days, but I don't understand how to solve it:
Please be patient, I don't know who to ask by now.
Thanks for your help.
when the "OK" button is pressed.
Appair the message on the first gtkentry but the second entry still empty
void gtk_entry_set_text (GtkEntry* otarget, const gchar* TargetText); //Give no action like no command exist
Code written in GCC via Geany
#include <stdio.h>
#include <gtk/gtk.h>
#include <gmodule.h>
int main(int argc, char *argv[])
{
GtkBuilder *builder;
GtkWidget *window;
gtk_init(&argc, &argv);
builder = gtk_builder_new();
gtk_builder_add_from_file (builder, "test.glade", NULL);
window = GTK_WIDGET(gtk_builder_get_object(builder, "TestWin"));
gtk_builder_connect_signals(builder, NULL);
g_object_unref(builder);
gtk_widget_show(window);
gtk_main();
return 0;
}
// I have to put (extern "C" G_MODULE_EXPORT ) because without give Could not find signal handler 'on_ok_button_clicked'. Did you compile with -rdynamic?
extern "C" G_MODULE_EXPORT void on_ok_button_clicked(GtkButton *msgbox_ok, GtkEntry *origin, GtkEntry *target, gpointer user_data)
{
const gchar *OriginText;
const gchar *TargetText;
OriginText = gtk_entry_get_text (GTK_ENTRY (origin)); // gtk_entry_get_text: assertion 'GTK_IS_ENTRY (entry)' failed
TargetText = OriginText;
void gtk_entry_set_text (GtkEntry *target, const gchar *TargetText); //Give no action like no command exist
}
extern "C" G_MODULE_EXPORT void on_cancel_button_clicked(GtkButton *cancel_button, gpointer user_data)
{
gtk_main_quit();
}
extern "C" G_MODULE_EXPORT void on_TestWin_destroy(GtkWidget *TestWin, gpointer user_data)
{
gtk_main_quit();
}
File test.glade in XML creato con Glade 3
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.1 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<object class="GtkWindow" id="TestWin">
<property name="can_focus">False</property>
<property name="default_width">420</property>
<property name="default_height">200</property>
<signal name="destroy" handler="on_TestWin_destroy" swapped="no"/>
<child>
<placeholder/>
</child>
<child>
<object class="GtkFixed">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkButton" id="ok_button">
<property name="label" translatable="yes">OK</property>
<property name="width_request">95</property>
<property name="height_request">35</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<signal name="clicked" handler="on_ok_button_clicked" swapped="no"/>
</object>
<packing>
<property name="x">190</property>
<property name="y">130</property>
</packing>
</child>
<child>
<object class="GtkButton" id="cancel_button">
<property name="label" translatable="yes">Cancell</property>
<property name="width_request">100</property>
<property name="height_request">35</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<signal name="clicked" handler="on_cancel_button_clicked" swapped="no"/>
</object>
<packing>
<property name="x">300</property>
<property name="y">130</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="origin">
<property name="width_request">300</property>
<property name="height_request">35</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
</object>
<packing>
<property name="x">100</property>
<property name="y">20</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="target">
<property name="width_request">300</property>
<property name="height_request">35</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
</object>
<packing>
<property name="x">100</property>
<property name="y">60</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="lbl_origin">
<property name="width_request">90</property>
<property name="height_request">35</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Origin Text</property>
</object>
<packing>
<property name="x">5</property>
<property name="y">20</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="lbl_target">
<property name="width_request">90</property>
<property name="height_request">35</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Target Text</property>
</object>
<packing>
<property name="x">5</property>
<property name="y">60</property>
</packing>
</child>
</object>
</child>
</object>
</interface>
Command used for compilation under Windows 10
gcc -pthread -mms-bitfields -IC:/msys64/mingw64/include/gtk-3.0 -IC:/msys64/mingw64/include/cairo -IC:/msys64/mingw64/include -IC:/msys64/mingw64/include/pango-1.0 -IC:/msys64/mingw64/include/fribidi -IC:/msys64/mingw64/include -IC:/msys64/mingw64/include/atk-1.0 -IC:/msys64/mingw64/include/cairo -IC:/msys64/mingw64/include/pixman-1 -IC:/msys64/mingw64/include -IC:/msys64/mingw64/include/freetype2 -IC:/msys64/mingw64/include -IC:/msys64/mingw64/include/harfbuzz -IC:/msys64/mingw64/include/libpng16 -IC:/msys64/mingw64/include/gdk-pixbuf-2.0 -IC:/msys64/mingw64/include -IC:/msys64/mingw64/lib/libffi-3.2.1/include -IC:/msys64/mingw64/include/glib-2.0 -IC:/msys64/mingw64/lib/glib-2.0/include -IC:/msys64/mingw64/include test.cpp -o test -LC:/msys64/mingw64/lib -lgtk-3 -lgdk-3 -lz -lgdi32 -limm32 -lshell32 -lole32 -Wl,-luuid -lwinmm -ldwmapi -lsetupapi -lcfgmgr32 -lpangowin32-1.0 -lpangocairo-1.0 -lpango-1.0 -latk-1.0 -lcairo-gobject -lcairo -lgdk_pixbuf-2.0 -lgio-2.0 -lgobject-2.0 -lintl -lglib-2.0
Below are 4 files:
Case #1: example1.py using example1.glade.
Case #2: example2.py using example2.glade.
To see the output in both cases, the steps are the same for each case. Just click on the multiline label or on the link button after opening one of these programs, and the output will be shown in the terminal.
Screenshot, the same for both cases
1st case
example1.py
# coding=utf-8
import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk
def box_clicked(*args):
print(args)
return True
b = Gtk.Builder()
b.add_from_file("example1.glade")
w = b.get_object("window1")
lb = b.get_object("linkButton")
eb = b.get_object("eventbox1")
eb.connect("button-release-event", box_clicked, lb)
w.connect("delete-event", Gtk.main_quit)
w.show_all()
Gtk.main()
example1.glade
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.20.0 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<object class="GtkWindow" id="window1">
<property name="can_focus">False</property>
<child>
<object class="GtkAspectFrame">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label_xalign">0</property>
<child>
<object class="GtkEventBox" id="eventbox1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="above_child">True</property>
<child>
<object class="GtkBox" id="box1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkLinkButton" id="linkButton">
<property name="label" translatable="yes">button</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="relief">none</property>
<property name="uri">http://www.google.com</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="multilineLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">this
is
a
multiline
label</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</interface>
The signal and the handler were connected manually from code.
Example of arguments passed to the signal handler, printed with print(args):
(<Gtk.EventBox object at 0x02bc4b6c (GtkEventBox at 0x02b9e290)>, <Gdk.EventButt
on object at 0x02bc4c34 (void at 0x02e691c8)>, <Gtk.LinkButton object at 0x02668
914 (GtkLinkButton at 0x02e37120)>)
Pretty print:
Gtk.EventBox
Gtk.EventButton
Gtk.LinkButton
2nd case
example2.py
# coding=utf-8
import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk
class Builder(Gtk.Builder):
def __init__(self):
Gtk.Builder.__init__(self)
self.add_from_file("example2.glade")
self.connect_signals(self)
self.win = self.get_object("window1")
def box_clicked(self, *args):
print(args)
return True
win = Builder().win
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main()
example2.glade
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.20.0 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<object class="GtkWindow" id="window1">
<property name="can_focus">False</property>
<child>
<object class="GtkAspectFrame">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label_xalign">0</property>
<child>
<object class="GtkEventBox" id="eventbox1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="above_child">True</property>
<signal name="button-release-event" handler="box_clicked" object="linkButton" swapped="no"/>
<child>
<object class="GtkBox" id="box1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkLinkButton" id="linkButton">
<property name="label" translatable="yes">button</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="relief">none</property>
<property name="uri">http://www.google.com</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="multilineLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">this
is
a
multiline
label</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</interface>
The event handler was connected to the signal in Glade.
Example of arguments passed to the signal handler, printed with print(args):
(<Gtk.LinkButton object at 0x02c68554 (GtkLinkButton at 0x02e96118)>, <Gdk.Event
Button object at 0x02c6b5f4 (void at 0x02d56a60)>)
Pretty print
Gtk.LinkButton
Gdk.EventButton
Pretty print comparison
Arguments for the 1st case:
Gtk.EventBox
Gtk.EventButton
Gtk.LinkButton
Arguments for the 2nd case:
Gtk.LinkButton
Gdk.EventButton
I want to comprehend the reasons behind the differences between the output in these 2 cases.
I use Python 2.7.13 and GTK+ 3.22 on MSYS2 on Windows 10. Both MSYS2 and Windows have all the available updates installed.
The second glade file has an object attribute to the signal element, which is the equivalent of using g_signal_connect_object() instead of g_signal_connect() in C. It passes the given object (the link button) as the first parameter to the signal handler.
I'm new to C++ GUI programming with GTK+, and I'm having a issue with getting the signal handler for one of my buttons to work, upon compiling and running I receive the following warning. Does anyone know if I'm doing something incorrectly or missing something?
(Project Thoth:4359): Gtk-WARNING **: Could not find signal handler 'on_login_clicked'. Did you compile with -rdynamic?
This is my cpp file
#include <cstdlib>
#include <cstdio>
#include <string>
#include <gtk/gtk.h>
#include <iostream>
extern "C"
using namespace std;
int main(int argc, char *argv[])
{
GtkEntry *e1;//textbox1
GtkEntry *e2;//textbox2
GtkEntry *e3;//textbox3
GtkBuilder *gtkBuilder;
GtkWidget *window;
gtk_init(&argc, &argv);
gtkBuilder = gtk_builder_new();
gtk_builder_add_from_file(gtkBuilder, "Unsaved 1.glade", NULL);
window = GTK_WIDGET(gtk_builder_get_object(gtkBuilder, "Login"));
gtk_builder_connect_signals(gtkBuilder, window);
g_object_unref(G_OBJECT(gtkBuilder));
gtk_widget_show(window);
gtk_main();
cout << "Login window loaded";
return 0;
}
G_MODULE_EXPORT void on_login_clicked()
{
printf("Request Detected\n");
GtkBuilder *gtkBuilder;
GtkWidget *window;
gtkBuilder = gtk_builder_new();
gtk_builder_add_from_file(gtkBuilder, "Unsaved 1.glade", NULL);
GtkEntry *e1;
GtkEntry *e2;
e1 = GTK_ENTRY( gtk_builder_get_object( gtkBuilder, "user1" ));
e2 = GTK_ENTRY( gtk_builder_get_object( gtkBuilder, "pass"));
gtk_builder_connect_signals(gtkBuilder, e1);
const char *home;
home = gtk_entry_get_text(e1);
cout << home;
}
and my glade file
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.18.3 -->
<interface>
<requires lib="gtk+" version="3.0"/>
<object class="GtkApplicationWindow" id="Login">
<property name="can_focus">False</property>
<property name="window_position">center</property>
<property name="default_width">400</property>
<property name="default_height">300</property>
<signal name="destroy" handler="on_window_destroy" swapped="no"/>
<child>
<object class="GtkLayout" id="layout1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkLabel" id="Label">
<property name="width_request">100</property>
<property name="height_request">80</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Project Thoth
</property>
<property name="angle">0.089999999999999997</property>
<attributes>
<attribute name="weight" value="bold"/>
</attributes>
</object>
<packing>
<property name="x">156</property>
<property name="y">14</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="user1">
<property name="width_request">166</property>
<property name="height_request">80</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
</object>
<packing>
<property name="x">128</property>
<property name="y">72</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label1">
<property name="width_request">100</property>
<property name="height_request">80</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Username:
</property>
</object>
<packing>
<property name="x">121</property>
<property name="y">52</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="pass">
<property name="width_request">166</property>
<property name="height_request">84</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
</object>
<packing>
<property name="x">129</property>
<property name="y">130</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label3">
<property name="width_request">100</property>
<property name="height_request">80</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Password:
</property>
</object>
<packing>
<property name="x">117</property>
<property name="y">123</property>
</packing>
</child>
<child>
<object class="GtkButton" id="button1">
<property name="label" translatable="yes">Login</property>
<property name="width_request">70</property>
<property name="height_request">29</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="relief">half</property>
<signal name="clicked" handler="on_login_clicked" swapped="no"/>
</object>
<packing>
<property name="x">171</property>
<property name="y">191</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label2">
<property name="width_request">105</property>
<property name="height_request">35</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">save info login ?</property>
</object>
<packing>
<property name="x">154</property>
<property name="y">227</property>
</packing>
</child>
<child>
<object class="GtkSwitch" id="switch1">
<property name="width_request">74</property>
<property name="height_request">23</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
</object>
<packing>
<property name="x">166</property>
<property name="y">263</property>
</packing>
</child>
</object>
</child>
</object>
</interface>
also for compiling i used the following flags
g++ -o "Project Thoth" main.cpp $(pkg-config --cflags --libs gtk+-3.0 gmodule-2.0 )
Thanks in advance for any help.
The message is giving a good suggestion: compile (actually link) with -rdynamic so compile your your code with:
g++ -rdynamic -o Project_Thoth -Wall -g main.cpp \
$(pkg-config --cflags --libs gtk+-3.0 gmodule-2.0 )
BTW, I strongly recommend avoiding a space in your executable name. So Project_Thoth not "Project Thoth". Also, don't forget to ask for warnings (with -Wall at least, perhaps also add -Wextra) and debug info (-g), which is very useful, notably to debug your program with gdb debugger (or to hunt memory leaks with valgrind).
Once the program is debugged, for benchmarking purposes, you might ask the compiler to optimize (so add -O2).
BTW, if you really want to use GTK with C++ (not just C), consider gtkmm. But you could code your GTK program in plain C99 (so no cout, but printf). And perhaps even consider a switch to Qt (another widget toolkit, in C++), if C++ is important to you.
If coding in C++ with GTK (not gtkmm), better declare as extern "C" all your GTK related code.