Building a Grid out of FlowBox GTK

Viewed 144

What I'm aiming to do is build a 3x2 grid from within Python Gtk using the FlowBox widget.

The screenshot shows I'm doing the 3x2 perfectly. The problem is that I wanted the buttons to look like smaller squares and not fill up the whole screen. I realize I might have to do this with the grid layout, but I'm just hoping that this wouldve been accomplishable using FlowBox for simplicity. Any ideas?

enter image description here

from gi.repository import Gtk

class MyWindow(Gtk.Window):
    def __init__(self):
        super().__init__(title="Hello World")

        self.box1 = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
        self.add(self.box1)
        self.set_default_size(800, 500);

        self.btnTL= Gtk.Button(label="back")
        self.heading= Gtk.Label(label="Home")
        self.btnTR= Gtk.Button(label="home")
        self.boxT = Gtk.Box()
        self.boxT.pack_start(self.btnTL, False, False, 0)
        self.boxT.pack_start(self.heading,True, True, 0)
        self.boxT.pack_start(self.btnTR, False, False, 0)
        self.box1.add(self.boxT)

        self.cFlow = Gtk.FlowBox()
        self.cFlow.set_valign(Gtk.Align.FILL)
        self.cFlow.set_max_children_per_line(3)
        self.cFlow.set_hadjustment(Gtk.Adjustment(100, 100, 10, 100, 100, 100))
        self.buttonAdd(self.cFlow)
        self.buttonAdd(self.cFlow)
        self.buttonAdd(self.cFlow)
        self.buttonAdd(self.cFlow)
        self.buttonAdd(self.cFlow)
        self.buttonAdd(self.cFlow)
        self.box1.pack_start(self.cFlow,True,True,0)

        self.button1 = Gtk.Button(label="test")
        self.button1.connect("clicked", self.on_button1_clicked)
        #self.box1.pack_start(self.button1, True, True, 0)


        self.btnBL = Gtk.Button(label="L")
        self.bread = Gtk.Label(label="")
        self.btnBR = Gtk.Button(label="R")
        self.boxB = Gtk.Box()
        self.boxB.pack_start(self.btnBL, False, False, 0)
        self.boxB.pack_start(self.bread, True, True, 0)
        self.boxB.pack_start(self.btnBR, False, False, 0)
        self.box1.add(self.boxB)

UPDATE: I made some tweaks but now I get this issue where my window height expands from what I originally set it and I tried everything to eliminate the Xtra space. the window also expands when I add like an 8 character (or more) label to the button.

    def buttonAdd(self,widget):

    self.button2 = Gtk.Button("tffkjdsljdsflkds\nt")
    #self.button2.set_halign(Gtk.Align.CENTER)
    #self.button2.set_valign(Gtk.Align.CENTER)
    #self.button2.set_vexpand(True)
    #self.button2.set_hexpand(True)

    #self.button2.set_property("height-request",100)
    #self.button2.set_property("width-request",150)
    self.button2.connect("clicked",self.clickedTest)
    widget.add(self.button2)

enter image description here

1 Answers

My answer will be in C++, but I think it will be easily translatable to Python.

First of all, the same problem would arise when using Gtk.Grid instead of Gtk.FowBox. The way containers work in Gtk is that you add widgets to your layout and you then specify their sizes using expanding flags and margins. In the following example, I resized the first test button in the Gtk.FlowBox. Look at the MakeButtonsSmaller() method, this is where it happens:

#include <iostream>
#include <gtkmm.h>

// Some contants, just for better readability
constexpr bool EXPAND     = true;
constexpr bool NO_EXPAND  = false;
constexpr bool FILL       = true;
constexpr bool NO_FILL    = false;
constexpr bool NO_PADDING = 0;

class MainWindow : public Gtk::ApplicationWindow
{

public:

    MainWindow();

private:

    void MakeButtonsSmaller();

    Gtk::Box m_box1;

    // Header widgets:
    Gtk::Box m_boxT;
    Gtk::Button m_btnTL{"back"};
    Gtk::Button m_heading{"Home"};
    Gtk::Button m_btnTR{"home"};

    // Main space widgets:
    Gtk::FlowBox m_cFlow;
    Gtk::Button m_button1{"test"};
    Gtk::Button m_button2{"test"};
    Gtk::Button m_button3{"test"};
    Gtk::Button m_button4{"test"};
    Gtk::Button m_button5{"test"};
    Gtk::Button m_button6{"test"};

    // Footer widgets:
    Gtk::Box m_boxB;
    Gtk::Button m_btnBL{"L"};
    Gtk::Button m_bread{""};
    Gtk::Button m_btnBR{"R"};

};

void MainWindow::MakeButtonsSmaller()
{
    m_button1.set_halign(Gtk::Align::ALIGN_CENTER);
    m_button1.set_vexpand(true);
    m_button1.set_margin_bottom(170);
    m_button1.set_margin_top(170);
}

MainWindow::MainWindow()
: m_box1{Gtk::Orientation::ORIENTATION_VERTICAL}
{
    MakeButtonsSmaller();

    set_title("Hello World");
    set_default_size(800, 500);

    add(m_box1);

    // Header:
    m_boxT.pack_start(m_btnTL,   NO_EXPAND, NO_FILL, NO_PADDING);
    m_boxT.pack_start(m_heading, EXPAND,    FILL,    NO_PADDING);
    m_boxT.pack_start(m_btnTR,   NO_EXPAND, NO_FILL, NO_PADDING);
    m_box1.add(m_boxT);

    // Main space:
    m_cFlow.set_valign(Gtk::Align::ALIGN_FILL);
    m_cFlow.set_max_children_per_line(3);
    m_cFlow.set_hadjustment(Gtk::Adjustment::create(100, 100, 10, 100, 100, 100));

    m_cFlow.add(m_button1);
    m_cFlow.add(m_button2);
    m_cFlow.add(m_button3);
    m_cFlow.add(m_button4);
    m_cFlow.add(m_button5);
    m_cFlow.add(m_button6);
    m_box1.pack_start(m_cFlow, EXPAND, FILL, NO_PADDING);

    // Footer:
    m_boxB.pack_start(m_btnBL, NO_EXPAND, NO_FILL, NO_PADDING);
    m_boxB.pack_start(m_bread, EXPAND,    FILL,    NO_PADDING);
    m_boxB.pack_start(m_btnBR, NO_EXPAND, NO_FILL, NO_PADDING);
    m_box1.add(m_boxB);
}

int main(int argc, char *argv[])
{
    std::cout << "Gtkmm version : " << gtk_get_major_version() << "."
                                    << gtk_get_minor_version() << "."
                                    << gtk_get_micro_version() << std::endl;

    auto app = Gtk::Application::create(argc, argv, "org.gtkmm.examples.base");
  
    MainWindow window;
    window.show_all();
  
    return app->run(window);
}

Which yields: enter image description here

I leave it to you to tweak the other buttons, but the basic idea is there.

Related