Checkbox with CSS in GLade Python

2019-07-13 00:35发布

问题:

everyone I am trying to change the colors of the checkboxes when they are pressed because I am doing a job that requires their use. I am using them with no "Drawing Indicator" attribute, so I need them to have a different color when pressed, because it does not look very well and is not very appealing. Is there any way to do this? The version of my glade is 3.18.3. Im using a Pi3 model B

This is my code:

import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
from gi.repository import GObject as gobject
from gi.repository import Gtk, Gdk
import gtk


#Checkbuttons


def on_checkbutton_toggled(button, name):
    if (button.get_active()):
        state = "Active"

    else:
        state = "Inactive"
    print("port " + name + " toggled, state is " +state)


def start(button):
    print ("Button start clicked")

def save(button):
    print ("Button save clicked")

def clear(button):
    print ("Button clear clicked")

def select_all(button):
    print ("Button all clicked")

def details(button):
    print ("Button details clicked")

def click_for_help(button):
    print ("Button help clicked")

def gtk_style():
    css= b"""
.button:checked {
    color:white;
    background:red;
}
"""
    style_provider = Gtk.CssProvider()
    style_provider.load_from_data(css)

    Gtk.StyleContext.add_provider_for_screen(
        Gdk.Screen.get_default(),
        style_provider,
        Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
    )

    gtk_style()

# GUI (Graphical User Interface)
builder = Gtk.Builder()                                                                                                                                  
builder.add_from_file("/home/pi/Desktop/Wi-Green_Project/schedule-0.4.3/Wi-GreenSPM.glade")                                                                                                         
handlers = {
        "action_start": start,
        "action_save": save,
        "action_clear": clear,
        "action_all": select_all,
        "action_details": details,
        "action_help":click_for_help


    }

builder.connect_signals(handlers)
window = builder.get_object("window_WG")


checkb1 = builder.get_object("port1")
checkb2 = builder.get_object("port2")
checkb3 = builder.get_object("port3")
checkb4 = builder.get_object("port4")
checkb5 = builder.get_object("port5")
checkb6 = builder.get_object("port6")
checkb7 = builder.get_object("port7")
checkb8 = builder.get_object("port8")
checkb9 = builder.get_object("port9")
checkb10 = builder.get_object("port10")
checkb11 = builder.get_object("port11")
checkb12 = builder.get_object("port12")
checkb13 = builder.get_object("port13")
checkb14 = builder.get_object("port14")
checkb15 = builder.get_object("port15")
checkb16 = builder.get_object("port16")
checkb17 = builder.get_object("port17")
checkb18 = builder.get_object("port18")
checkb19 = builder.get_object("port19")
checkb20 = builder.get_object("port20")
checkb21 = builder.get_object("port21")
checkb22 = builder.get_object("port22")
checkb23 = builder.get_object("port23")
checkb24 = builder.get_object("port24")

checkb1.connect ("toggled", on_checkbutton_toggled, "1")
checkb2.connect ("toggled", on_checkbutton_toggled, "2")
checkb3.connect ("toggled", on_checkbutton_toggled, "3")
checkb4.connect ("toggled", on_checkbutton_toggled, "4")
checkb5.connect ("toggled", on_checkbutton_toggled, "5")
checkb6.connect ("toggled", on_checkbutton_toggled, "6")
checkb7.connect ("toggled", on_checkbutton_toggled, "7")
checkb8.connect ("toggled", on_checkbutton_toggled, "8")
checkb9.connect ("toggled", on_checkbutton_toggled, "9")
checkb10.connect ("toggled", on_checkbutton_toggled, "10")
checkb11.connect ("toggled", on_checkbutton_toggled, "11")
checkb12.connect ("toggled", on_checkbutton_toggled, "12")
checkb13.connect ("toggled", on_checkbutton_toggled, "13")
checkb14.connect ("toggled", on_checkbutton_toggled, "14")
checkb15.connect ("toggled", on_checkbutton_toggled, "15")
checkb16.connect ("toggled", on_checkbutton_toggled, "16")
checkb17.connect ("toggled", on_checkbutton_toggled, "17")
checkb18.connect ("toggled", on_checkbutton_toggled, "18")
checkb19.connect ("toggled", on_checkbutton_toggled, "19")
checkb20.connect ("toggled", on_checkbutton_toggled, "20")
checkb21.connect ("toggled", on_checkbutton_toggled, "21")
checkb22.connect ("toggled", on_checkbutton_toggled, "22")
checkb23.connect ("toggled", on_checkbutton_toggled, "23")
checkb24.connect ("toggled", on_checkbutton_toggled, "24")
#---------------------------------------------------------------------------------------

window.connect("destroy", Gtk.main_quit)

window.show_all()

Gtk.main()

回答1:

Since the Gtk.CheckButton is set without draw indicator, then it basically becomes a togglebutton and the CSS class, on Gtk+ 3.18 is .button.

Defining a provider for this class and adding it to the screen it's rather simple.

First, the relevant css code is:

.button:checked {
    color: white;
    background: red;
}

For this example, the button, when checked, will have a red background with white text.

A working example would be:

#!/usr/bin/python3
from gi.repository import Gtk, Gdk
import sys


class MyWindow(Gtk.Window):

    def __init__(self):
        Gtk.Window.__init__(self, title="Hello World")
        self.set_name('MyWindow')
        self.set_default_size(600, 300)

        self.box = Gtk.HBox()
        self.box.set_halign(Gtk.Align.CENTER)
        self.box.set_valign(Gtk.Align.CENTER)
        self.add(self.box)

        self.button1 = Gtk.CheckButton(label="1")
        self.button1.set_mode (False);
        self.button1.connect("clicked", self.on_button1_clicked)
        self.box.pack_start(self.button1, True, True, 0)

        self.button2 = Gtk.CheckButton(label="2")
        self.button2.set_mode (False);
        self.button2.connect("clicked", self.on_button2_clicked)
        self.box.pack_start(self.button2, True, True, 0)

    def on_button1_clicked(self, widget):
        print("Button 1")

    def on_button2_clicked(self, widget):
        print("Button 2")


def main(argv):

    def gtk_style():
        css = b"""
.button:checked {
    color: white;
    background: red;
}
        """
        style_provider = Gtk.CssProvider()
        style_provider.load_from_data(css)

        Gtk.StyleContext.add_provider_for_screen(
            Gdk.Screen.get_default(),
            style_provider,
            Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
        )

    gtk_style()
    win = MyWindow()
    win.connect("delete-event", Gtk.main_quit)
    win.show_all()
    Gtk.main()

if __name__ == "__main__":
    main(sys.argv)

The result is something like this:

This will apply the same behavior to all checkbuttons, so if the idea is to use this solution only on those numbered buttons but want another checkbuttons (as togglebuttons) on the application then you need to add/remove a style class or add a custom style class, etc.

EDIT: Solving the question code not working.

The problem resides on the fact that gtk_style () is not being invoked. The call is inside its own definition:

def gtk_style():
   ...code...
   gtk_style() # <----- Here is the problem.

Python indentation is relevant. The way it is now, it becomes recursive and it's not being invoked. The solution is to remove that line and move it to the code below, following the, e.g., window.connect line.

A dummy glade file (myui.glade):

<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.19.0 -->
<interface>
  <requires lib="gtk+" version="3.16"/>
  <object class="GtkWindow" id="window1">
    <property name="can_focus">False</property>
    <child>
      <object class="GtkGrid" id="grid1">
        <property name="visible">True</property>
        <property name="can_focus">False</property>
        <child>
          <object class="GtkCheckButton" id="port1">
            <property name="label" translatable="yes">Port</property>
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <property name="receives_default">False</property>
            <property name="xalign">0</property>
            <property name="draw_indicator">False</property>
          </object>
          <packing>
            <property name="left_attach">0</property>
            <property name="top_attach">0</property>
          </packing>
        </child>
        <child>
          <object class="GtkCheckButton" id="port2">
            <property name="label" translatable="yes">Port</property>
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <property name="receives_default">False</property>
            <property name="xalign">0.5</property>
            <property name="draw_indicator">False</property>
          </object>
          <packing>
            <property name="left_attach">1</property>
            <property name="top_attach">0</property>
          </packing>
        </child>
        <child>
          <object class="GtkCheckButton" id="port3">
            <property name="label" translatable="yes">Port</property>
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <property name="receives_default">False</property>
            <property name="xalign">0.5</property>
            <property name="draw_indicator">False</property>
          </object>
          <packing>
            <property name="left_attach">2</property>
            <property name="top_attach">0</property>
          </packing>
        </child>
        <child>
          <object class="GtkCheckButton" id="port4">
            <property name="label" translatable="yes">Port</property>
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <property name="receives_default">False</property>
            <property name="xalign">0.5</property>
            <property name="draw_indicator">False</property>
          </object>
          <packing>
            <property name="left_attach">3</property>
            <property name="top_attach">0</property>
          </packing>
        </child>
        <child>
          <object class="GtkCheckButton" id="port5">
            <property name="label" translatable="yes">Port</property>
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <property name="receives_default">False</property>
            <property name="xalign">0.5</property>
            <property name="draw_indicator">False</property>
          </object>
          <packing>
            <property name="left_attach">4</property>
            <property name="top_attach">0</property>
          </packing>
        </child>
        <child>
          <object class="GtkCheckButton" id="port6">
            <property name="label" translatable="yes">Port</property>
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <property name="receives_default">False</property>
            <property name="xalign">0.5</property>
            <property name="draw_indicator">False</property>
          </object>
          <packing>
            <property name="left_attach">5</property>
            <property name="top_attach">0</property>
          </packing>
        </child>
        <child>
          <object class="GtkCheckButton" id="port7">
            <property name="label" translatable="yes">Port</property>
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <property name="receives_default">False</property>
            <property name="xalign">0.5</property>
            <property name="draw_indicator">False</property>
          </object>
          <packing>
            <property name="left_attach">6</property>
            <property name="top_attach">0</property>
          </packing>
        </child>
        <child>
          <object class="GtkCheckButton" id="port8">
            <property name="label" translatable="yes">Port</property>
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <property name="receives_default">False</property>
            <property name="xalign">0.5</property>
            <property name="draw_indicator">False</property>
          </object>
          <packing>
            <property name="left_attach">7</property>
            <property name="top_attach">0</property>
          </packing>
        </child>
        <child>
          <object class="GtkCheckButton" id="port9">
            <property name="label" translatable="yes">Port</property>
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <property name="receives_default">False</property>
            <property name="xalign">0.5</property>
            <property name="draw_indicator">False</property>
          </object>
          <packing>
            <property name="left_attach">8</property>
            <property name="top_attach">0</property>
          </packing>
        </child>
        <child>
          <object class="GtkCheckButton" id="port10">
            <property name="label" translatable="yes">Port</property>
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <property name="receives_default">False</property>
            <property name="xalign">0.5</property>
            <property name="draw_indicator">False</property>
          </object>
          <packing>
            <property name="left_attach">9</property>
            <property name="top_attach">0</property>
          </packing>
        </child>
        <child>
          <object class="GtkCheckButton" id="port11">
            <property name="label" translatable="yes">Port</property>
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <property name="receives_default">False</property>
            <property name="xalign">0.5</property>
            <property name="draw_indicator">False</property>
          </object>
          <packing>
            <property name="left_attach">10</property>
            <property name="top_attach">0</property>
          </packing>
        </child>
        <child>
          <object class="GtkCheckButton" id="port12">
            <property name="label" translatable="yes">Port</property>
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <property name="receives_default">False</property>
            <property name="xalign">0.5</property>
            <property name="draw_indicator">False</property>
          </object>
          <packing>
            <property name="left_attach">11</property>
            <property name="top_attach">0</property>
          </packing>
        </child>
        <child>
          <object class="GtkCheckButton" id="port13">
            <property name="label" translatable="yes">Port</property>
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <property name="receives_default">False</property>
            <property name="xalign">0.5</property>
            <property name="draw_indicator">False</property>
          </object>
          <packing>
            <property name="left_attach">0</property>
            <property name="top_attach">1</property>
          </packing>
        </child>
        <child>
          <object class="GtkCheckButton" id="port14">
            <property name="label" translatable="yes">Port</property>
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <property name="receives_default">False</property>
            <property name="xalign">0.5</property>
            <property name="draw_indicator">False</property>
          </object>
          <packing>
            <property name="left_attach">1</property>
            <property name="top_attach">1</property>
          </packing>
        </child>
        <child>
          <object class="GtkCheckButton" id="port15">
            <property name="label" translatable="yes">Port</property>
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <property name="receives_default">False</property>
            <property name="xalign">0.5</property>
            <property name="draw_indicator">False</property>
          </object>
          <packing>
            <property name="left_attach">2</property>
            <property name="top_attach">1</property>
          </packing>
        </child>
        <child>
          <object class="GtkCheckButton" id="port16">
            <property name="label" translatable="yes">Port</property>
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <property name="receives_default">False</property>
            <property name="xalign">0.5</property>
            <property name="draw_indicator">False</property>
          </object>
          <packing>
            <property name="left_attach">3</property>
            <property name="top_attach">1</property>
          </packing>
        </child>
        <child>
          <object class="GtkCheckButton" id="port17">
            <property name="label" translatable="yes">Port</property>
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <property name="receives_default">False</property>
            <property name="xalign">0.5</property>
            <property name="draw_indicator">False</property>
          </object>
          <packing>
            <property name="left_attach">4</property>
            <property name="top_attach">1</property>
          </packing>
        </child>
        <child>
          <object class="GtkCheckButton" id="port18">
            <property name="label" translatable="yes">Port</property>
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <property name="receives_default">False</property>
            <property name="xalign">0.5</property>
            <property name="draw_indicator">False</property>
          </object>
          <packing>
            <property name="left_attach">5</property>
            <property name="top_attach">1</property>
          </packing>
        </child>
        <child>
          <object class="GtkCheckButton" id="port19">
            <property name="label" translatable="yes">Port</property>
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <property name="receives_default">False</property>
            <property name="xalign">0.5</property>
            <property name="draw_indicator">False</property>
          </object>
          <packing>
            <property name="left_attach">6</property>
            <property name="top_attach">1</property>
          </packing>
        </child>
        <child>
          <object class="GtkCheckButton" id="port20">
            <property name="label" translatable="yes">Port</property>
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <property name="receives_default">False</property>
            <property name="xalign">0.5</property>
            <property name="draw_indicator">False</property>
          </object>
          <packing>
            <property name="left_attach">7</property>
            <property name="top_attach">1</property>
          </packing>
        </child>
        <child>
          <object class="GtkCheckButton" id="port21">
            <property name="label" translatable="yes">Port</property>
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <property name="receives_default">False</property>
            <property name="xalign">0.5</property>
            <property name="draw_indicator">False</property>
          </object>
          <packing>
            <property name="left_attach">8</property>
            <property name="top_attach">1</property>
          </packing>
        </child>
        <child>
          <object class="GtkCheckButton" id="port22">
            <property name="label" translatable="yes">Port</property>
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <property name="receives_default">False</property>
            <property name="xalign">0.5</property>
            <property name="draw_indicator">False</property>
          </object>
          <packing>
            <property name="left_attach">9</property>
            <property name="top_attach">1</property>
          </packing>
        </child>
        <child>
          <object class="GtkCheckButton" id="port23">
            <property name="label" translatable="yes">Port</property>
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <property name="receives_default">False</property>
            <property name="xalign">0.5</property>
            <property name="draw_indicator">False</property>
          </object>
          <packing>
            <property name="left_attach">10</property>
            <property name="top_attach">1</property>
          </packing>
        </child>
        <child>
          <object class="GtkCheckButton" id="port24">
            <property name="label" translatable="yes">Port</property>
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <property name="receives_default">False</property>
            <property name="xalign">0.5</property>
            <property name="draw_indicator">False</property>
          </object>
          <packing>
            <property name="left_attach">11</property>
            <property name="top_attach">1</property>
          </packing>
        </child>
      </object>
    </child>
  </object>
</interface>

Adapting your code to the dummy glade file and applying the changes to fix the code:

import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
from gi.repository import GObject as gobject
from gi.repository import Gtk, Gdk
import gtk


#Checkbuttons


def on_checkbutton_toggled(button, name):
    if (button.get_active()):
        state = "Active"

    else:
        state = "Inactive"
    print("port " + name + " toggled, state is " +state)


def start(button):
    print ("Button start clicked")

def save(button):
    print ("Button save clicked")

def clear(button):
    print ("Button clear clicked")

def select_all(button):
    print ("Button all clicked")

def details(button):
    print ("Button details clicked")

def click_for_help(button):
    print ("Button help clicked")

def gtk_style():
    css= b"""
.button:checked {
    color:white;
    background:red;
}
"""
    style_provider = Gtk.CssProvider()
    style_provider.load_from_data(css)

    Gtk.StyleContext.add_provider_for_screen(
        Gdk.Screen.get_default(),
        style_provider,
        Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
    )


# GUI (Graphical User Interface)
builder = Gtk.Builder()                                                                                                                                  
builder.add_from_file("myui.glade")                                                                                                         
handlers = {
        "action_start": start,
        "action_save": save,
        "action_clear": clear,
        "action_all": select_all,
        "action_details": details,
        "action_help":click_for_help


    }

builder.connect_signals(handlers)
window = builder.get_object("window1")

checkb1 = builder.get_object("port1")
checkb2 = builder.get_object("port2")
checkb3 = builder.get_object("port3")
checkb4 = builder.get_object("port4")
checkb5 = builder.get_object("port5")
checkb6 = builder.get_object("port6")
checkb7 = builder.get_object("port7")
checkb8 = builder.get_object("port8")
checkb9 = builder.get_object("port9")
checkb10 = builder.get_object("port10")
checkb11 = builder.get_object("port11")
checkb12 = builder.get_object("port12")
checkb13 = builder.get_object("port13")
checkb14 = builder.get_object("port14")
checkb15 = builder.get_object("port15")
checkb16 = builder.get_object("port16")
checkb17 = builder.get_object("port17")
checkb18 = builder.get_object("port18")
checkb19 = builder.get_object("port19")
checkb20 = builder.get_object("port20")
checkb21 = builder.get_object("port21")
checkb22 = builder.get_object("port22")
checkb23 = builder.get_object("port23")
checkb24 = builder.get_object("port24")

checkb1.connect ("toggled", on_checkbutton_toggled, "1")
checkb2.connect ("toggled", on_checkbutton_toggled, "2")
checkb3.connect ("toggled", on_checkbutton_toggled, "3")
checkb4.connect ("toggled", on_checkbutton_toggled, "4")
checkb5.connect ("toggled", on_checkbutton_toggled, "5")
checkb6.connect ("toggled", on_checkbutton_toggled, "6")
checkb7.connect ("toggled", on_checkbutton_toggled, "7")
checkb8.connect ("toggled", on_checkbutton_toggled, "8")
checkb9.connect ("toggled", on_checkbutton_toggled, "9")
checkb10.connect ("toggled", on_checkbutton_toggled, "10")
checkb11.connect ("toggled", on_checkbutton_toggled, "11")
checkb12.connect ("toggled", on_checkbutton_toggled, "12")
checkb13.connect ("toggled", on_checkbutton_toggled, "13")
checkb14.connect ("toggled", on_checkbutton_toggled, "14")
checkb15.connect ("toggled", on_checkbutton_toggled, "15")
checkb16.connect ("toggled", on_checkbutton_toggled, "16")
checkb17.connect ("toggled", on_checkbutton_toggled, "17")
checkb18.connect ("toggled", on_checkbutton_toggled, "18")
checkb19.connect ("toggled", on_checkbutton_toggled, "19")
checkb20.connect ("toggled", on_checkbutton_toggled, "20")
checkb21.connect ("toggled", on_checkbutton_toggled, "21")
checkb22.connect ("toggled", on_checkbutton_toggled, "22")
checkb23.connect ("toggled", on_checkbutton_toggled, "23")
checkb24.connect ("toggled", on_checkbutton_toggled, "24")
#---------------------------------------------------------------------------------------

window.connect("destroy", Gtk.main_quit)

gtk_style ()  # <----------------------- MOVED HERE

window.show_all()

Gtk.main()

The result should be something like this: