Gtk.CssProvider() how do ID based selectors work in Gtk3?
Asked Answered
F

2

8

I've been fiddling with this on and off for a couple of days but just can't seem to come to grips with what the issues might be.

Essentially I'm trying to style some Gtk Widgets in Gtk3 using CSS style declarations, nothing complicated but just trying to target a specific element by its id/name. The Gtk documentation for Gtk.CssProvider() says that

#widgetname { background-color: #333333; }

should work as a valid selector for a widget with its name set to "widgetname" but I just can't seem to make it work. I thought originally that it was the CSS not loading but I can target a top-level widget like so:

GtkWindow { background-color: #333; }

and it will apply the style to the window and I can see the background color has changed. I've tried using the name as an ID for a couple of different types of widgets (GtkEventBox, GtkTextView, GtkStatusBar, GtkBox) and the ID based selector just doesn't seem to work.

Here's a shortened snippet of how I'm loading the css:

css = Gtk.CssProvider()

# css.load_from_file(file)
css.load_from_data('''

GtkWindow {
    background-color: #333;
}

GtkEventBox {
    background-color: #333;
}

#statusbarwrap, #textview_event_wrap, #box1 {
     background-color: #333;
}

''')

style_context = self.get_style_context()
style_context.add_provider(
    css,
    Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)

Here is the docs for GtkCssProvider https://developer.gnome.org/gtk3/3.7/GtkCssProvider.html

Example 24 on that page (just scroll down a page or two) shows that the #ID selector is valid and I'm setting the name for the widgets in Glade.

Any help would be greatly appreciated.

Flimflam answered 24/5, 2013 at 17:58 Comment(0)
B
7

We can use 'gtk_widget_set_name()' to give this widget a name(ID).

win = Gtk.Window()
win.set_name('main_window')

then '#main_window' can be used as the ID selector in CSS3:

#main_window {
  background-color: ...
}

If you open a glade file using a text editor, you can find out that, the name of widget is actually taged as id, like this:

<object class="GtkWindow" id="window1">

Note that, the name of a widget should not contain special characters like *, #, or >, which are part of CSS syntax.

Beeeater answered 27/5, 2013 at 1:55 Comment(7)
When using Glade, the CSS identifier is set by the name property and not the id attribute. See Locoluis's answer.Hyder
copy paste? codesd.com/item/…Riga
@jdknight, I am new to the world of GTK3/Rust and the CSS is wanting. With that said, what is Glade?Reiterant
@Daniel, Glade refers to "Glade Interface Designer", a UI to help build GTK interfaces. The application works with .glade files (XML), which can be used to generate applicable UI source code.Hyder
@jdknight, thank you, but is it done in the browser? I thought GTK was desktop type of applications.Reiterant
@Daniel, Glade itself is a GTK application. Glade is not associated with a browser. I assume the idea of using CSS may give an indication that a browser is involved; however, CSS can be used outside of the context of browsers. Glade/XML documents can be styled with CSS, which then Glade uses in part with its translation to respective GTK code, and GTK may use CSS to style the windows/widgets it manages.Hyder
@jdknight, I wish I would have known about Glade before. We ended up creating our own layouts framework with GTK3/Rust.Reiterant
H
5

The following is a complete example, which I'm posting here to clarify the confusion between names and IDs in Gtk3+CSS:

german.py:

# coding: utf-8
from gi.repository import Gtk, Gdk
import time

builder = Gtk.Builder()
builder.add_from_file("german.glade")
builder.connect_signals({"closeApplication": Gtk.main_quit})

screen = Gdk.Screen.get_default()

css_provider = Gtk.CssProvider()
css_provider.load_from_path('german.css')

context = Gtk.StyleContext()
context.add_provider_for_screen(screen, css_provider,
  Gtk.STYLE_PROVIDER_PRIORITY_USER)

window = builder.get_object("applicationwindow1")
window.show_all()

Gtk.main()

german.css:

#blackBox {
  background-color: black;
}
#redBox {
  background-color: red;
}
.goldBox {
  background-color: gold;
}

german.glade:

<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.16.1 -->
<interface>
  <requires lib="gtk+" version="3.0"/>
  <object class="GtkApplicationWindow" id="applicationwindow1">
    <property name="can_focus">False</property>
    <signal name="delete-event" handler="closeApplication" swapped="no"/>
    <child>
      <object class="GtkBox" id="box1">
        <property name="visible">True</property>
        <property name="can_focus">False</property>
        <property name="orientation">vertical</property>
        <child>
          <object class="GtkEventBox" id="blackBox">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <child>
              <placeholder/>
            </child>
          </object>
          <packing>
            <property name="expand">True</property>
            <property name="fill">True</property>
            <property name="position">0</property>
          </packing>
        </child>
        <child>
          <object class="GtkEventBox" id="eventbox2">
            <property name="name">redBox</property>
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <child>
              <placeholder/>
            </child>
          </object>
          <packing>
            <property name="expand">True</property>
            <property name="fill">True</property>
            <property name="position">1</property>
          </packing>
        </child>
        <child>
          <object class="GtkEventBox" id="eventbox3">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <child>
              <placeholder/>
            </child>
            <style>
              <class name="goldBox"/>
            </style>
          </object>
          <packing>
            <property name="expand">True</property>
            <property name="fill">True</property>
            <property name="position">2</property>
          </packing>
        </child>
      </object>
    </child>
  </object>
</interface>

Result:

Three boxes aligned vertically, like the flag of Germany. Except that the first box is NOT black, because #name refers to an object with a matching "name" property, not to an object with that id.

It took me a while to figure it out. I'm new with Gtk3 myself...

Hypnotic answered 26/5, 2015 at 22:5 Comment(3)
what if we don't use glade?Durazzo
@JackHerer In Python: Gtk.Widget.get_name() Gtk.Widget.set_name() corresponds to the CSS id selector. The id attribute on the Glade XML file appears to be only used by GtkBuilder, not by Gtk itself.Hypnotic
Ok cool, thanks. I try to stay away from the GtkBuilder/Glade/Anjuta side and just stick to pure python.Durazzo

© 2022 - 2024 — McMap. All rights reserved.