Vianney Bailleux
Vianney Bailleux

Reputation: 423

python GTK+ action in many files

I spread my code in several files but I do not know how to make the child file interact with the main file.

example fichier1:

#!/usr/bin/env python3
# coding: utf-8

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

class MainWindow(Gtk.Window):

    def __init__(self):
        Gtk.Window.__init__(self)

        self.grid = Gtk.Grid()
        self.add(self.grid)

        self.label = Gtk.Label("An example of a Label widget.")

        self.menuBar = Menu()

        self.grid.attach(self.menuBar, 0, 0, 1, 1)
        self.grid.attach(self.label, 1, 0, 1, 1)

    def onClick(self, button):
        self.label.set_label('Test OK')

win = MainWindow()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main()

Fichier2:

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

class Menu(Gtk.Grid):

menuUi= "/home/vianney/programmes/Menu.ui"

def __init__(self):
    Gtk.Grid.__init__(self)

    action_group = Gtk.ActionGroup("my_actions")

    self.AddActionMenu(action_group)

    uimanager = self.create_ui_manager()
    uimanager.insert_action_group(action_group)

    menubar = uimanager.get_widget("/MenuBar")

    self.attach(menubar, 0, 0, 1, 1)

def AddActionMenu(self, action_group):
    action_group.add_actions([
        ("ActionMenu", None, "Edition"),
        ("AddGame", None, "Add Game", None, None, self.AddGame)
    ])

def AddGame(self, widget):
    self.label.set_label('Test OK')

def create_ui_manager(self):
    uimanager = Gtk.UIManager()
    uimanager.add_ui_from_file(self.menuUi)
    return uimanager

here is the menu file:

<ui>
    <menubar name='MenuBar'>
        <menu action='ActionMenu'>
            <menuitem action='AddGame' />
        </menu>
    </menubar>
</ui>

in this example I would have changed the contents of the label in the file 1 belong to the file 2 menu

Thank you very much for your help

Upvotes: 2

Views: 150

Answers (1)

Jos&#233; Fonte
Jos&#233; Fonte

Reputation: 4114

There are many ways to achieve your goals but following the common Gtk way, would be to create signals to your own custom composite widgets.

Let's create a signal, called add-game-clicked, so when a user clicks that menu option a signal in the Menu class will be triggered / emitted.

To do that on your code, we add:

self.menu.connect ("add-game-clicked", self.onAddGameClicked)

And then, rename the method onClick to something more meaningful like onAddGameClicked

So, your main python file, let's call it main.py, will be:

#!/usr/bin/env python3
# coding: utf-8

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

class MainWindow(Gtk.Window):

    def __init__(self):
        Gtk.Window.__init__(self)

        self.grid = Gtk.Grid()
        self.add(self.grid)

        self.label = Gtk.Label("An example of a Label widget.")

        self.menuBar = Menu()
        self.menuBar.connect ("add-game-clicked", self.onAddGameClicked)

        self.grid.attach(self.menuBar, 0, 0, 1, 1)
        self.grid.attach(self.label, 1, 0, 1, 1)

    def onAddGameClicked(self, widget):
        self.label.set_label('Test OK')

win = MainWindow()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main()

Then we need to create a signal on your custom composite widget. To do that we add:

__gsignals__ = {
    'add-game-clicked': (GObject.SIGNAL_RUN_FIRST, None, ())
}

below the class definition and then emit the signal when the right event happens:

def AddGame(self, widget):
    self.emit("add-game-clicked")

Its important to say that python is: indentation, indentation, indentation, and your TestMenu.py file it's not correctly indented.

So your TestMenu.py file should be like this:

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

class Menu(Gtk.Grid):

    __gsignals__ = {
        'add-game-clicked': (GObject.SIGNAL_RUN_FIRST, None, ())
    }

    menuUi= "Menu.ui"

    def __init__(self):
        Gtk.Grid.__init__(self)

        action_group = Gtk.ActionGroup("my_actions")

        self.AddActionMenu(action_group)

        uimanager = self.create_ui_manager()
        uimanager.insert_action_group(action_group)

        menubar = uimanager.get_widget("/MenuBar")

        self.attach(menubar, 0, 0, 1, 1)

    def AddActionMenu(self, action_group):
        action_group.add_actions([
            ("ActionMenu", None, "Edition"),
            ("AddGame", None, "Add Game", None, None, self.AddGame)
        ])

    def AddGame(self, widget):
        self.emit("add-game-clicked")

    def create_ui_manager(self):
        uimanager = Gtk.UIManager()
        uimanager.add_ui_from_file(self.menuUi)
        return uimanager

Also notice that setting full path to files in this context ain't good. Use relative paths in your project otherwise things become too rigid and less portable.

Using the supplied Menu.ui file we should get something like this:

result

After clicking the Add Game menu option, the label will change.

Upvotes: 1

Related Questions