2010-06-09 3 views
7

C에서 Gtk 라이브러리를 사용하여 Gtk 버튼 (예 :)을 복제하고 앱의 다른 곳에 포장하는 방법이 있습니까? 같은 위젯을 두 번 포장 할 수 없다는 것을 안다.) (Gtk 위젯을 복사하는 좋은 방법이 있습니까?

GtkButton *a = g_object_new(GTK_TYPE_BUTTON, "label", "o_0", NULL); 
GtkButton *b = g_memdup(a, sizeof *a); 
gtk_box_pack_start_defaults(GTK_BOX(vbox), GTK_WIDGET(b)); 

이 중 VBOX를 만들고 창에서 팩 및 아마 gtk_main을 실행되는 코드를 둘러싸고있다 : 그리고이 코드는 분명히 작동하지만 버튼의 단순 복사본을 시도 할 때 발생하는 표시하지 않을 것이라고 . 이 오류 메시지를 이해하기 위해 이러한 하드가 발생합니다 : 같은 라인을 따라

(main:6044): Gtk-CRITICAL **: gtk_widget_hide: assertion `GTK_IS_WIDGET (widget)' failed 

(main:6044): Gtk-CRITICAL **: gtk_widget_realize: assertion `GTK_WIDGET_ANCHORED (widget) || GTK_IS_INVISIBLE (widget)' failed 
** 
Gtk:ERROR:/build/buildd/gtk+2.0-2.18.3/gtk/gtkwidget.c:8431:gtk_widget_real_map: assertion failed: (GTK_WIDGET_REALIZED (widget)) 

을, 난 내 자신의 G 객체 (필요하지 않게의 GTK 위젯)을 작성한다면, 복사 생성자를 작성하는 좋은 방법이있다. 그것은 선택적인 후크를 가진 인터페이스이어야하고 클래스의 계층 구조를 어떤 식 으로든 다루는 속성에 주로 기반해야한다고 생각합니다.

나는이 작업을 수행 할 것 :

GtkButton *b = copyable_copy(COPYABLE(a)); 

GtkButton는 이론적 복사 가능한 인터페이스를 사용할 수 있다면.

+0

후크와 물건을 제공하여 '복사 가능'한 GObject 인터페이스를 만들 수 있습니다. 글을 쓰고 싶지는 않겠지 만, 아마도 까다로워 질 것입니다 ... – Spudd86

답변

3

속성을 축복하는 클론은 실행 가능한 솔루션입니다.

나는 많은 주들이 속성들에 노출되지 않도록주의를 기울이지 만 (모든 적절한 위젯은 속성들에 의해 GtkBuilder과 함께 사용 가능하도록 완전히 정의되어야 함) 코너 케이스가 많으면 강력한 복제를 어렵게 만듭니다 (인터페이스와 컨테이너 내 마음에 오는 첫 번째 것).

+0

고마워, 이것이 GObject에 대한 일반적인 복사 생성자가 될 수있는 가장 좋은 방법이다. – Jake

+1

'GtkWidget :: margin' 및'GtkWidget :: expand' 속성도 설정하지 않으려합니다. 다른 속성을 덮어 씁니다. – ptomato

+0

이것은 당신이 테스트 한만큼 효과가 있을지 모르지만 다른 답변과 그 코멘트에 여러 가지 이유로 제시되어 사람들에게 안전 추천을 받는다는 의미에서 "실행 가능"하지 않습니다. 따라서 "GObject에 일반 복사 생성자가있을 수있는 최선"이 아니며이 질문에 대한 실제 답변이 아닙니다. (좋은 방법이 있을까요? 아니요,하지만 여기에는 상상할 수 없을만큼 약한 해킹이 있습니다. ') –

4

저는 그렇게 생각하지 않습니다. 내가 아는 한, 위젯이 외부에서 액세스 할 수있는 속성의 모든 상태를 유지한다는 보장은 없습니다. 위젯이 내보내기하지 않아 상태를 "숨 깁니다". 외부에서 복사 할 수있는 방법이 없습니다.

기술적으로 위젯은 구현 외부에 표시되지 않는 struct 코어에 필드를 포함 할 수 있으므로 바이트를 지정하려는 경우가 아니면 memcpy() 바보를 사용하여 비트를 복사 할 수 없습니다 수동으로 계산하고 리터럴을 사용하여 계산합니다.

위젯은 사본이 여전히 작동 할 수있는 속성을 통해 충분한 위젯을 노출하고 아마도 사소한 결함 만 보여줄 가능성이 높습니다. 그것은 꽤 멋진 해킹 일 것입니다. gtk-devel-list 메일 링리스트에서 핵심 GTK + 개발자에게 직접 문의하는 것이 좋습니다. 위젯을 복제하는 것은 비록 그 사소한 아니다

GObject * 
g_object_clone(GObject *src) 
{ 
    GObject *dst; 
    GParameter *params; 
    GParamSpec **specs; 
    guint n, n_specs, n_params; 

    specs = g_object_class_list_properties(G_OBJECT_GET_CLASS(src), &n_specs); 
    params = g_new0(GParameter, n_specs); 
    n_params = 0; 

    for (n = 0; n < n_specs; ++n) 
     if (strcmp(specs[n]->name, "parent") && 
      (specs[n]->flags & G_PARAM_READWRITE) == G_PARAM_READWRITE) { 
      params[n_params].name = g_intern_string(specs[n]->name); 
      g_value_init(&params[n_params].value, specs[n]->value_type); 
      g_object_get_property(src, specs[n]->name, &params[n_params].value); 
      ++ n_params; 
     } 

    dst = g_object_newv(G_TYPE_FROM_INSTANCE(src), n_params, params); 
    g_free(specs); 
    g_free(params); 

    return dst; 
} 

하지만, 위의 방법은 (확인을위한 GtkButton에) 대부분의 경우에 사용할 수 :

+0

그것의주의는, 그러나 어쩌면 충분히 신중하지 않다! 비트 복사는 작동하지 않을 것이고, 더 많은 것은 마찬가지이다. C++ : 소스가 다른 객체에 대한 참조를 보유하고 있기 때문에 비트 단위 복사본은 참조 카운트를 증가시키지 않고 비트 참조 복사본을 추가로 작성하므로 사용 후 해제, 이중 해제 및 기타 모든 공포 방식으로 이어집니다. 또한, GTK + 개발자들이 여기에 대해 관심을 갖지 않을 것이라고 확신합니다. 이유는 여기에 있습니다. IMO도 마찬가지입니다. –

관련 문제