Фон пользовательского виджета GTK отображается сплошным черным цветом.

Я пытаюсь создать собственный виджет в GTK 3. Я заметил проблемы с рисованием, которые появляются только с некоторыми темами GTK, в то время как все другие темы работают отлично. Я сузил проблему до кода, рисующего фон, вызвав gtk_render_background(). В некоторых темах фон отображается сплошным черным цветом, хотя это не цвет фона тем по умолчанию. Ниже приведена упрощенная версия моей функции рисования.

static void gtk_databox_ruler_draw_ticks(GtkDataboxRuler *ruler)
{
    GtkWidget *widget;
    GtkStateFlags state;
    cairo_t *cr;
    GtkStyleContext *style_context;
    gint width, height;

    if (!gtk_widget_is_drawable(GTK_WIDGET(ruler))) {
        return;
    }

    widget = GTK_WIDGET(ruler);
    state = gtk_widget_get_state_flags(widget);
    style_context = gtk_widget_get_style_context(widget);

    gtk_style_context_save(style_context);
    gtk_style_context_add_class(style_context, GTK_STYLE_CLASS_DEFAULT);
    gtk_style_context_set_state(style_context, state);

    /* <test-code> */
    GdkRGBA test;
    gtk_style_context_get_background_color(style_context, gtk_widget_get_state_flags(widget), &test);
    /* </test-code> */

    width = gtk_widget_get_allocated_width(widget);
    height = gtk_widget_get_allocated_height(widget);

    cr = cairo_create(ruler->priv->backing_surface);

    gtk_render_background(style_context, cr, 0, 0, width, height);

    gtk_style_context_restore(style_context);
    cairo_destroy(cr);
}

Я добавил тестовый код для запроса цвета фона и установил точку останова в gdb:

При использовании темы Ubuntu Ambiance:

(gdb) print test
$1: test = {red = 0.94901960784313721, green = 0.94509803921568625, 
  blue = 0.94117647058823528, alpha = 1}

При использовании темы Ubuntu HighContrast:

(gdb) print test
$1: test = {red = 0, green = 0, blue = 0, alpha = 0}

Теперь мне интересно, неправильно ли я использую новый GtkStyleContext или тема не работает. Как я могу сузить источник проблемы?

Я также был бы признателен, если бы кто-нибудь мог указать мне на хорошее введение в GtkStyleContext. Официальная документация API не так уж полезна для понимания фундаментальной концепции.


person dasup    schedule 03.09.2012    source источник
comment
Я не знаю, где вы рисуете, но вы могли рисовать виджет только в его виртуальном методе рисования. В вашем коде так много вещей, которые вызовут неожиданное поведение, что что угодно может сделать это.   -  person erick2red    schedule 04.09.2012
comment
Показанная выше функция gtk_databox_ruler_draw_ticks вызывается из функции отрисовки виджета (GtkWidgetClass->draw). Можете ли вы указать на вещи в приведенном выше коде, которые необходимо исправить?   -  person dasup    schedule 13.09.2012
comment
Не знаю, поможет ли это, но вы можете посмотреть здесь   -  person erick2red    schedule 13.09.2012


Ответы (3)


По прошествии более года мне пришлось снова заняться этой проблемой, потому что она также возникает при использовании стиля GTK3 по умолчанию (встроенного), то есть когда моя программа используется в системе, в которой не установлены темы и т. д.

Похоже, что источником проблемы является то, что некоторые темы GTK определяют цвет фона для «случая по умолчанию», а другие — нет.

тема GTK3 по умолчанию:

…
* {
  color: @fg_color;
  border-color: shade (@bg_color, 0.6);
  padding: 2px;
  -GtkWindow-resize-grip-width: 0;
  -GtkWindow-resize-grip-height: 0;
  -GtkWindow-decoration-button-layout: 'icon:minimize,maximize,close';
}

GtkWindow, .button, .slider {
  background-color: @bg_color;
}
…

Тема Адвайты:

…
* {
    /* inherit the color from parent by default */
    color: inherit;
    background-color: @theme_bg_color;
}
…

Чтобы отрисовать фон, мне просто нужно выбрать класс виджета, цвет фона которого определен для всех (большинства) тем. Для этого я использую класс кнопки:

gtk_style_context_add_class(style_context, GTK_STYLE_CLASS_BUTTON); 
person dasup    schedule 02.03.2014

Какую версию Ubuntu и GTK3 вы используете?

Возможно, вам нужно вызвать gtk_style_context_set_junction_sides().

Вас также может заинтересовать эта информация от Бенджамина Отте, одного из разработчиков GTK. Как работают стили GTK, также доступно Стили GTK+3.

person mike    schedule 03.09.2012
comment
Я использую Ubuntu 12.04, libgtk версии 3.4.2-0ubuntu0. Я добавил gtk_style_context_set_junction_sides с GTK_JUNCTION_BOTTOM, установленным после gtk_style_context_add_class, но это не помогло. Спасибо за ссылку, но я думаю, что она больше фокусируется на стороне CSS, в то время как мне нужно больше информации о стороне GtkStyleContext (т.е. рендеринг, что делает сохранение/восстановление, как работают классы). - person dasup; 04.09.2012

Часть подвоха здесь может заключаться в том, что все больше и больше не обязательно должен быть один цвет фона.

Согласно документации https://developer.gnome.org/gtk3/stable/GtkStyleContext.html#gtk-style-context-get-background-color:

«Эта функция гораздо менее полезна, чем кажется, и ее не следует использовать во вновь написанном коде. В CSS нет понятия «фоновый цвет», так как фоном может быть изображение, градиент или любой другой шаблон, включая сплошной. цвета."

person atrus    schedule 30.11.2015
comment
Спасибо за указание на это! Обратите внимание, что в приведенном выше коде я использовал gtk_style_context_get_background_color только для целей тестирования/отладки. Реальный код вызывает gtk_render_background, который, как я предполагаю, имеет дело со всеми видами фоновых определений. Однако вызов gtk_render_background приводит к сплошному черному фону с определенными темами. - person dasup; 01.12.2015