1

我在玩 pygtk 来构建我的小项目,它使用 gtk,基本上有一个窗口,在这个窗口中我有一个树形视图,在树形视图内有一个 gtk.liststore。

这是带有窗口及其值的图像

一切都很酷,直到我意识到我需要一些标签,看到很多使用 pango 的示例,并且它是有效的,至少在选择的行被更改之前。

我用一些不太优雅的东西解决了这个问题, 这里有一个完整代码的链接

    def on_toolbar_button_clicked(self, widget, tag):
        bounds_front    = self.text_buffer_front.get_selection_bounds()
        bounds_back     = self.text_buffer_back.get_selection_bounds()

        if len(bounds_front) != 0:

            (start, end)        = bounds_front
            selection_front      = self.text_buffer_front.get_text(start, end, True)
            get_insert_front     = self.text_buffer_front.get_insert()

            self.text_buffer_front.delete(start, end)

            iter_front           = self.text_buffer_front.get_iter_at_mark(get_insert_front)
            self.text_buffer_front.insert(iter_front, tag[0] + selection_front + tag[1])

基本上,当我单击工具栏下划线按钮时,此方法会将 <u></u> 放在一个单词周围,它的值将放置在 liststore 中,并使用 textview 显示该值。如果至少 set_text 检测到这些语法,这将是完美的。

所以,我想要实现的是在 textview 显示标记的单词,当我更改行并返回上一个标记的行时,它仍然显示标记的单词,例如,如果我在一个单词下划线,它仍然当我回来时下划线,如果解决方案涉及使用 pango,我怎样才能从中获取值以供以后使用。

到目前为止,我尝试的是搞乱 textbuffer.serialize 和 textbuffer.deserialized,但它并没有按我的意愿工作。

编辑

就像这里我将下划线标记应用于“纸张”,序列化文本缓冲区,将其放入变量中,但我怎样才能将它传递回缓冲区?

exported = self.text_buffer_front.serialize( self.text_buffer_front, format, start_iter_front, end_iter_front )

打印变量'exported'我得到一个字节值:

b'GTKTEXTBUFFERCONTENTS-0001\x00\x00\x00w <text_view_markup>\n <tags>\n </tags>\n<text>A
At the first comes rock!  Rock, <apply_tag name="underline">paper</apply_tag>, scissors!

编辑 2

这可能很明显,但对我来说不是,如果我有一个序列化的东西,接下来我需要做的只是“反序列化”它,为此有gtk.TextBuffer.deserialize

语法应该是这样的:

        self.dict_any_tags = {str(key): value[1] for key, value in enumerate(self.sub_list_store)}

    def item_selected(self, *args):
        try:
            iter_start_front        = self.text_buffer_front.get_start_iter()
            iter_end_front          = self.text_buffer_front.get_end_iter()
            path                    = self.selected_row.get_selected_rows()[1][0]

            try:
                self.text_buffer_front.deserialize(self.text_buffer_front, self.text_buffer_front.register_deserialize_tagset(), self.text_buffer_front.get_start_iter(), self.dict_any_tags[str(path)])
            except:
                self.text_buffer_front.set_text(self.sub_list_store[path][1])
        except IndexError:
            pass

    def on_toolbar_button_clicked(self, widget, tag):
        bounds_front    = self.text_buffer_front.get_selection_bounds()
        bounds_back     = self.text_buffer_back.get_selection_bounds()
        path            = self.selected_row.get_selected_rows()[1][0]

        if len(bounds_front) != 0:

            (start, end)        = bounds_front
            selection_front     = self.text_buffer_front.get_text(start, end, True)
            get_insert_front    = self.text_buffer_front.get_insert()

            self.text_buffer_front.apply_tag(tag, start, end)

            start_iter_front    = self.text_buffer_front.get_start_iter()
            end_iter_front      = self.text_buffer_front.get_end_iter()
            format              = self.text_buffer_front.register_serialize_tagset()
            exported            = self.text_buffer_front.serialize( self.text_buffer_front,
                                                                    format,
                                                                    start_iter_front,
                                                                    end_iter_front)

            self.dict_any_tags[str(path)] = exported

问题是,当我在尝试之前尝试将反序列化放在错误的位置时,它什么也没做。现在我可以更轻松地跟踪标签的位置等。我只需要运行更多测试。

4

1 回答 1

0

关键是创建另一个迭代器(我使用字典)来跟踪序列化文本,然后当我连续单击时,如果值为字节,它会尝试使用反序列化函数,因为它不会简单地使用 set_text 设置文本。

在反序列化之前将文本设置为空也很重要 set_text('') ,否则缓冲区的先前值将放置在缓冲区的当前值之前。

至于文本的更改,我使用方法 connect 连接“更改”信号并将更改序列化并将序列化值传递给字典。这就是我得到的:

        # dictionary to track the tags
        self.dict_any_change_front  = {str(key): value[1] for key, value in enumerate(self.sub_list_store)}
        self.dict_any_change_back   = {str(key): value[1] for key, value in enumerate(self.sub_list_store_back)}

    def deserialize(self, text_buffer, exported):
        text_buffer.set_text('')
        text_buffer.deserialize( text_buffer,
                                 text_buffer.register_deserialize_tagset(),
                                 text_buffer.get_start_iter(),
                                 exported )

    def item_selected(self, *args):
        #   Need this try/except to silent a indexerror that will occur case the second window close and if opened again,
        # merely cosmetic as it will always occur, just select any row and all good.
        #   The get_selected_rows()[1] will return a empty list at first try when reopening the second window, I just don't know why

        try:
            path                    = self.selected_row.get_selected_rows()[1][0]

            exported_front          = self.dict_any_change_front[str(path)]
            exported_back           = self.dict_any_change_back[str(path)]

            try:
                if isinstance(exported_front, bytes):
                    self.deserialize(self.text_buffer_front, exported_front)
                else:
                    self.text_buffer_front.set_text(self.sub_list_store[path][1])
                if isinstance(exported_back, bytes):
                    self.deserialize(self.text_buffer_back, exported_back)
                else:
                    self.text_buffer_back.set_text(self.sub_list_store_back[path][1])
            except:
                self.text_buffer_front.set_text(self.sub_list_store[path][1])
                self.text_buffer_back.set_text(self.sub_list_store_back[path][1])

            self.text_buffer_front.connect('changed', self.editingCard)
            self.text_buffer_back.connect('changed', self.editingCardBack)

        except IndexError:
            pass

    def editingCard(self, text_buffer):
        path                                = self.selected_row.get_selected_rows()[1][0]
        start_iter_front                    = text_buffer.get_start_iter()
        end_iter_front                      = text_buffer.get_end_iter() 

        self.sub_list_store[path][1]        = text_buffer.get_text(start_iter_front, end_iter_front, True)

        format                              = text_buffer.register_serialize_tagset()
        exported                            = text_buffer.serialize(    text_buffer,
                                                                        format,
                                                                        start_iter_front,
                                                                        end_iter_front )
        
        self.dict_any_change_front[str(path)] = exported

    def editingCardBack(self, text_buffer):
        path                                = self.selected_row.get_selected_rows()[1][0]
        start_iter_back                     = text_buffer.get_start_iter()
        end_iter_back                       = text_buffer.get_end_iter() 

        self.sub_list_store_back[path][1]   = text_buffer.get_text(start_iter_back, end_iter_back, True)

        format              = text_buffer.register_serialize_tagset()
        exported            = text_buffer.serialize(    text_buffer,
                                                        format,
                                                        start_iter_back,
                                                        end_iter_back   )
        self.dict_any_change_back[str(path)] = exported

    def on_toolbar_button_clicked(self, widget, tag_front, tag_back):
        bounds_front    = self.text_buffer_front.get_selection_bounds()
        bounds_back     = self.text_buffer_back.get_selection_bounds()
        path            = self.selected_row.get_selected_rows()[1][0]

        ##### FRONT
        if len(bounds_front) != 0:
            (start, end)        = bounds_front
            selection_front     = self.text_buffer_front.get_text(start, end, True)
            get_insert_front    = self.text_buffer_front.get_insert()

            self.text_buffer_front.apply_tag(tag_front, start, end)

            start_iter_front    = self.text_buffer_front.get_start_iter()
            end_iter_front      = self.text_buffer_front.get_end_iter()
            format              = self.text_buffer_front.register_serialize_tagset()
            exported            = self.text_buffer_front.serialize( self.text_buffer_front,
                                                                    format,
                                                                    start_iter_front,
                                                                    end_iter_front )
            self.dict_any_change_front[str(path)] = exported


        ###### BACK
        if len(bounds_back) != 0:
            (start, end)        = bounds_back
            selection_back      = self.text_buffer_back.get_text(start, end, True)
            get_insert_back     = self.text_buffer_back.get_insert()

            self.text_buffer_back.apply_tag(tag_back, start, end)

            start_iter_back     = self.text_buffer_back.get_start_iter()
            end_iter_back       = self.text_buffer_back.get_end_iter()
            format              = self.text_buffer_back.register_serialize_tagset()
            exported            = self.text_buffer_back.serialize(  self.text_buffer_back,
                                                                    format,
                                                                    start_iter_back,
                                                                    end_iter_back )
            self.dict_any_change_back[str(path)] = exported

按我的意愿工作:)。

编辑

我调整了我的代码以在开始时序列化所有内容并将其放入字典中,而不是将字符串放入字典中,并且编辑文本序列化文本并将其放入字典中,这样可以删除一些 if/else 和 try/except 的.

我还创建了序列化和反序列化的函数,并将这些函数放在另一个文件中,我认为这种方式更好。

  • 我的处理程序文件.py:
...

from myfuncfile import serializeIt, deserializeIt

...
        # dictionary to track the tags
        self.dict_any_change_front  =   {str(key): serializeIt(text_buffer=self.text_buffer_front, tmp_string=value[1]) \
                                        for key, value in enumerate(self.sub_list_store)}

        self.dict_any_change_back   =   {str(key): serializeIt(text_buffer=self.text_buffer_back, tmp_string=value[1]) \
                                        for key, value in enumerate(self.sub_list_store_back)}

    def item_selected(self, *args):
        #   Silencing a indexerror that will occur in case the window was hided and rised again
        # it is not important, can be ignored

        try:
            path                    = self.selected_row.get_selected_rows()[1][0]

            exported_front          = self.dict_any_change_front[str(path)]
            exported_back           = self.dict_any_change_back[str(path)]

            deserializeIt(self.text_buffer_front, exported_front)
            deserializeIt(self.text_buffer_back, exported_back)

            self.text_buffer_front.connect('changed', self.editingCard)
            self.text_buffer_back.connect('changed', self.editingCardBack)

        except IndexError:
            pass

    def editingCard(self, text_buffer_front):
        #   Silencing a indexerror that will occur in case the window was hided and rised again
        # it is not important, can be ignored
        try:
            path                                    = self.selected_row.get_selected_rows()[1][0]
            start_iter_front                        = text_buffer_front.get_start_iter()
            end_iter_front                          = text_buffer_front.get_end_iter() 

            self.sub_list_store[path][1]            = text_buffer_front.get_text(start_iter_front, end_iter_front, True)

            exported                                = serializeIt(text_buffer=text_buffer_front)
            self.dict_any_change_front[str(path)]   = exported
        except IndexError:
            pass

    def editingCardBack(self, text_buffer_back):
        #   Silencing a indexerror that will occur in case the window was hided and rised again
        # it is not important, can be ignored
        try:
            path                                    = self.selected_row.get_selected_rows()[1][0]
            start_iter_back                         = text_buffer_back.get_start_iter()
            end_iter_back                           = text_buffer_back.get_end_iter() 

            self.sub_list_store_back[path][1]       = text_buffer_back.get_text(start_iter_back, end_iter_back, True)

            exported                                = serializeIt(text_buffer=text_buffer_back)
            self.dict_any_change_back[str(path)]    = exported

        except IndexError:
            pass

    def on_toolbar_button_clicked(self, widget, tag_front, tag_back):
        bounds_front    = self.text_buffer_front.get_selection_bounds()
        bounds_back     = self.text_buffer_back.get_selection_bounds()
        path            = self.selected_row.get_selected_rows()[1][0]

        ##### FRONT
        if len(bounds_front) != 0:
            (start, end)        = bounds_front
            selection_front     = self.text_buffer_front.get_text(start, end, True)
            get_insert_front    = self.text_buffer_front.get_insert()

            self.text_buffer_front.apply_tag(tag_front, start, end)

            exported                                = serializeIt(text_buffer=self.text_buffer_front)
            self.dict_any_change_front[str(path)]   = exported


        ###### BACK
        if len(bounds_back) != 0:
            (start, end)        = bounds_back
            selection_back      = self.text_buffer_back.get_text(start, end, True)
            get_insert_back     = self.text_buffer_back.get_insert()

            self.text_buffer_back.apply_tag(tag_back, start, end)

            exported                                = serializeIt(text_buffer=self.text_buffer_back)
            self.dict_any_change_back[str(path)]    = exported
...
  • myfuncfile.py:
...

def serializeIt(text_buffer, tmp_string=None):
    if tmp_string:
        text_buffer.set_text(tmp_string)
        tmp_start_iter  = text_buffer.get_start_iter()
        tmp_end_iter    = text_buffer.get_end_iter()
        tmp_format      = text_buffer.register_serialize_tagset()
        tmp_exported    = text_buffer.serialize( text_buffer,
                                                 tmp_format,
                                                 tmp_start_iter,
                                                 tmp_end_iter )
        return tmp_exported
    else:
        start_iter  = text_buffer.get_start_iter()
        end_iter    = text_buffer.get_end_iter()
        format      = text_buffer.register_serialize_tagset()
        exported    = text_buffer.serialize( text_buffer,
                                             format,
                                             start_iter,
                                             end_iter )
        return exported

def deserializeIt(text_buffer, exported):
    text_buffer.set_text('')
    text_buffer.deserialize(text_buffer,
                            text_buffer.register_deserialize_tagset(),
                            text_buffer.get_start_iter(),
                            exported )
...
于 2020-09-04T02:03:11.120 回答