LINUX.ORG.RU

[custom GTK widget], почему не отображается родитель?


0

1

День добрый, пытаюсь тут наваять виджет, наследую его от GtkEntry,добавил его на форму, но проблема в том что виджет не отображается на форме, вместо него пустое пространство, все методы я беру от родителя:

static void 
gtk_button_entry_class_init(GtkButtonEntryClass * class)
{
	GObjectClass 	* gobject_class	= G_OBJECT_CLASS(class);	
	GtkWidgetClass 	* widget_class 	= (GtkWidgetClass*)class;
	GtkObjectClass 	* object_class 	= GTK_OBJECT_CLASS(class);
	
	parent_class = (GtkEntryClass*)g_type_class_peek_parent(class);
	
	object_class->destroy 				= gtk_button_entry_destroy;
	gobject_class->finalize 			= gtk_button_entry_finalize;
	widget_class->realize 				= gtk_button_entry_realize;
	widget_class->map 					= gtk_button_entry_map;
	widget_class->size_request 			= gtk_button_entry_size_request;
	widget_class->size_allocate 		= gtk_button_entry_size_allocate;
	widget_class->expose_event 			= gtk_button_entry_expose;
	widget_class->button_press_event 	= gtk_button_entry_press;
	widget_class->button_release_event 	= gtk_button_entry_release;

}

static void 
gtk_button_entry_init(GtkButtonEntry * button_entry)
{
	
	
}

GtkWidget * 
gtk_button_entry_new()
{
	return GTK_WIDGET(g_object_new(GTK_TYPE_BUTTON_ENTRY, NULL));
}

static void
gtk_button_entry_realize(GtkWidget * widget)
{
  GTK_WIDGET_CLASS(parent_class)->realize(widget);
}

static void
gtk_button_entry_map(GtkWidget * widget)
{
	GTK_WIDGET_CLASS(parent_class)->map(widget);
}

static void 
gtk_button_entry_size_request(GtkWidget *widget, GtkRequisition * requisition)
{
	GTK_WIDGET_CLASS(parent_class)->size_request(widget, requisition);
}

static void
gtk_button_entry_size_allocate(GtkWidget *widget, GtkAllocation * allocation)
{
	GTK_WIDGET_CLASS(parent_class)->size_allocate(widget, allocation);
}

static gint 
gtk_button_entry_expose(GtkWidget * widget, GdkEventExpose *event)
{
	/* Draw buttons here */
	
	return GTK_WIDGET_CLASS(parent_class)->expose_event(widget, event);
}

static void 
gtk_button_entry_finalize(GObject *obj)
{
	/* Free buttons here */
	
	if (G_OBJECT_CLASS(parent_class)->finalize)
		G_OBJECT_CLASS(parent_class)->finalize(obj);
	
}

static void 
gtk_button_entry_destroy(GtkObject *obj)
{
	if (GTK_OBJECT_CLASS(parent_class)->destroy)
		GTK_OBJECT_CLASS(parent_class)->destroy(obj);
	
}

и файл теста:

int main(int argc, char *argv[]) {

	GtkWidget * window;
	GtkWidget * vbox;
	GtkWidget * button;
	GtkWidget * button_entry;
	
	gtk_init(&argc, &argv);
	window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
	g_return_val_if_fail(window != NULL, 0);
	
	vbox = gtk_vbox_new(FALSE, 0);
	gtk_container_add(GTK_CONTAINER(window), vbox);
	
	button = gtk_button_new_with_label("TEST");
	gtk_container_add(GTK_CONTAINER(vbox), button);
	
	button_entry = gtk_button_entry_new();
	gtk_widget_set_size_request(button_entry, 40, 20);
	gtk_container_add(GTK_CONTAINER(vbox), button_entry);
	
	gtk_widget_show_all(window);
	g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(main_quit), NULL);
	gtk_main();

Здесь под кнопкой у меня образуется пустое место, размером в 20 пикселей, как и установил. Если же заменить в

button_entry = gtk_button_entry_new();
на
button_entry = gtk_entry_new();
То всё нормально создаётся, Entry появляется под кнопкой, но в тоже время у моего виджета поле requisition(width и height, посмотрел по отладчику) равны нулю, почему-то(я ведь установил размер виджета)... в чём может быть проблема, дайте наводку :)

★★★★★

не знаю, поможет или нет, но очень хороший способ делать custom widgets - использовать vala

наследуешь, делаешь так чтобы работало, потом берешь сгенерированный сишный код, и продолжаешь уже с ним работать. работы в 100 раз меньше.

waker ★★★★★ ()
Ответ на: комментарий от ananas

А что там заполнять то? Этот метод для инициализации полей объекта, ведь так(в смысле все методы xxx_init это для объекта, а xxx_class_init -для инициализации класса)? да и струтура GtkButtonEntry у меня пока почти ничего не содержит:

typedef struct {
    GtkEntry parent;
    GList * buttons_info;
} GtkButtonEntry;

класс соответственно:

typedef struct {
    GtkEntryClass parent;
    (* pressed)(int index);
    (* released)(int index);

} GtkButtonEntryClass;

Или родителей мне тоже инициализировать?

xterro ★★★★★ ()
Ответ на: комментарий от xterro

очень просто. прогоняешь .vala файл через valac, на выходе обычный сишник, типа того что ты привел вверху.

waker ★★★★★ ()
Ответ на: комментарий от ananas

Ума не приложу что писать в gtk_button_entry_init, как родителя инициализировать? :(

И ещё такой момент, можно ли на GtkEntry положить кнопку? Или придётся это её самостоятельно рисовать в expose?

xterro ★★★★★ ()
Ответ на: комментарий от xterro

загляни в gtk_entry_init. как минимум должны выставляться атрибуты editable и visible у родителя. у тебя они скорее всего нули, поэтому ничего и не показывается

а для композитного виджета лучше наследоваться от какого-нибудь GtkBox

ananas ★★★★★ ()
Ответ на: комментарий от ananas

Добавил d gtk_button_entry_class_init такое:

	GValue val = { 0, };
	g_value_init(&val, G_TYPE_BOOLEAN);
	g_value_set_boolean(&val, TRUE);
	g_object_set_property(parent_class, "visibility", &val); 
	g_object_set_property(parent_class, "editable", &val); 
	g_value_unset(&val);

Ругаетсо, грит

note: expected 'struct GObject *' but argument is of type 'struct GtkEntryClass *'

Оно разве не от GObject? Пытался в gtk_button_entry_init добавлять тоже ругается

gtk_entry_set_visibility(&button_entry->parent, TRUE);
говорит, мол это нифига не GtkEntry... :(

xterro ★★★★★ ()
Ответ на: комментарий от ananas

Это я в gtk_entry_init посмотрел что свойство задаются у класса, и решил так попробовать. Ещё пробовал так:

	GValue val = { 0, };
	g_value_init(&val, G_TYPE_BOOLEAN);
	g_value_set_boolean(&val, TRUE);
	
	g_object_set_property(&button_entry->parent, "visibility", &val); 
	g_value_unset (&val);

Но в этом случае мне говорит мол object class GtkButtonEntry has no property 'visibility', т.е класс моего виджета не имеет свойства Visibility(он его и правда не имеет), но ведь я свойство устанавливаю для его родителя, а не для него т.е для GtkEntry... или не?

xterro ★★★★★ ()
Ответ на: комментарий от xterro
diff -urN ttt-orig/buttonedit.c ttt/buttonedit.c
--- ttt-orig/buttonedit.c	2011-05-04 16:07:40.000000000 +0300
+++ ttt/buttonedit.c	2011-05-04 16:13:09.461995684 +0300
@@ -37,7 +37,7 @@
 			0,                				/* количество кешируемых в памяти объектов 		*/
 			(GInstanceInitFunc)gtk_button_entry_init, /* конструктор объекта 				*/
 		};
-		button_entry_type = g_type_register_static(GTK_TYPE_EVENT_BOX, 
+		button_entry_type = g_type_register_static(GTK_TYPE_ENTRY, 
 													"GtkButtonEntry", 
 													&button_entry_info, 0);
 	}
@@ -52,7 +52,7 @@
 	GtkWidgetClass 	* widget_class 	= GTK_WIDGET_CLASS(class);
 	GtkObjectClass 	* object_class 	= GTK_OBJECT_CLASS(class);
 	
-	parent_class = (GtkEntryClass*)g_type_class_peek_parent(class);
+	parent_class = GTK_ENTRY_CLASS(g_type_class_peek_parent(class));
 	
 	object_class->destroy 				= gtk_button_entry_destroy;
 	gobject_class->finalize 			= gtk_button_entry_finalize;
@@ -76,16 +76,6 @@
 static void 
 gtk_button_entry_init(GtkButtonEntry * button_entry)
 {
-	GValue val = { 0, };
-	g_value_init(&val, G_TYPE_BOOLEAN);
-	g_value_set_boolean(&val, TRUE);
-	
-	g_object_set_property(&button_entry->parent, "visibility", &val); 
-	g_value_unset (&val);
-	
-//	gtk_entry_set_visibility(&button_entry->parent, TRUE);
-
-	
 }
 
 GtkWidget * 
diff -urN ttt-orig/buttonedit.h ttt/buttonedit.h
--- ttt-orig/buttonedit.h	2011-05-03 15:36:04.000000000 +0300
+++ ttt/buttonedit.h	2011-05-04 16:09:15.833995712 +0300
@@ -20,14 +20,14 @@
 
 
 typedef struct {
-	GtkEntry parent;
+	GtkEntry entry;
 	GList * buttons_info;
 	
 } GtkButtonEntry;
 
 
 typedef struct {
-	GtkEntryClass parent;
+	GtkEntryClass parent_class;
 	void (* pressed)(int num); /*!< 'num' is index of the pressed button in 'buttons_info' list */
 	void (* released)(int num);
 	

с настройками GtkEntry, думаю, сам разберешься. но лучше наследоваться от box-а какого-нибудь, и делать композитный виджет, а не лепить свой.

ananas ★★★★★ ()
Ответ на: комментарий от ananas

Как я понял проблема была в этом:

 button_entry_type = g_type_register_static(GTK_TYPE_ENTRY,... 

но лучше наследоваться от box-а какого-нибудь, и делать композитный виджет, а не лепить свой.

Я хочу на текстовом поле разместить несколько кнопок с краю, мне подумалось что GtkEntry будет в самый раз для такого виджета, а если свой делать с нуля, то это его нужно рисовать, курсор обрабатывать, и т.д это практически тот же самый GtkEntry и получается... если что-то новое делать, чьего функционала нет среди стандартных, там да... имхо.

xterro ★★★★★ ()
Ответ на: комментарий от xterro

не только. ссылка на родительский класс должна обзываться parent_class, а не parent.

насколько я понимаю, у тебя класс, очень похожий на GtkSpinButton, так что смотри на его имплементацию

ananas ★★★★★ ()
Ответ на: комментарий от ananas

Хм, я думал без разницы как называть parent или parent_class. Да похожий, пытаюсь сделать текстовое поле с кнопкой с краю(которая с тремя точкаи ещё), как например кнопка выбора пути в винде. Спасибо, пойду поковыряю spinbutton :)

xterro ★★★★★ ()
Ответ на: комментарий от xterro

> Хм, я думал без разницы как называть parent или parent_class. Да похожий, пытаюсь сделать текстовое поле с кнопкой с краю(которая с тремя точкаи ещё)

для этого хватит иконок в GtkEntry

ananas ★★★★★ ()
Ответ на: комментарий от ananas

Там их можно только две расположить, слева и справа по одной, а мне нужно чтобы была возожность располагать несколько штук подряд, типа как в DevExpress , эдакое универсальное решение www.devexpress.com/Products/NET/Controls/WinForms/Editors/Editors/ButtonEdit.xml

xterro ★★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.