Jump to content

[Python] TreeView com AutoScroll


NuGuN

Recommended Posts

Boas!

Aqui fica um rápido exemplo de como fazer autoscroll numa TreeView dentro de uma ScrolledWindow.

No seguinte exemplo temos uma TreeView dentro de uma ScrolledWindow e um botão para adicionar linhas (row's) no inicio da TreeView:

# -*- coding: utf-8 -*-

import gtk


class AutoScroll:

    def __init__(self):
        self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
        self.window.connect('delete_event', self.delete_event)
        self.window.connect('destroy', self.destroy)

        self.scrolled_window = gtk.ScrolledWindow()
        self.scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)

        self.inc = 0 # Serve apenas como contador para o número que aparece na TreeView.
        self.ls = self.cm()

        treeview = gtk.TreeView(self.ls)
        treeview.set_rules_hint(True)

        self.scrolled_window.add(treeview)

        rendererText = gtk.CellRendererText()
        column = gtk.TreeViewColumn("ID", rendererText, text=0)
        column.set_sort_column_id(0)
        treeview.append_column(column)

        vbox = gtk.VBox(False, 0)
        vbox.pack_start(self.scrolled_window, True, True, 0)

        button = gtk.Button("Incermenta!")
        button.connect("clicked", self.incrementa)
        vbox.pack_start(button, False, False, 0)

        self.window.add(vbox)

        self.window.set_default_size(300,200)
        self.window.show_all()



    def incrementa(self, widget):
        self.ls.prepend([self.inc]) # Adiciona uma nova 'row' à TreeView
        self.inc += 1
            

    def cm(self):
        store = gtk.ListStore(int)
        return store


    def delete_event(self, widget, event, data=None):
        return False


    def destroy(self, widget, data=None):
        gtk.main_quit()


    def main(self):
        gtk.main()



if __name__ == '__main__':
    app = AutoScroll()
    app.main()

Quando o número de linhas na TreeView é superior ao que o tamanho actual da janela consegue mostrar, o scroll é activado! Ate aqui tudo bem... O problema é que em vez de fazer scroll para o ultimo valor adicionado, neste caso esta na primeira linha, faz scroll quase para o final da lista!

Para resolver este problema, pegando no código acima postado,  primeiro temos de adicionar um objecto do tipo gtk.Adjustment. Este objecto da-nos valores como o tamanho que a TreeView está a ocupar dentro da ScrolledWindo (upper), o tamanho da janela visivel (page_size), etc. Para mais detalhes, gtk.Adjustment

self.adj = self.scrolled_window.get_vadjustment()

self.adj, será o nosso objecto gtk.Adjustment.

Depois é preciso saber quando é preciso fazer autoscroll. Para isso arranjamos um handler para um dos sinais do objecto que é gerado  quando ha alguma alteração aos valores do scroll.

self.adj.connect('changed', self.scroll_changed)

Onde 'changed' é o nome do sinal e self.scroll_changed é a função que irá fazer o handle do sinal.

Além do sinal 'changed' que é gerado quando qualquer valor do objecto é alterado (value, upper, lower, step_increment, etc), existe também o sinal 'value_changed' que apenas é gerado quando ha uma alteração do valor 'value' que indica quanto foi o ajuste do scroll.

Em seguida adiciona-se o handler para o sinal.

    def scroll_changed(self, adj):
        self.adj.set_value(self.adj.get_property('lower'))
        self.scrolled_window.set_vadjustment(self.adj)
        print adj.value, adj.lower, adj.upper, adj.step_increment, adj.page_increment, adj.page_size

self.adj.set_value(self.adj.get_property('lower')) - self.adj.set_value() serve para ajustar o scroll numa posição especifica e self.adj.get_property('lower') retorna o valor minimo a que se pode ajustar o scroll, que neste caso é '0.0'. Estes atributos funcionam com valores do tipo float, logo, é '0.0' e nao '0'.

self.scrolled_window.set_vadjustment(self.adj) - configura-se a ScrolledWindow com os novos valores.

Resultado:

# -*- coding: utf-8 -*-

import gtk





class AutoScroll:

    def __init__(self):
        self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
        self.window.connect('delete_event', self.delete_event)
        self.window.connect('destroy', self.destroy)


        self.scrolled_window = gtk.ScrolledWindow()
        self.scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)

######################################################################################################
        self.adj = self.scrolled_window.get_vadjustment()
        self.adj.connect('changed', self.scroll_changed)
######################################################################################################

        self.inc = 0 # Serve apenas como contador para o número que aparece na TreeView.
        self.ls = self.cm()


        treeview = gtk.TreeView(self.ls)
        treeview.set_rules_hint(True)

        self.scrolled_window.add(treeview)

        rendererText = gtk.CellRendererText()
        column = gtk.TreeViewColumn("ID", rendererText, text=0)
        column.set_sort_column_id(0)
        treeview.append_column(column)

        vbox = gtk.VBox(False, 0)
        vbox.pack_start(self.scrolled_window, True, True, 0)

        button = gtk.Button("Incermenta!")
        button.connect("clicked", self.incrementa)
        vbox.pack_start(button, False, False, 0)

        self.window.add(vbox)

        self.window.set_default_size(300,200)
        self.window.show_all()


    def incrementa(self, widget):
        self.ls.prepend([self.inc]) # Adiciona uma nova 'row' à TreeView
        self.inc += 1
######################################################################################################
    def scroll_changed(self, adj):
        self.adj.set_value(self.adj.get_property('lower'))
        self.scrolled_window.set_vadjustment(self.adj)
        print adj.value, adj.lower, adj.upper, adj.step_increment, adj.page_increment, adj.page_size
######################################################################################################

            

    def cm(self):
        store = gtk.ListStore(int)
        return store


    def delete_event(self, widget, event, data=None):
        return False



    def destroy(self, widget, data=None):
        gtk.main_quit()


    def main(self):
        gtk.main()


if __name__ == '__main__':
    app = AutoScroll()
    app.main()

Para fazer o autoscroll quando as linhas são adicionadas no final da TreeView basta alterar as seguintes linhas:

self.ls.prepend([self.inc]) # Adiciona uma nova 'row' no inicio da TreeView

para

self.ls.append([self.inc]) # Adiciona uma nova 'row' no final da TreeView

self.adj.set_value(self.adj.get_property('lower'))

para

self.adj.set_value(self.adj.get_property('upper'))

E por agora é só  🙂

Cumps!

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.