2013-02-08 10 views
6

auf einem GTK3-Programm mit Python habe ich ein Protokoll implementiert. Dies ist ein TextView mit TextBuffer in einem ScrolledWindow. Mit einer Routine füge ich eine neue Zeile an dieses Protokoll an. Danach sollte es zur letzten Zeile scrollen.Scrolle zum Ende von ScrolledWindow/TextView

def append_log(self, line): 
    self.textbuffer.insert(self.textbuffer.get_end_iter(), "\n"+line, -1) 
    # scrolling down 

Es sollte wie folgt aussehen: http://www.physik.tu-dresden.de/~s9472632/log_manual.png

Aber es funktioniert nicht. Ich habe den folgenden Code ausprobiert.

# nothing happens 
adj = self.scrolledwindow.get_vadjustment() 
adj.set_value(adj.get_upper()-adj.get_page_size()) # same without subtraction (only upper or page_size) 
self.scrolledwindow.set_vadjustment(adj)    # with and without this line 

.

# nothing happens 
self.textview.scroll_to_iter(self.textbuffer.get_end_iter(), 0.0, False, 0.5, 0.5) 

.

# works a bit but scroll bars cover the text (see picture below) 
self.textview.scroll_to_mark(self.textbuffer.get_insert(), 0.0, False, 0.5, 0.5) 

Bild: http://www.physik.tu-dresden.de/~s9472632/log_scroll.png

Es scheint, die letzten vier Argumente von scroll_to * (within_margin, use_align, xalign, yalign) haben keinen Einfluss der Ergebnisse.

Wie funktioniert es?

Tschüss Markus

+0

Stellen Sie sicher, dass Sie die Add-Methode für untergeordnete Benutzer mit systemeigenen Scroll-Funktionen verwenden. Dies ist "container_add" in C api. – ergosys

Antwort

5

Also ich denke, ich kenne das Problem. Ich denke du hast das falsche Signal angeschlossen, so dass die TextView noch keine neue Größe angefordert hat. Der folgende Code verwendet das Signal der TextView und es funktioniert wie ein Charme.

#!/usr/bin/env python 

from gi.repository import Gtk, GObject 


class W(Gtk.Window): 

    def __init__(self): 

     super(W, self).__init__() 
     self.connect("destroy", Gtk.main_quit) 
     self.set_default_size(200, 400) 

     self._msg_i = 0 
     self._sw = Gtk.ScrolledWindow() 
     self.add(self._sw) 

     self._tw = Gtk.TextView() 
     self._tb = self._tw.get_buffer() 

     self._sw.add_with_viewport(self._tw) 
     #The signal should at least be connected after the scrolled window 
     #is created, since the callback works on it. 
     self._tw.connect("size-allocate", self._autoscroll) 

     GObject.timeout_add(400, self.sim_log) # Invokes spamming 
     self.show_all() 

    def sim_log(self, *args): 
     """A simple spamming function to emulate some sort of logging""" 
     self._msg_i += 1 
     i = self._tb.get_end_iter() 
     self._tb.insert(i, "\n* Message {0} recieved!".format(self._msg_i), -1) 
     return True 

    def _autoscroll(self, *args): 
     """The actual scrolling method""" 
     adj = self._sw.get_vadjustment() 
     adj.set_value(adj.get_upper() - adj.get_page_size()) 


if __name__ == "__main__": 

    w = W() 
    Gtk.main() 
2

Ich hatte gerade dies und machte die scroll_to_mark Linie arbeiten. Ich glaube, Ihr Problem bestand darin, 'use_align' auf 'False' zu setzen. Die Zeile sollte lauten:

self.textview.scroll_to_mark (self.textbuffer.get_insert(), 0,0, True, 0,5, 0,5)

1

Für gtkmm 3.0/C++ 11:

void append(std::string s) { 
    textbuffer->insert(textbuffer->end(), s.c_str()); 

    // Wait for Gui to Redraw with added line to buffer 
    while (gtk_events_pending()) 
    gtk_main_iteration_do(false); 

    // Scoll to end of Buffer 
    auto it = textbuffer->get_iter_at_line(textbuffer->get_line_count()); 
    TextView1.scroll_to(it); 
} 
Verwandte Themen