2013-10-01 2 views
0

코드의 첫 번째 섹션은 게시 된 원래 코드입니다. 두 번째 코드는 올바른 방향으로 이끌어 준 Bob의 대답을 수정 한 것입니다.PyGtk TextView에서 빈 줄에 텍스트 속성을 설정하는 방법은 무엇입니까?

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() 

답변

0

다음은 코드를 수정 한 것입니다. 방금 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() 
+0

당신은 올바른 방향으로 나를 이끌어주었습니다. Expose는 호출이 넘치므로 한 번만 호출되도록 수정했습니다. 원래 질문 인 두 번째 코드 섹션을 참조하십시오. 한 번 전화를 걸 수있는 올바른 방법인지는 확실하지 않지만 홍수를 막을 수는 있습니다. – mikkx

+0

@mikkx 병목 현상과 수천 건의 전화를 어떻게 알게 되었습니까? cProfile을 사용하고 있었습니까? 왜냐하면 나는이 괴물 같은 pygtk를 디버깅 할 방법을 찾고 있습니다. 여기 내 질문에 대한 답변을 찾을 수 없습니다 : http://stackoverflow.com/questions/19120258/gtk-treeview-20-line-minimal-script-wont-show-treeview-itself-within-the-windo –

+0

아니요, 콜백 메소드에서 인쇄를 사용하고 카운터를 증가 시켰습니다. – mikkx