无法将 CSS 应用于 GtkEntry 小部件 (GTK3 / gi / Python) 不工作
Cannot apply CSS to GtkEntry Widget (GTK3 / gi / Python) Not Working
我一直无法弄清楚我做错了什么。我敢肯定这很简单,但逃避了我。即使在下面的示例中,我也无法正常工作。我似乎无法在单个 GtkWindow 中将 CSS 样式应用于 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()
这里是林间空地 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 框都会是红色的(我不想要)。
我到底错过了什么?
好吧,好吧,换个思路再看一遍,我想我已经弄明白了。我不确定它为什么会这样工作,但希望有人比我更聪明。
出于某种原因,我需要以点表示法指定小部件类型和 class 名称,因为散列表示法在 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")
现在我有一个红色和一个蓝色的输入框。
在常规浏览器 CSS 中,#foo
指代 ID 为 foo
的 HTML 元素(设置为 id="foo"
)和 .foo
指的是样式为 class 的元素(设置为 class="foo"
,或多个 class 元素,例如 class="foo bar"
。)
在 GTK CSS 中,ID 转换为小部件名称(例如 entry.set_name('foo')
或 XML 文件中的 <property name="name">foo</property>
;不幸的是 not 与 XML 文件中的 id="foo"
相同)并且 class 仍然是 class 样式(但在 GTK 中它设置为 entry.get_style_context().add_class('foo')
。由于您的小部件具有样式 class 但没有名称,因此您必须使用点语法。
Question: Apply CSS
to a GtkEntry
Widget
正如 ptomato 在他的回答中所描述的那样,如果您没有为您的小部件定义 name
,则不能使用 css = "#red ...
。
定义小部件 name
,使用:
- 在
glade
文件中:<property name="name">red</property>
- 在脚本中:
entry = builder.get_object('entry1')
entry.set_name('red')
- Gtk.CssProvider, Gtk.CssProvider.load_from_data
- Gtk.StyleContext, Gtk.StyleContext.add_provider_for_screen
Method 1: Using a widgets name, 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;}"
Working example, using a widgets name:
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()
Method 2: Using a widgets style class, css = b".entry.red ...
:
Gtk.Widget.get_style_context, Gtk.StyleContext.add_class
- 使用嵌套样式定义
CSS
class .entry
, .red
, .blue
:
css = b"""
.entry {color: white;}
.entry.red {background-image: linear-gradient(red, orange);}
.entry.blue {background-image: linear-gradient(blue, lightblue);}
- 将命名样式 classes 添加到小部件:
entry1 = builder.get_object('entry1')
entry1.get_style_context().add_class("entry")
entry1.get_style_context().add_class("red")
# the same for `entry2`
...
Working example using a widgets style class:
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
我一直无法弄清楚我做错了什么。我敢肯定这很简单,但逃避了我。即使在下面的示例中,我也无法正常工作。我似乎无法在单个 GtkWindow 中将 CSS 样式应用于 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()
这里是林间空地 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 框都会是红色的(我不想要)。
我到底错过了什么?
好吧,好吧,换个思路再看一遍,我想我已经弄明白了。我不确定它为什么会这样工作,但希望有人比我更聪明。
出于某种原因,我需要以点表示法指定小部件类型和 class 名称,因为散列表示法在 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")
现在我有一个红色和一个蓝色的输入框。
在常规浏览器 CSS 中,#foo
指代 ID 为 foo
的 HTML 元素(设置为 id="foo"
)和 .foo
指的是样式为 class 的元素(设置为 class="foo"
,或多个 class 元素,例如 class="foo bar"
。)
在 GTK CSS 中,ID 转换为小部件名称(例如 entry.set_name('foo')
或 XML 文件中的 <property name="name">foo</property>
;不幸的是 not 与 XML 文件中的 id="foo"
相同)并且 class 仍然是 class 样式(但在 GTK 中它设置为 entry.get_style_context().add_class('foo')
。由于您的小部件具有样式 class 但没有名称,因此您必须使用点语法。
Question: Apply
CSS
to aGtkEntry
Widget
正如 ptomato 在他的回答中所描述的那样,如果您没有为您的小部件定义 name
,则不能使用 css = "#red ...
。
定义小部件 name
,使用:
- 在
glade
文件中:<property name="name">red</property>
- 在脚本中:
entry = builder.get_object('entry1')
entry.set_name('red')
- Gtk.CssProvider, Gtk.CssProvider.load_from_data
- Gtk.StyleContext, Gtk.StyleContext.add_provider_for_screen
Method 1: Using a widgets name,
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;}"
Working example, using a widgets name:
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()
Method 2: Using a widgets style class,
css = b".entry.red ...
:
Gtk.Widget.get_style_context, Gtk.StyleContext.add_class
- 使用嵌套样式定义
CSS
class.entry
,.red
,.blue
:
css = b""" .entry {color: white;} .entry.red {background-image: linear-gradient(red, orange);} .entry.blue {background-image: linear-gradient(blue, lightblue);}
- 将命名样式 classes 添加到小部件:
entry1 = builder.get_object('entry1') entry1.get_style_context().add_class("entry") entry1.get_style_context().add_class("red") # the same for `entry2` ...
Working example using a widgets style class:
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