Я создаю небольшую программу с C++ и GTK 3 (просто изучая ее), и у меня были проблемы с этим. Итак, я выделил проблематичную часть.
Он разрешается получать запись и печатать ее при нажатии кнопки.
Это код:
#include <iostream>
#include <gtk/gtk.h>
using namespace std;
GtkWidget *wventana;
GtkWidget *wgrid;
//FUNCS
void ventana(string titulo, int margen)
{
const char * tituloc = titulo.c_str();
wventana = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_position (GTK_WINDOW (wventana), GTK_WIN_POS_CENTER);
gtk_window_set_title (GTK_WINDOW (wventana), tituloc);
gtk_container_set_border_width(GTK_CONTAINER(wventana), margen);
}
void grid()
{
wgrid = gtk_grid_new();
gtk_container_add(GTK_CONTAINER(wventana), wgrid);
gtk_grid_set_row_spacing (GTK_GRID (wgrid), 10);
gtk_grid_set_column_spacing (GTK_GRID (wgrid), 25);
}
void boton_clic (GtkEntry *wentrada, gpointer user_data)
{
const char *nombre;
nombre = gtk_entry_get_text(wentrada);
cout << nombre << endl;
}
void entrada(int x, int y, int lx, int ly)
{
GtkWidget *wentrada;
wentrada = gtk_entry_new();
gtk_grid_attach (GTK_GRID (wgrid), wentrada, x, y, lx, ly);
}
void boton(string texto, int x, int y, int lx, int ly)
{
const char * wtexto = texto.c_str();
GtkWidget *wboton;
wboton = gtk_button_new_with_label (wtexto);
gtk_grid_attach (GTK_GRID (wgrid), wboton, x, y, lx, ly);
g_signal_connect (GTK_BUTTON (wboton), "clicked", G_CALLBACK (boton_clic), G_OBJECT (wventana));
}
//MAIN
int main(int argc, char *argv[])
{
gtk_init (&argc, &argv);
ventana("ventana",10);
grid();
entrada(1, 1, 1, 1);
boton("Aprietame", 1, 2, 1, 1);
gtk_widget_show_all (wventana);
gtk_main ();
return 0;
}
Он не получает запись и показывает следующее сообщение об ошибке:
(boton:6669): Gtk-CRITICAL **: gtk_entry_get_text: assertion 'GTK_IS_ENTRY (entry)' failed
Может ли кто-нибудь рассказать, в чем проблема? и как я могу заставить его работать? Или в любом случае, что является хорошей альтернативой для этого? (он должен быть с разделенными функциями)
Заранее спасибо.
Спасибо за ваш ответ @ptomato, я попробовал заменить с предложенными вами изменениями новый код:
#include <iostream>
#include <gtk/gtk.h>
using namespace std;
GtkWidget *wventana;
GtkWidget *wgrid;
//FUNCS
void ventana(string titulo, int margen)
{
const char * tituloc = titulo.c_str();
wventana = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_position (GTK_WINDOW (wventana), GTK_WIN_POS_CENTER);
gtk_window_set_title (GTK_WINDOW (wventana), tituloc);
gtk_container_set_border_width(GTK_CONTAINER(wventana), margen);
}
void grid()
{
wgrid = gtk_grid_new();
gtk_container_add(GTK_CONTAINER(wventana), wgrid);
gtk_grid_set_row_spacing (GTK_GRID (wgrid), 10);
gtk_grid_set_column_spacing (GTK_GRID (wgrid), 25);
}
void boton_clic (GtkButton *wboton, GtkEntry *wentrada)
{
const char *nombre;
nombre = gtk_entry_get_text (wentrada);
cout << nombre << endl;
}
void entrada(int x, int y, int lx, int ly)
{
GtkWidget *wentrada;
wentrada = gtk_entry_new();
gtk_grid_attach (GTK_GRID (wgrid), wentrada, x, y, lx, ly);
}
void boton(string texto, int x, int y, int lx, int ly)
{
const char * wtexto = texto.c_str();
GtkWidget *wboton;
wboton = gtk_button_new_with_label (wtexto);
gtk_grid_attach (GTK_GRID (wgrid), wboton, x, y, lx, ly);
g_signal_connect (wboton, "clicked", G_CALLBACK (boton_clic), wentrada);
}
//MAIN
int main(int argc, char *argv[])
{
gtk_init (&argc, &argv);
ventana("ventana",10);
grid();
entrada(1, 1, 1, 1);
boton("Aprietame", 1, 2, 1, 1);
gtk_widget_show_all (wventana);
gtk_main ();
return 0;
}
но когда я пытаюсь скомпилировать его, он показывает:
In file included from /usr/include/glib-2.0/gobject/gobject.h:28:0,
from /usr/include/glib-2.0/gobject/gbinding.h:29,
from /usr/include/glib-2.0/glib-object.h:23,
from /usr/include/glib-2.0/gio/gioenums.h:28,
from /usr/include/glib-2.0/gio/giotypes.h:28,
from /usr/include/glib-2.0/gio/gio.h:26,
from /usr/include/gtk-3.0/gdk/gdkapplaunchcontext.h:28,
from /usr/include/gtk-3.0/gdk/gdk.h:32,
from /usr/include/gtk-3.0/gtk/gtk.h:30,
from boton.cpp:2:
boton.cpp: In function ‘void boton(std::string, int, int, int, int):
boton.cpp:51:64: error: ‘wentrada was not declared in this scope
g_signal_connect (wboton, "clicked", G_CALLBACK (boton_clic), wentrada);
^
/usr/include/glib-2.0/gobject/gsignal.h:472:73: note: in definition of macro ‘g_signal_connect
g_signal_connect_data ((instance), (detailed_signal), (c_handler), (data), NULL, (GConnectFlags) 0)
^
Compilation failed.
Что не так? Что мне делать???
Не могли бы вы еще раз объяснить второй аргумент? (английский не мой родной язык, и эта часть меня немного сбила с толку: P)
Еще раз спасибо.
boton_clic
сигнала boton_clic
имеет два аргумента: GtkWidget *
и указатель на некоторые пользовательские данные, которые вы указываете. Первым аргументом всегда является объект, который отправил сигнал, так что это wboton
; но вы помечены аргументом wentrada
и рассматриваете его как GtkEntry *
, следовательно, сообщение об ошибке.
Второй аргумент - это данные пользователя, которые вы указываете при подключении сигнала. В вашем g_signal_connect()
вы проходите здесь wventana
. Но если вы хотите получить доступ к записи в вашем обработчике сигнала, вы должны вместо этого перейти wentrada
.
Итак, это должно выглядеть так:
void boton_clic (GtkButton *wboton, GtkEntry *wentrada)
{
const char *nombre;
nombre = gtk_entry_get_text (wentrada);
cout << nombre << endl;
}
...
g_signal_connect (wboton, "clicked", G_CALLBACK (boton_clic), wentrada);
wventada
иwgrid
, в начале кода:GtkWidget *wentrada;
, На самом деле, это не лучшее решение. Лучше, если вы создаете классы, а не используете глобальные переменные. Но для этого примера это решение, которое подходит к остальной части кода.