Как получить стандартные системные цвета для пользовательского виджета

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

Я пробовал это, но я получаю только черный или белый, а не фактические используемые цвета:

bool MyWidget::on_draw(const Cairo::RefPtr<Cairo::Context>& cr) {
    Gdk::Cairo::set_source_rgba(cr,
        get_style_context()->get_color(Gtk::STATE_FLAG_SELECTED));
}

Каков правильный способ получить стандартные цвета с помощью gtkmm, чтобы, если пользователь изменит свою цветовую тему, изменения также были отражены здесь?

Или считается лучшей практикой определить некоторые новые стили CSS, которые унаследованы от стандартных системных, чтобы люди могли переопределять цвета только для моего виджета, если они хотят, не затрагивая другие?


person Malvineous    schedule 08.03.2015    source источник


Ответы (2)


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

Мне пришлось добавить это в конструктор виджета:

this->get_style_context()->add_class(GTK_STYLE_CLASS_ENTRY);

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

this->get_style_context()->add_class(GTK_STYLE_CLASS_DEFAULT);

И в моей функции рендеринга временно установите стили ввода текста, чтобы получить цвет:

auto cxStyle = this->get_style_context();
cxStyle->context_save();
cxStyle->add_class(GTK_STYLE_CLASS_ENTRY);
Gdk::Cairo::set_source_rgba(cr, cxStyle->get_background_color(Gtk::STATE_FLAG_SELECTED));
cr->fill();
cxStyle->context_restore();

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

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

person Malvineous    schedule 12.03.2015
comment
Вы можете настроить контекст стиля любым удобным для вас способом, а затем вызвать с ним функцию render_background(). Вы также можете определить класс стиля любым способом. Я также хотел бы отметить, что get_background_color() устарел, потому что он не имеет смысла в CSS (изображение или градиент не являются цветом, и вы можете использовать их все в CSS). Суть в том, что если вы используете API контекста стиля, вам также необходимо использовать API render_*. - person ebassi; 12.03.2015
comment
@ebassi: я просто ухожу с кастомного gtkmm пример виджета - если get_background_color() устарел, возможно, стоит обновить руководство! Я понятия не имею о классах стилей - есть ли пример, подобный этому руководству, который показывает лучшие практики их использования? - person Malvineous; 13.03.2015
comment
Вы должны сообщить об ошибке gtkmm — bugzilla.gnome.org/ — gtkmm — это привязка, и она поддерживается отдельно от самого GTK. Для классов стилей см. GtkCssProvider для загрузки пользовательского CSS, GtkStyleContext::add_provider() для добавления нового поставщика и GtkStyleContext::add_class() для добавления класса к виджету; затем вам нужно написать нужный CSS. - person ebassi; 13.03.2015

Правильный способ рендеринга фона виджета — использовать gtk_render_background()< /а>. Эта функция будет учитывать состояние и стиль виджета.

Ваш код выше становится:

bool
MyWidget::on_draw (const Cairo::RefPtr<Cairo::Context>& cr)
{
  double w = get_allocated_width(), h = get_allocated_height();
  Glib::RefPtr<Gtk::StyleContext> context = get_style_context();

  context->render_background(cr, 0, 0, w, h);

  return true;
}

Таким образом, ваш виджет всегда будет обновляться в соответствии с темой.

Если вы хотите управлять цветом и стилем вашего виджета, вы должны использовать дополнительный Gtk::StyleProvider для вашего приложения, чтобы загрузить пользовательский фрагмент CSS с желаемыми классами стиля.

person ebassi    schedule 09.03.2015
comment
Любые предложения о том, как получить текущий цвет выделения, если это с помощью CSS? Мой виджет отображает набор элементов, и я хотел бы использовать цвет выделения, чтобы изменить фон выбранного в данный момент элемента, но не всего элемента управления, который должен оставаться с фоном по умолчанию. - person Malvineous; 10.03.2015
comment
Вы можете сохранить состояние виджета, убрать из его флагов состояние SELECTED, отрендерить фон по всему выделению; затем верните состояние SELECTED и визуализируйте фон только в той области, которую вы хотите показать как выделенную. - person ebassi; 10.03.2015
comment
К сожалению, это не работает - render_background() белый, независимо от того, звоню ли я set_state_flags(Gtk::STATE_FLAG_SELECTED, true) или нет! - person Malvineous; 12.03.2015
comment
У вас есть стиль, связанный с виджетом? - person ebassi; 12.03.2015
comment
Я не знаю, я просто ухожу руководство по пользовательскому виджету gtkmm. Если бы стили были нужны, вы бы подумали, что они были бы частью учебника! - person Malvineous; 13.03.2015
comment
get_style_context() вернет Glib::RefPtr‹Gtk::StyleContext›, а не Gtk::StyleContext*. В то время я пытался отредактировать ответ, но только что заметил, что редактирование было отклонено. - person murrayc; 09.05.2015