在Python GTK3中设置输入背景色并将其重新设置为默认值的最佳方法 [英] Best way to set Entry Background Color in Python GTK3 and set back to default

查看:97
本文介绍了在Python GTK3中设置输入背景色并将其重新设置为默认值的最佳方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

设置一个条目的背景颜色并将其重新设置为默认颜色的最佳方法是什么?

What is the best way to set background color for one entry and set it back to the default color?

我的脚本现在可以工作了,但是我敢肯定这不是最好的方法.
另外我还有两个问题:

My script is now working but I am very sure this is not the best way.
Also I still have two problems:

  1. 如果我插入不包含字符串"red"或"green"的文本,然后选择此文本,因为它全是白色,所以看不到我的选择.
  2. 我认为有比将self.entry_default_background_color_str插入CSS文本更好的方法.
  1. If I insert a text, not containing string "red" or "green" and select this text I cant see my selection because It is all white.
  2. I think there are better ways then the way I insert self.entry_default_background_color_str into the CSS text.


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代码中的情况. 主要问题的答案(以及用于执行此操作的适当代码)始终位于答案的底部.

I will first address the issues you mention, as they give insight into what is going on in GTK and OP's code. The answer to the main question (and proper code for doing this) is all the way at the bottom of the answer.

  1. 如果我插入不包含字符串"red"或"green"的文本,然后选择此文本,因为它全是白色,所以看不到我的选择.

发生这种情况的原因是因为使用了background属性,这会将Entry的所有与背景相关的属性设置为该颜色.因此,选择的背景和真实的"背景都如此.

The reason this happens is because the background property is used, this sets all background related properties of the Entry to that color. So both that of the selection as well as the "real" background.

然后的问题是,我们使用什么属性,这是GTK的一部分,文献记载很少,但是我们可以使用

Then the question is what property do we use, this is a part of GTK which is poorly documented but we can find out using the GtkInspector which lets us see what style properties are changing. This yields we should use background-image instead and that background-color is used for the background of the selection.

仅将background-image设置为颜色是行不通的,这会产生错误,因为需要图像.因此,现在我们必须想出一种方法来将我们的color设置为可以设置为background-image的内容,幸运的是,检查器向我们展示了GTK在内部进行处理的方式,即通过包装如下颜色:linear-gradient(red).这样做会创建均匀的红色图像,可以用作背景.

Just setting the background-image to the color doesn't work, that gives a error because a image is expected. So now we have to figure out a way to make our color into something we can set as a background-image luckily the inspector shows us the way GTK does it internally namely by wrapping the color like this: linear-gradient(red). Doing so creates a uniform red image which can be used as the background.

将此知识应用于您的代码将为我们提供:

Applying this knowledge to your code gives us:

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); }')


  1. 我认为有比将self.entry_default_background_color_str插入CSS文本更好的方法.
  1. I think there are better ways then the way I insert self.entry_default_background_color_str into the CSS text.

确实有更好的方法,即不要这样做.我们只需输入CssProvider空版本的CSS,就可以轻松返回到默认值,这将覆盖旧的CSS,从而删除所有旧的样式属性,例如颜色.

There is indeed a better way, namely don't do it. We can easily return to the default by just feeding the CssProvider an empty version of the css, this will overwrite the old one and thus remove any old style properties like for example the color.

将其与上一节结合起来可以给我们:

Combining this with the previous section gives us:

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 {}')


设置一个条目的背景颜色并将其重新设置为默认颜色的最佳方法是什么?

What is the best way to set background color for one entry and set it back to the default color?

现在,我解决了您的代码问题,现在这是所有重要的问题.您现在的操作方式是替换CSS文件,该文件可以正常运行,但从长远来看确实效率很低.通常,您将加载CSS并使用类和ID来告知要应用的样式.

Now that I addressed the issues with your code, now this all important question. The way your are doing it now is replacing the CSS file, which works fine but in the long run is really inefficient. Normally you would load the CSS and uses classes and ids to tell it which styling to apply.

下面,我对您的代码进行了修改,以使其达到这种目的,请查看注释以获取解释.

Below I adapted your code to do it this way, check the comments for the explanation.

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")

这篇关于在Python GTK3中设置输入背景色并将其重新设置为默认值的最佳方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆