1
votes

I'm currently developing a PyGObject app and I'm having issues selecting specific children in a Gtk+ FlowBox. Even after selecting the FlowBox selection mode (SINGLE) populating the FlowBox and writing code to select a specific child, the first child is always selected.

#!/usr/bin/python

import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gio

class App(Gtk.Window):

    def __init__(self):
        Gtk.Window.__init__(self, title="App")

        flowbox = Gtk.FlowBox()
        flowbox.set_valign(Gtk.Align.START)
        flowbox.set_selection_mode(Gtk.SelectionMode.SINGLE)

        # Drawing 3 squares
        flowbox.add(self.drawing_area())
        flowbox.add(self.drawing_area())
        flowbox.add(self.drawing_area())

        child = flowbox.get_child_at_index(2)
        flowbox.select_child(child)
        flowbox.queue_draw()

        self.add(flowbox)

    def drawing_area(self):
        preview = Gtk.DrawingArea()
        preview.connect("draw", self.draw_square)
        preview.set_size_request(150, 150)
        return preview

    def draw_square(self, widget, cr):
        cr.scale(150, 150)

        style_context = widget.get_style_context()
        color = style_context.get_color(Gtk.StateFlags.NORMAL)
        cr.set_source_rgba(*color)

        cr.rectangle(0, 0, 1, 1)
        cr.fill()

window = App()
window.connect("delete-event", Gtk.main_quit)
window.show_all()
Gtk.main()

Even though I choose to select the child at index 2, the app only ever shows the first child being selected: Screenshot of above code running

The strange part is that when I check to see which child is selected using the following code (placed before the "self.add(flowbox)" line), the Terminal displays that the child I specified to be selected (at index 2) is the only selected child, even though the window only shows the first child being selected:

for child in flowbox.get_selected_children():
    print child.get_index()
1
What specific version of GTK+?andlabs
I'm using Ubuntu 16.04, so Gtk+ 3.18.Thomas Stevenson

1 Answers

1
votes

I think you have located a bug in GTK, it seems that something in show_all is messing up. My first guess was that it was caused by the fact that the FlowBox wasn't realized so I changed your code to use the show signal (realize but show is emitted later) and checked whether it still happend. Sadly it was..

So I got the feeling that something else was off so just a quick test added self.show() right after Gtk.Window.__init__ this made the selection work but made the Flowbox wider than needed (probably because of the default width of a empty window). So I added the self.show() in the listener and this actually solved the issue.

The complete code is as follows, but as it is a dirty workaround you should still report this bug.

#!/usr/bin/python

import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gio

class App(Gtk.Window):

    def __init__(self):
        Gtk.Window.__init__(self, title="App")

        self.flowbox = Gtk.FlowBox()
        self.flowbox.set_valign(Gtk.Align.START)
        self.flowbox.set_selection_mode(Gtk.SelectionMode.SINGLE)

        # Drawing 3 squares
        self.flowbox.add(self.drawing_area())
        self.flowbox.add(self.drawing_area())
        self.flowbox.add(self.drawing_area())

        self.flowbox.connect("show", self.on_realize)

        self.add(self.flowbox)

    def on_realize(self, flowbox):
        # The creative workaround/hack
        self.show()
        child = self.flowbox.get_child_at_index(2)
        self.flowbox.select_child(child)

    def drawing_area(self):
        preview = Gtk.DrawingArea()
        preview.connect("draw", self.draw_square)
        preview.set_size_request(150, 150)
        return preview

    def draw_square(self, widget, cr):
        cr.scale(150, 150)

        style_context = widget.get_style_context()
        color = style_context.get_color(Gtk.StateFlags.NORMAL)
        cr.set_source_rgba(*color)

        cr.rectangle(0, 0, 1, 1)
        cr.fill()

window = App()
window.connect("delete-event", Gtk.main_quit)
window.show_all()
Gtk.main()