无法将 CSS 应用于 GtkEntry 小部件(GTK3 / gi / Python)不工作

Posted

技术标签:

【中文标题】无法将 CSS 应用于 GtkEntry 小部件(GTK3 / gi / Python)不工作【英文标题】:Cannot apply CSS to GtkEntry Widget (GTK3 / gi / Python) Not Working 【发布时间】:2019-11-25 22:55:56 【问题描述】:

我一直无法弄清楚我做错了什么。我敢肯定,这很简单,但却让我无法接受。即使在以下示例中,我也无法使其正常工作。我似乎无法将 CSS 样式应用于单个 GtkWindow 中的 GtkEntry 小部件。我只是想把输入框的背景变成红色。

我查看过的所有内容和看到的示例都如下所示,似乎没有其他人被难倒。

这是我的 Python:

import gi
gi.require_version('Gtk', '3.0')
gi.require_version('Gdk', '3.0')
from gi.repository import Gtk
from gi.repository import Gdk

builder = Gtk.Builder()
builder.add_from_file("entry.glade")

window = builder.get_object('window1')
window.connect('destroy', Gtk.main_quit)

css = "#red  background-image: linear-gradient(red); "
provider = Gtk.CssProvider()
provider.load_from_data(css)
Gtk.StyleContext().add_provider_for_screen(Gdk.Screen.get_default(), provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)

entry = builder.get_object('entry1')
entry_style_context = entry.get_style_context()
entry_style_context.add_class("red")

window.show_all()

Gtk.main()

这里是 Glade XML:

<?xml version="1.0" encoding="UTF-8"?>
<interface>
  <requires lib="gtk+" version="3.0"/>
  <!-- interface-naming-policy project-wide -->
  <object class="GtkWindow" id="window1">
    <property name="can_focus">False</property>
    <child>
      <object class="GtkVBox" id="vbox1">
        <property name="visible">True</property>
        <property name="can_focus">False</property>
        <child>
          <object class="GtkEntry" id="entry1">
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <property name="invisible_char">●</property>
            <property name="primary_icon_activatable">False</property>
            <property name="secondary_icon_activatable">False</property>
            <property name="primary_icon_sensitive">True</property>
            <property name="secondary_icon_sensitive">True</property>
          </object>
          <packing>
            <property name="expand">True</property>
            <property name="fill">True</property>
            <property name="position">0</property>
          </packing>
        </child>
      </object>
    </child>
  </object>
</interface>

如果我将 CSS 设置为 .entry background-image: linear-gradient(red); 它可以工作,但是所有 GtkEntry 框都会是红色的(我不想要)。

我到底错过了什么?

【问题讨论】:

相关Import CSS file in Python GTK3 program created using Glade,看注释"如果没有设置背景图片" 另外值得注意的是 你不应该将 Gtk3 与 Gtk2 混合使用。坏事难免发生。它与你的问题无关,但不好的事情会发生在你身上。哇哈哈哈哈哈! 感谢@PaulChilds,将林间空地更改为 3.0 以保持一致性(但没有变化)。 @stovfl - 这似乎不是原因,因为我试图设置背景,而不是颜色,它确实适用于 .entry 级别,但我确实为Gdk 如帖子中所述,但仍然没有乐趣。 【参考方案1】:

问题:将CSS 应用到GtkEntry 小部件

正如 ptomato 在他的回答中所描述的,如果您没有为您的小部件定义 name,则不能使用 css = "#red ...

定义一个小部件name,使用:

glade 文件中:&lt;property name="name"&gt;red&lt;/property&gt; 在脚本中:entry = builder.get_object('entry1')entry.set_name('red')
Gtk.CssProvider, Gtk.CssProvider.load_from_data Gtk.StyleContext, Gtk.StyleContext.add_provider_for_screen

方法一:使用小部件名称,css = b"#entry ...

    glade文件中的小部件name设置为entry
        <child>
          <object class="GtkEntry" id="entry1">
            <property name="name">entry</property>
    

    使用小部件名称 entry 定义您的 CSS

        css = b"#entry background-image: linear-gradient(red, orange); color: white;"
    

    工作示例,使用小部件名称:

    class App:
        def __init__(self):
            super().__init__()
    
            builder = Gtk.Builder()
            builder.add_from_file("entry.glade")
    
            window = builder.get_object('window1')
            window.connect('destroy', Gtk.main_quit)
    
            css = b"#entry background-image: linear-gradient(red, orange);"
            provider = Gtk.CssProvider()
            provider.load_from_data(css)
            Gtk.StyleContext()\
                .add_provider_for_screen(Gdk.Screen.get_default(),
                                         provider,
                                         Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)
    
            window.show_all()
    
    if __name__ == "__main__":
        main = App()
        Gtk.main()
    

方法2:使用小部件样式类,css = b".entry.red ...

Gtk.Widget.get_style_context, Gtk.StyleContext.add_class

    使用嵌套样式类.entry.red.blue 定义您的CSS
        css = b"""
        .entry color: white;
        .entry.red background-image: linear-gradient(red, orange);
        .entry.blue background-image: linear-gradient(blue, lightblue);
    将命名的样式类添加到小部件:
        entry1 = builder.get_object('entry1')
        entry1.get_style_context().add_class("entry")
        entry1.get_style_context().add_class("red")

        # the same for `entry2`
        ...

使用小部件样式类的工作示例:

class App:
    def __init__(self):
        super().__init__()

        builder = Gtk.Builder()
        builder.add_from_file("entry.glade")

        window = builder.get_object('window1')
        window.connect('destroy', Gtk.main_quit)

        css = b"""
        .entry  color: white;
        .entry.red  background-image: linear-gradient(red, orange);
        .entry.blue  background-image: linear-gradient(blue, lightblue);
        """
        provider = Gtk.CssProvider()
        provider.load_from_data(css)
        Gtk.StyleContext()\
            .add_provider_for_screen(Gdk.Screen.get_default(),
                                     provider,
                                     Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)

        entry1 = builder.get_object('entry1')
        entry1.set_text('TEST')
        entry1.get_style_context().add_class("entry")
        entry1.get_style_context().add_class("red")

        entry2 = builder.get_object('entry2')
        entry2.set_text('TEST')
        entry2.get_style_context().add_class("entry")
        entry2.get_style_context().add_class("blue")

        window.show_all()

if __name__ == "__main__":
    main = App()
    Gtk.main()

使用 Python 测试:3.5 - gi.__version__:3.22.0 - Glade 3.20.0

【讨论】:

【参考方案2】:

在常规浏览器 CSS 中,#foo 指的是 ID 为 foohtml 元素(设置为,例如id="foo"),.foo 指的是具有样式类的元素(设置为,例如@987654325 @,或多个类,例如class="foo bar"。)

在 GTK CSS 中,ID 转换为小部件名称(例如在 XML 文件中设置为 entry.set_name('foo')&lt;property name="name"&gt;foo&lt;/property&gt;;不幸的是与 XML 文件中的 id="foo" 相同) 并且该类仍然是样式类(但在 GTK 中它设置为,例如 entry.get_style_context().add_class('foo')。由于您的小部件具有样式类但没有名称,这就是您必须使用点语法的原因。

【讨论】:

“转换为小部件名称”:为了澄清,您能否使用完整的 entry.set_name('entry1') 示例编辑您的答案。 &lt;object class="GtkEntry" id="entry1"&gt;,entry1中不是widget的名字吗? 希望如何在 XML 文件中设置它的示例应该澄清它。【参考方案3】:

好的,好吧,用一个新鲜的头脑再看一遍,我想我已经弄明白了。我不确定它为什么会这样工作,但希望有人比我更聪明。

无论出于何种原因,我都需要以点表示法指定小部件类型和类名,因为哈希表示法在 CSS/HTML 领域中无法正常工作。

工作:css = "#foo background-image: linear-gradient(red);

这个可以工作:css = "entry.foo background-image: linear-gradient(red);

我已通过向 Glade 添加第二个输入框并执行以下操作来验证这一点:

css = """
.entry.red  background-image: linear-gradient(red); 
.entry.blue  background-image: linear-gradient(blue); 
"""
provider = Gtk.CssProvider()
provider.load_from_data(css)
Gtk.StyleContext().add_provider_for_screen(Gdk.Screen.get_default(), provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)

builder.get_object('entry1').get_style_context().add_class("red")
builder.get_object('entry2').get_style_context().add_class("blue")

现在我有一个红色和一个蓝色的输入框。

【讨论】:

获取以下信息:provider.load_from_data(css) TypeError: Item 0: Must be number, not strtk-WARNING : Theme parsing error: &lt;data&gt;:2:58: Using one color stop with linear-gradient() is deprecated.。不,背景颜色。

以上是关于无法将 CSS 应用于 GtkEntry 小部件(GTK3 / gi / Python)不工作的主要内容,如果未能解决你的问题,请参考以下文章

GTK3 使用带有 ID 的 CSS 从 GtkEntry 中删除蓝框

将几何网格应用于 tkinter Notebook 页面中的小部件的问题

防止将 css“内容”应用于特定元素

适用于显示静态 html 页面的 C++ 小部件

将 jQuery UI 小部件应用于 ajax 加载的元素

从 android 11 小部件启动另一个应用程序?