在Python GTK3中设置条目背景颜色并将其设置回默认值的最佳方法
问题内容:
设置一个条目的背景颜色并将其设置回默认颜色的最佳方法是什么?
我的脚本现在可以正常工作,但是我敢肯定这不是最好的方法。
另外我还有两个问题:
- 如果插入不包含字符串“ red”或“ green”的文本,然后选择此文本,则看不到我的选择,因为它全是白色的。
- 我认为有比插入
self.entry_default_background_color_str
CSS文本更好的方法。
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
from gi.repository import Gdk
class Window(Gtk.Window):
def __init__(self):
self.screen = Gdk.Screen.get_default()
self.gtk_provider = Gtk.CssProvider()
self.gtk_context = Gtk.StyleContext()
self.gtk_context.add_provider_for_screen(self.screen, self.gtk_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)
Gtk.Window.__init__(self, title="Check Input")
self.set_size_request(300, 80)
self.mainbox = Gtk.VBox()
self.add(self.mainbox)
# entry
self.name_entry = Gtk.Entry()
self.name_entry.set_name("name_entry")
self.mainbox.pack_start(self.name_entry, True, True, 0)
self.name_entry.connect("changed", self.check_input)
entry_context = self.name_entry.get_style_context()
self.entry_default_background_color = entry_context.get_background_color(Gtk.StateType.NORMAL)
self.entry_default_background_color_str = self.entry_default_background_color.to_string()
self.show_all()
def check_input(self, _widget=None):
if "red" in self.name_entry.get_text():
self.gtk_provider.load_from_data('#name_entry { background: red; }')
elif "green" in self.name_entry.get_text():
self.gtk_provider.load_from_data('#name_entry { background: green; }')
else:
self.gtk_provider.load_from_data('#name_entry { background: ' + self.entry_default_background_color_str + '; }')
def main():
window = Window()
Gtk.main()
if __name__ == "__main__":
main()
问题答案:
我将首先解决您提到的问题,因为它们可以洞悉GTK和OP代码中的情况。 主要问题的答案(以及用于执行此操作的适当代码)始终位于答案的底部。
- 如果插入不包含字符串“ red”或“ green”的文本,然后选择此文本,则看不到我的选择,因为它全是白色的。
发生这种情况的原因是因为background
使用了该属性,这会将Entry的所有与背景相关的属性设置为该颜色。因此,选择的背景和“真实的”背景都一样。
然后的问题是,我们使用什么属性,这是GTK的一部分,文献记载很少,但是我们可以使用GtkInspector找出来,让我们看到哪些样式属性正在更改。这样就产生了,我们应该使用background- image
它background-color
作为选择的背景。
仅将设置background- image
为颜色是行不通的,这会产生错误,因为需要图像。所以,现在我们必须想出一个办法,使我们的color
到的东西,我们可以设置为background- image
幸运的是,检查显示,美国GTK做它的内部,即通过包装这样的颜色的方式:linear- gradient(red)
。这样做会创建均匀的红色图像,可以用作背景。
将这些知识应用于您的代码可以使我们:
if "red" in self.name_entry.get_text():
self.gtk_provider.load_from_data('#name_entry { background-image: linear-gradient(red); }')
elif "green" in self.name_entry.get_text():
self.gtk_provider.load_from_data('#name_entry { background-image: linear-gradient(green); }')
- 我认为有比插入
self.entry_default_background_color_str
CSS文本更好的方法。
确实有更好的方法,即不要这样做。我们只需CssProvider
输入空版本的css,就可以轻松返回默认值,这将覆盖旧的css,从而删除所有旧的样式属性,例如颜色。
将其与上一部分结合在一起,我们得到:
if "red" in self.name_entry.get_text():
self.gtk_provider.load_from_data('#name_entry { background-image: linear-gradient(red); }')
elif "green" in self.name_entry.get_text():
self.gtk_provider.load_from_data('#name_entry { background-image: linear-gradient(green); }')
else:
self.gtk_provider.load_from_data('#name_entry {}')
设置一个条目的背景颜色并将其设置回默认颜色的最佳方法是什么?
既然我已经解决了您的代码问题,那么这就是所有重要的问题。您现在的操作方式是替换CSS文件,该文件可以正常运行,但从长远来看确实效率很低。通常,您将加载CSS并使用类和ID来告知要应用的样式。
下面,我对您的代码进行了修改以实现这种方式,请查看注释以获取解释。
def __init__(self):
screen = Gdk.Screen.get_default()
gtk_provider = Gtk.CssProvider()
gtk_context = Gtk.StyleContext()
gtk_context.add_provider_for_screen(screen, gtk_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)
# Create the window
Gtk.Window.__init__(self, title="Check Input")
self.set_size_request(300, 80)
self.mainbox = Gtk.VBox()
self.add(self.mainbox)
# Load the CSS
gtk_provider.load_from_data("""
#name_entry.red { background-image: linear-gradient(red); }
#name_entry.green { background-image: linear-gradient(green); }
""")
# Create the entry and give it a name which will be the ID
name_entry = Gtk.Entry()
name_entry.set_name("name_entry")
self.mainbox.pack_start(name_entry, True, True, 0)
# Add the listener
name_entry.connect("changed", self.check_input)
self.show_all()
def check_input(self, entry):
# Get the style context for this widget
entry_style_context = entry.get_style_context()
# Check if our text contains red
if "red" in entry.get_text():
# Add the red class, so now the styling with .red is applied
entry_style_context.add_class("red")
# Check if our text contains green
elif "green" in entry.get_text():
# Add the red class, so now the styling with .green is applied
entry_style_context.add_class("green")
else:
# When the text doesn't contain it remove the color classes to show the default behaviour
entry_style_context.remove_class("red")
entry_style_context.remove_class("green")