tim
tim

Reputation: 407

Gtk3+ Pygobject select columns in a TreeView

Is there an efficient way/a way at all to retrieve the column of the selected cell in a ListModel when a user clicks on a cell in a TreeView? Or is there no such things as Cells and only Rows can be selected and return their treeiter/model when I call the get_selected() method?

I would like to present the user a matrix of numeric values and allow him to select one column, which values will then be plotted.

If you have any documentation/examples at hand, please don't hesitate to share :)

EDIT: What I tried to do was connecting the clicked event on the column headers to a function that gives me the column number I encoded in the column text during creation. But this seems not quite right..

I can create a minimal working example, if that would help..

Upvotes: 2

Views: 813

Answers (2)

zezollo
zezollo

Reputation: 5027

Using Gtk.TreeView.get_cursor() could be another way, though I haven't tested this in the case of columns containing packed data (but not every TreeView requires this feature).

This gives you a direct access to the GtkTreePath and GtkTreeViewColumn matching current focus.

Here's a slightly modified version of @jcoppens example in his answer:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
#  test_coord.py
#
#  Copyright 2016 John Coppens <[email protected]>
#
#  This program is free software```; you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation; either version 2 of the License, or
#  (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program; if not, write to the Free Software
#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
#  MA 02110-1301, USA.
#
#


from gi.repository import Gtk


class MainWindow(Gtk.Window):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.connect("destroy", lambda x: Gtk.main_quit())

        self.trview = Gtk.TreeView()
        tstore = Gtk.ListStore(str, str, str)
        renderer = Gtk.CellRendererText()
        for i in range(3):
            col = Gtk.TreeViewColumn("Col %d" % i, renderer, text=i)
            # col.colnr = i
            self.trview.append_column(col)

        self.trview.set_model(tstore)
        self.trview.get_selection()\
            .connect("changed", self.on_selection_changed)

        for i in range(0, 15, 3):
            tstore.append((str(i), str(i+1), str(i+2)))

        self.add(self.trview)
        self.show_all()

    def on_selection_changed(self, selection):
        print("trview.get_cursor() returns: {}"
              .format(self.trview.get_cursor()))

    def run(self):
        Gtk.main()


def main(args):
    mainwdw = MainWindow()
    mainwdw.run()

    return 0


if __name__ == '__main__':
    import sys
    sys.exit(main(sys.argv))

Upvotes: 0

jcoppens
jcoppens

Reputation: 5440

Accessing 'columns' in GtkTreeView is a little more complicated than suspected at first sight. One of the reasons is that columns can actually contain several items, which are then shown as new column, even though they are 'packed'.

One way to identify columns is to assign a sort_id to each, but that would make the headers clickable, which is unnatural if the sort doesn't actually works.

I devised this (somewhat devious) method:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
#  test_coord.py
#  
#  Copyright 2016 John Coppens <[email protected]>
#  
#  This program is free software```; you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation; either version 2 of the License, or
#  (at your option) any later version.
#  
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#  
#  You should have received a copy of the GNU General Public License
#  along with this program; if not, write to the Free Software
#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
#  MA 02110-1301, USA.
#  
#  


from gi.repository import Gtk

class MainWindow(Gtk.Window):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.connect("destroy", lambda x: Gtk.main_quit())

        trview = Gtk.TreeView()
        tstore = Gtk.ListStore(str, str, str)
        renderer = Gtk.CellRendererText()
        for i in range(3):
            col = Gtk.TreeViewColumn("Col %d" % i, renderer, text = i)
            col.colnr = i
            trview.append_column(col)

        trview.set_model(tstore)
        trview.connect("button-press-event", self.on_pressed)

        for i in range(0, 15, 3):
            tstore.append((str(i), str(i+1), str(i+2)))

        self.add(trview)
        self.show_all()

    def on_pressed(self, trview, event):
        path, col, x, y = trview.get_path_at_pos(event.x, event.y)
        print("Column = %d, Row = %s" % (col.colnr, path.to_string()))

    def run(self):
        Gtk.main()


def main(args):
    mainwdw = MainWindow()
    mainwdw.run()

    return 0

if __name__ == '__main__':
    import sys
    sys.exit(main(sys.argv))

The trick here is to use the possibility Python offers to add attributes to existing classes. So I added a colnr to each column and used that to identify the clicked cell. In C++, it would be necessary to use the set_data and get_data methods to do the same thing (which are not available in Python).

Upvotes: 3

Related Questions