Изменение предварительных настроек виджета программно в gtkmm3/gtk3

Я начал портировать некоторые из своих приложений gtkmm2 на gtkmm3, и мне не совсем понятен правильный механизм изменения свойств, таких как цвет виджета, из приложения в ответ на изменение состояния. Вот краткий пример, иллюстрирующий то, чего я пытаюсь добиться, а именно инвертировать цвета изображения кнопки и текста в зависимости от определенного состояния:

Я создаю окно (Gwin) и жестко задаю короткую строку CSS, которой достаточно, чтобы определить начальное состояние виджетов при запуске:

int main(int argc, char *argv[])
{
   try
   {
        Gtk::Main *kit(new Gtk::Main(argc, argv));
        GWin *dl(new GWin(sdi, argc, argv));

        auto screen = dl->get_screen();
        Glib::RefPtr<Gtk::CssProvider> css(Gtk::CssProvider::create());
        Glib::RefPtr<Gtk::StyleContext> style(dl->get_style_context());

        Glib::ustring theme(
                      "@define-color bg rgb(57.64%, 48.62%, 36.47%);"
                      "@define-color BtnBg rgb(23.13%, 19.60%, 16.07%);"
                      ".background { background-color: @bg; }"
                      "button"
                      "{"
                      "   background-image:image(@BtnBg);"
                      "   border-color: @bg;"
                      "   color: rgb(80.%, 80.%, 80.%);"
                      "   padding-left: 4px;"
                      "   padding-right: 4px;"
                      "}"
                      "button:hover"
                      "{"
                      "   background-image:image(rgb(77%, 81%, 84%));"
                      "   color: rgb(0.%, 0.%, 0.%);"
                      "}"
                      "#LSK0 { background-image: image(@bg); border-color:@bg }"
                      "#RSK0 { background-image: image(@bg); border-color:@bg }"
                      );
      css->load_from_data(theme);
      style->add_provider_for_screen(screen, css, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);



     dl->Run();
     delete kit;
   }
   catch(const std::string &e)
   {
      std::cout << "ERROR: GWin now exits:\n" << e << std::endl;
   }
   return(0);
}

Теперь внутри класса GWin соответствующим фрагментом кода является следующий обработчик сигнала, который работает с mRunButton Gtk::Button, который был инициализирован с помощью mRunButton.set_name("RunButton"):

void GCDU::onBtnLight(bool on)
{
   // The GTK3 code
   Glib::RefPtr<Gtk::CssProvider> css(Gtk::CssProvider::create());
   Glib::RefPtr<Gtk::StyleContext> style(mRunButton.get_style_context());

   Glib::ustring theme(on ?
                       "#RunButton { background-image: image(rgb(80%, 80%, 80%); color: rgb(0.%, 0.%, 0.%); }"
                       :
                       "#RunButton { background-image: image(rgb(23.13%, 19.60%, 16.07%)); color: rgb(80.%, 80.%, 80.%); }"
                      );
   css->load_from_data(theme);
   style->add_provider(css, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);

   // The old GTK2 code
   //Gdk::Color c(mButtonBG);
   //Gdk::Color f;
   //if(on)
   //{
   //   c.set("white");
   //   f.set("black");
   //}
   //else
   //{
   //   f.set("white");
   //}
   //mRunButton.modify_bg(Gtk::STATE_NORMAL, c);
   //mRunButton.get_child()->modify_fg(Gtk::STATE_NORMAL, f);
}

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

Спасибо за внимание к вопросу.


person codeZonkey    schedule 27.10.2017    source источник


Ответы (1)


Что ж, после дополнительных исследований таких вопросов, как это и этоя нашел то, что я считаю правильным способом делать то, что мне нужно.

В основном определите свойства для состояний, которые стиль виджета будет содержать при добавлении поставщика CSS в окно:

Обновлено из main() выше в вопросе:

Glib::ustring theme(
                      "@define-color bg rgb(57.64%, 48.62%, 36.47%);"
                      "@define-color BtnBg rgb(23.13%, 19.60%, 16.07%);"
                      ".background { background-color: @bg; }"
                      "button"
                      "{"
                      "   background-image:image(@BtnBg);"
                      "   border-color: @bg;"
                      "   color: rgb(80.%, 80.%, 80.%);"
                      "   padding-left: 4px;"
                      "   padding-right: 4px;"
                      "}"
                      "button:hover"
                      "{"
                      //"   background-image:image(rgb(77%, 81%, 84%));"
                      "   background-image:image(#FF4300);"
                      "   color: rgb(100.%, 100.%, 100.%);"
                      "}"
                      "#LSK0 { background-image: image(@bg); border-color: @bg }"
                      "#RSK0 { background-image: image(@bg); border-color: @bg }"
                      ".RunButton { background-image: image(rgb(80%, 80%, 80%)); color: rgb(0.%, 0.%, 0.%); }"
                      );

Также обратите внимание, что свойства стиля «RunButton» теперь указаны как класс (.RunButton), а НЕ как идентификатор (#RunButton).

Это добавило стиль как класс внутри контекста оконных виджетов, но пока не применяет его ни к чему. Затем программно во время выполнения кода и в ответ на событие изменения состояния стиль виджета обновляется путем добавления и удаления классов свойств стиля:

void GWin::onBtnLight(bool on)
{
   if(on)
   {
      mRunButton.get_style_context()->add_class("RunButton");
   }
   else
   {
      mRunButton.get_style_context()->remove_class("RunButton");
   }
}

Теперь цвета кнопок и меток на виджете переключаются между классом стиля RunButton и классом стиля по умолчанию.

person codeZonkey    schedule 31.10.2017