在pyGTK的TextView/TextBuffer中插入粗体字符

4 投票
1 回答
2438 浏览
提问于 2025-04-16 07:28

我有一个文本视图(TextView)和一个与之关联的文本缓冲区(TextBuffer)。

当用户按下 Ctrl+b 时,我希望文本开始以粗体输入,直到用户再次按下 Ctrl+b。

我尝试了自己的方法,但都没有成功,然后我在邮件列表上找到了这个帖子:

http://www.daa.com.au/pipermail/pygtk/2009-April/016951.html

这个问题和我遇到的一样,某人给出的解决方案是:

你的应用程序需要处理管理文本缓冲区中标签的相关工作。当文本在光标处插入时,你的应用需要捕捉到一个信号,表示文本正在被插入,然后将所需的标签应用到插入的文本上。我认为这可以通过捕捉 TextBuffer 的 "insert-text" 信号来实现(使用 connect_after() 确保文本已经被插入),然后在回调中将标签应用到文本上。

所以我尝试了这个。这是我的 textbuffer.py:

import gtk
import pango

class TextBuffer(gtk.TextBuffer):
 def __init__(self):
  gtk.TextBuffer.__init__(self)
  self.connect_after('insert-text', self.text_inserted)
  # A list to hold our active tags
  self.tags_on = []
  # Our Bold tag.
  self.tag_bold = self.create_tag("bold", weight=pango.WEIGHT_BOLD) 

 def get_iter_position(self):
  return self.get_iter_at_mark(self.get_insert())
 
 def make_bold(self, text):
  ''' add "bold" to our active tags list '''
  self.tags_on.append('bold')
 
 def text_inserted(self, buffer, iter, text, length):
  # A text was inserted in the buffer. If there are ny tags in self.tags_on, apply them
  if self.tags_on:
   print self.get_iter_position()
   
   # This sets the iter back N characters
   iter.backward_chars(length)
   
   # And this applies tag from iter to end of buffer
   self.apply_tag_by_name('bold', self.get_iter_position(), self.get_end_iter())
   
   print self.get_iter_position()

每当有人按下 Ctrl+b 时,方法 make_bold() 就会从主脚本中被调用。

理论上,这正是邮件帮助中提到的做法。但实际上并没有成功。文本在我输入时并没有显示为粗体。如果我按左箭头把光标移动回去,然后再输入一个字符,光标右边的字符才会变成粗体。

我该如何完成这个任务呢?

另外,有人能把标签 'textbuffer' 加到这个帖子上吗?我不能创建新标签,我觉得这个标签比 'textview' 更准确。

1 个回答

5

在这个示例代码中,你在 TextBuffer.text_inserted 里调用了 iter.backward_chars,但你并没有使用这个 iter!所以我写了一个示例脚本来展示你想要的效果,并做一些说明:

import gtk
import pango

class TextBuffer(gtk.TextBuffer):
    def __init__(self):
        gtk.TextBuffer.__init__(self)
        self.connect_after('insert-text', self.text_inserted)
        # A list to hold our active tags
        self.tags_on = []
        # Our Bold tag.
        self.tag_bold = self.create_tag("bold", weight=pango.WEIGHT_BOLD)  

    def get_iter_position(self):
        return self.get_iter_at_mark(self.get_insert())

    def make_bold(self):
        ''' add "bold" to our active tags list '''
        if 'bold' in self.tags_on:
            del self.tags_on[self.tags_on.index('bold')]
        else:
            self.tags_on.append('bold')

    def text_inserted(self, buffer, iter, text, length):
        # A text was inserted in the buffer. If there are ny tags in self.tags_on,   apply them
        if self.tags_on:
            # This sets the iter back N characters
            iter.backward_chars(length)
            # And this applies tag from iter to end of buffer
            self.apply_tag_by_name('bold', self.get_iter_position(), iter)



def main():
    window = gtk.Window()
    window.connect('destroy', lambda _: gtk.main_quit())
    window.resize(300, 300)
    tb = TextBuffer()
    tv = gtk.TextView(buffer=tb)

    accel = gtk.AccelGroup()
    accel.connect_group(gtk.keysyms.b,
                        gtk.gdk.CONTROL_MASK,gtk.ACCEL_LOCKED,
                        lambda a,b,c,d: tb.make_bold())
    window.add_accel_group(accel)
    window.add(tv)
    window.show_all()
    gtk.main()

if __name__ == '__main__':
    main()

撰写回答