如何在PyGtk TextView中的空行上设置文本属性?

时间:2013-10-01 10:58:46

标签: pygtk

代码的第一部分是发布的原始代码。第二个代码是对Bob的回答的修改,他引导我朝着正确的方向发展。

我需要用户,当他们到达gtk.TextBuffer中的特定行(这是一个新行,当然是空的)时,用粗体字输入。

如果可能,下面的代码中需要进行哪些更改才能使字体从用户开始输入的位置变为粗体?

import gtk, pango

class BoldTestWindow(gtk.Window):

    def __init__(self):
        gtk.Window.__init__(self)
        self.connect( "destroy", lambda *w: gtk.main_quit() )

        self.set_default_size(280, 80)

        # Create a text view and get it's buffer.
        self.tv = gtk.TextView()
        buffer = self.tv.get_buffer()

        # Create the Tags and add them to the Tag Table.
        tags = [["weight", pango.WEIGHT_BOLD], ]
        for tag in tags:
            newTag = gtk.TextTag(name=tag[0])
            newTag.set_property(tag[0], tag[1])
            textTable = buffer.get_tag_table()
            textTable.add(newTag)

        # Grab an Iter to insert text.
        startIter = buffer.get_start_iter()

        # Insert some text in which to apply the bold attribute.
        buffer.insert(startIter, "A Bold Statement.")

        # startIter must be asked for again, because text was inserted.
        startIter = buffer.get_start_iter()
        endIter = buffer.get_end_iter()

        # Apply the tags to entire range of TextBuffer
        tags = ["weight",]
        for tag in tags:
            buffer.apply_tag_by_name(tag, startIter, endIter)

        # Let's see what happens.
        self.add(self.tv)
        self.tv.grab_focus()
        self.set_position(gtk.WIN_POS_CENTER)
        self.show_all()

if __name__ == "__main__":
    bww = BoldTestWindow()
    gtk.main()

鲍勃的回答是揭露事件,接受曝光事件泛滥,数千次调用改变属性,每个角色只需要添加一次调用。

为了阻止事件泛滥,我尝试了重要事件。

我尝试使用按键事件,但直到下一个事件回合才修改该字符,这样就没有为最后一个字符更改样式。

我尝试了密钥释放事件,这很有效,但添加属性有一点延迟。该字符不会是瞬间的属性,然后会添加粗体属性。

最后,我尝试了一个按键事件和暴露事件的混合,但是那个瓶颈缩了一些,然后来自irc #pygtk的Juhaz建议改变事件似乎运作良好。我相信anser很接​​近,我将在完成后使用以下部分发布它。我仍然需要计算线对齐属性,它们仍然是错误的。

import gtk, pango

# TaggedCursorTextView attempts to only add one feature to gtk.TextView: make the cursor dynamically settable
# to a list of tags.  This forces the current text being typed to the set of tags set.

class TaggedCursorTextView(gtk.TextView):
    def __init__(self):
        gtk.TextView.__init__(self)

        # Create buffer variable that point to it's internal TextBuffer.
        self.buffer = self.get_buffer()

        # Listen for the changed event. (User types, deletes or pastes text, etc.)
        self.connect("key-press-event", self.on_key_press_event)

        # What ever tags are place in here determines the text attributes (font type, bold, etc.)
        # That is being typed by the user at any given moment.
        # Default should be kept empty, no styles.
        self.cursorTags = []

        self.handlerID = None

    def addTags(self, tagList):
        # Create the Tags and add them to the Tag Table.  Ignores duplicate tag names.
        for tag in tagList:
            newTag = gtk.TextTag(name=tag[0])
            textTable = self.buffer.get_tag_table()
            tagNameFound = textTable.lookup(tag[0])
            if not tagNameFound:
                newTag.set_property(tag[1], tag[2])
                textTable.add(newTag)

    def removeTags(self, tagNameList):
        pass

    def setCursorTags(self, tagList):
        self.cursorTags = tagList

    def on_key_press_event(self, widget, event):
        self.handlerID = self.buffer.connect("changed", self.on_changed_event)

    def on_changed_event(self, widget):
        """This method updates the last character type to the cursor style."""
        self.buffer.disconnect(self.handlerID)

        # Get the iter that falls before and after the last char typed.
        endIter = self.buffer.get_end_iter()
        offset = endIter.get_offset() - 1
        startIter = self.buffer.get_iter_at_offset(offset)

        # Apply the tags to the newly typed char
        for tag in self.cursorTags:
            self.buffer.apply_tag_by_name(tag, startIter, endIter)

class TaggedCurserTextViewTestWindow(gtk.Window):

    def __init__(self):
        gtk.Window.__init__(self)
        self.connect( "destroy", lambda *w: gtk.main_quit() )

        self.set_default_size(280, 80)

        # Create a TaggedCursorTextView.
        tctv = TaggedCursorTextView()

        # Add some cursors tags that will be used at some point later in the app.
        # Each tag element list is: [tag name, tag property, tag value]
        tagList = [["Italic", "style", pango.STYLE_ITALIC], ["Bold", "weight", pango.WEIGHT_BOLD], ["Center", "justification", gtk.JUSTIFY_CENTER]]
        tctv.addTags(tagList)

        # Use the names of the tags in a list to set the cursor tags.
        tctv.setCursorTags(["Italic", "Bold", "Center"]) # Comment out this line for no style.

        # Let's see what happens.
        self.add(tctv)
        tctv.grab_focus()
        self.set_position(gtk.WIN_POS_CENTER)
        self.show_all()

if __name__ == "__main__":
    TaggedCurserTextViewTestWindow()
    gtk.main()

1 个答案:

答案 0 :(得分:0)

这是对代码的粗略修改。我刚刚为您的textview创建了一个expose-event处理程序,每当调用expose-event时(即当您的textview请求重绘时),它都会使用粗体字体重绘所有内容。

我不确定,如果这是你想要的;请详细说明你的目的,如果不是(我在IRC)。

import gtk, pango

class BoldTestWindow(gtk.Window):

    def __init__(self):
        gtk.Window.__init__(self)
        self.connect( "destroy", lambda *w: gtk.main_quit() )

        self.set_default_size(280, 80)

        # Create a text view and get it's buffer.
        self.tv = gtk.TextView()
        buffer = self.tv.get_buffer()

        # Create the Tags and add them to the Tag Table.
        tags = [["weight", pango.WEIGHT_BOLD], ]
        for tag in tags:
            newTag = gtk.TextTag(name=tag[0])
            newTag.set_property(tag[0], tag[1])
            textTable = buffer.get_tag_table()
            textTable.add(newTag)

        # Grab an Iter to insert text.
        startIter = buffer.get_start_iter()

        # Insert some text in which to apply the bold attribute.
        buffer.insert(startIter, "A Bold Statement.")

        # startIter must be asked for again, because text was inserted.
        startIter = buffer.get_start_iter()
        endIter = buffer.get_end_iter()

        # Apply the tags to entire range of TextBuffer
        tags = ["weight",]
        for tag in tags:
            buffer.apply_tag_by_name(tag, startIter, endIter)

        # Let's see what happens.
        self.add(self.tv)
        self.tv.grab_focus()
        self.set_position(gtk.WIN_POS_CENTER)
        self.show_all()

    def on_expose_event(self, widget, event, data=None):
        buffer = self.tv.get_buffer()
        startIter = buffer.get_start_iter()
        endIter = buffer.get_end_iter()

        # Apply the tags to entire range of TextBuffer
        tags = ["weight",]
        for tag in tags:
            buffer.apply_tag_by_name(tag, startIter, endIter)



if __name__ == "__main__":
    bww = BoldTestWindow()
    bww.tv.connect("expose-event", bww.on_expose_event)
    gtk.main()