【问题标题】:Convert pango markup string to GtkTextTag properties将 pango 标记字符串转换为 GtkTextTag 属性
【发布时间】:2012-03-18 07:59:58
【问题描述】:

我有一个gtk.TextView,我想在其中添加类似标记的文本。我知道这可以通过使用gtk.TextTag 来实现,您可以使用与 pango 标记字符串类似的属性来创建它。我注意到没有简单的方法可以像使用多个其他小部件一样对gtk.TextBuffer 说 set_markup。相反,您必须创建一个 TextTag,为其赋予属性,然后将其插入到 TextBuffer 的 TagTable 中,指定该标签适用的迭代器。

理想情况下,我想创建一个可以将 pango 标记字符串转换为 TextTag 以获得相同效果的函数。但是 gtk 似乎没有内置该功能。 我注意到您可以在标记的字符串上使用pango.parse_markup(),它将创建一个pango.AttributeList,其中包含有关字符串上设置的属性和它们出现的索引的信息。但是每种类型的属性都有细微的差异,因此很难对每种情况进行概括。有没有更好的方法来解决这个问题?还是 pango 标记不打算转换为 gtk.TextTag 的?

【问题讨论】:

    标签: python gtk pygtk pango


    【解决方案1】:

    我终于找到了自己的解决方案来解决这个问题。我创建了一个解析标记字符串的函数(使用pango.parse_markup)。通过阅读文档和 python 自省,我能够弄清楚如何获取 pango.Attribute 并将其转换为 GtkTextTag 可以使用的属性。

    函数如下:

    def parse_markup_string(string):
        '''
        Parses the string and returns a MarkupProps instance
        '''
        #The 'value' of an attribute...for some reason the same attribute is called several different things...
        attr_values = ('value', 'ink_rect', 'logical_rect', 'desc', 'color')
    
        #Get the AttributeList and text
        attr_list, text, accel = pango.parse_markup( string )
        attr_iter = attr_list.get_iterator()
    
        #Create the converter
        props = MarkupProps()
        props.text = text
    
        val = True
        while val:
                attrs = attr_iter.get_attrs()
    
                for attr in attrs:
                        name = attr.type
                        start = attr.start_index
                        end = attr.end_index
                        name = pango.AttrType(name).value_nick
    
                        value = None
                        #Figure out which 'value' attribute to use...there's only one per pango.Attribute
                        for attr_value in attr_values:
                                if hasattr( attr, attr_value ):
                                        value = getattr( attr, attr_value )
                                        break
    
                        #There are some irregularities...'font_desc' of the pango.Attribute
                        #should be mapped to the 'font' property of a GtkTextTag
                        if name == 'font_desc':
                                name = 'font'
                        props.add( name, value, start, end )
    
                val = attr_iter.next()
    
        return props
    

    此函数创建一个MarkupProps() 对象,该对象能够生成GtkTextTags 以及文本中的索引以应用它们。

    这是对象:

    class MarkupProps():
    '''
    Stores properties that contain indices and appropriate values for that property.
    Includes an iterator that generates GtkTextTags with the start and end indices to 
    apply them to
    '''
    def __init__(self): 
        '''
        properties = (  {   
                            'properties': {'foreground': 'green', 'background': 'red'}
                            'start': 0,
                            'end': 3
                        },
                        {
                            'properties': {'font': 'Lucida Sans 10'},
                            'start': 1,
                            'end':2,
    
                        },
                    )
        '''
        self.properties = []#Sequence containing all the properties, and values, organized by like start and end indices
        self.text = ""#The raw text without any markup
    
    def add( self, label, value, start, end ):
        '''
        Add a property to MarkupProps. If the start and end indices are already in
        a property dictionary, then add the property:value entry into
        that property, otherwise create a new one
        '''
        for prop in self.properties:
            if prop['start'] == start and prop['end'] == end:
                prop['properties'].update({label:value})
        else:
            new_prop =   {
                            'properties': {label:value},
                            'start': start,
                            'end':end,
                        }
            self.properties.append( new_prop )
    
    def __iter__(self):
        '''
        Creates a GtkTextTag for each dict of properties
        Yields (TextTag, start, end)
        '''
        for prop in self.properties:
            tag = gtk.TextTag()
            tag.set_properties( **prop['properties'] )
            yield (tag, prop['start'], prop['end'])
    

    因此,有了这个函数和MarkupProps 对象,我可以给定一个pango 标记字符串,将字符串分解为其属性和文本形式,然后将其转换为GtkTextTags。

    【讨论】:

    【解决方案2】:

    没有关注 GTK+ 的开发,也许他们最近添加了一些东西,但是看到这些错误:#59390#505478。由于它们没有关闭,因此可能什么也没做。

    【讨论】:

    • 嗯,所以看起来他们不打算支持。您是否尝试过任何变通方法?或者有什么建议?
    • 不是真的,我不再使用 GTK+ 或 PyGTK 甚至任何使用它们的项目。但由于这是 Python,为此编写一些函数应该不会太困难(除非它不是一种方法,除非您出于某种原因已经对 gtk.TextBuffer 进行了子类化;仅为一种方法进行子类化感觉有点过头了)。我会接受第二个错误中概述的建议,但我当然在这里有偏见,因为我是记者;)
    • 哦,我想我从未在错误报告中提到它。我将实现建议的功能和另一个创建与 Pango 标记相同/相似的标签的功能。所以用法就像buffer.inject_pango_markup_tags(); buffer.insert_parsed(...);,第一次调用只进行一次,第二次没有任何限制。
    • 感谢您的建议。我屈服并实施了自己的解决方案。答案已发布
    猜你喜欢
    • 2017-10-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-19
    • 2019-10-31
    • 2016-11-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多