问题描述
我当时正在与pygtk一起构建我的小项目,该项目使用gtk,基本上有一个窗口,在此窗口中,我有一个树视图,在树视图中有一个gtk.liststore。
Here is a image with the window and its values
一切都很酷,直到我意识到我需要一些标签,看到了许多使用pango的示例,并且它可以正常工作,至少直到选择的行被更改为止。
我用不太优雅的东西解决了这个问题, here a link to the complete code:
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])
基本上,当我单击工具栏的下划线按钮时,此方法会将 放在单词周围,其值将放置在列表存储中,并使用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,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,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,end_iter_front)
self.dict_any_tags[str(path)] = exported
问题是,当我尝试将反序列化放在错误的位置之前,它没有做任何事情。现在,我可以更轻松地跟踪标记在哪里,等等。我只需要运行更多测试。
解决方法
关键是创建另一个迭代器(我使用了字典)来跟踪序列化的文本,然后当我单击一行时,如果值是字节,它将尝试使用反序列化功能,因为不是,它将简单地正常设置文本带有set_text。
同样重要的是,在反序列化之前,将文本设置为no set_text(''),否则缓冲区的先前值将放置在缓冲区当前值的前面。
对于文本的更改,我使用了connect方法来连接'changed'信号,并对更改进行序列化,然后将序列化的值传递给字典。这就是我得到的:
# 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,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,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,True)
get_insert_back = self.text_buffer_back.get_insert()
self.text_buffer_back.apply_tag(tag_back,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,end_iter_back )
self.dict_any_change_back[str(path)] = exported
按我想要的方式工作:)。
修改
我调整了代码以在开始时将所有内容序列化并放在字典中,而不是在字典中放入字符串,也不像编辑文本那样将文本序列化并放入字典中,因此可以删除一些if / else和尝试/例外。
我还创建了对事物进行序列化和反序列化的函数,并将这些函数放在另一个文件中,我认为这种方法更好。
- myhandlerfile.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,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',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,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,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,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)
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,start_iter,end_iter )
return exported
def deserializeIt(text_buffer,exported):
text_buffer.set_text('')
text_buffer.deserialize(text_buffer,exported )
...