• Revista PROGRAMAR: Já está disponível a edição #53 da revista programar. Faz já o download aqui!

NuGuN

[Python] TreeView com AutoScroll

1 mensagem neste tópico

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!

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Crie uma conta ou ligue-se para comentar

Só membros podem comentar

Criar nova conta

Registe para ter uma conta na nossa comunidade. É fácil!


Registar nova conta

Entra

Já tem conta? Inicie sessão aqui.


Entrar Agora