How to allow only one instance of a given class?

4

If we run the code below, a window with a button inside will be created, which whenever clicked will open another window (Window2). How can I make a second instance of Window2 not be allowed? I want to do this without using modal ().

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

from gi.repository import Gtk

class Main(Gtk.Window):
    def __init__(self):
        button = Gtk.Button('Click')
        Gtk.Window.__init__(self, title = 'Main Window')
        button.connect('clicked', Window2)
        self.connect('delete-event', Gtk.main_quit)
        self.set_default_size(300, 200)
        self.add(button)
        self.show_all()

class Window2(Gtk.Window):
    def __init__(self, widget):
        button = Gtk.Button('Exit')
        Gtk.Window.__init__(self, title = 'Window2')
        button.connect('clicked', Gtk.main_quit)
        self.set_default_size(300, 200)
        self.add(button)
        self.show_all()


if __name__ == '__main__':
    Main()
    Gtk.main()
    
asked by anonymous 01.07.2014 / 19:42

3 answers

3

In the general case, one answer is to use Singleton, such as pointed out by Diego Vieira in the comments . In your specific case, I think you just have to change the behavior of the button to not create a window every time:

class Main(Gtk.Window):
    def __init__(self):
        self.window2 = None     # Cria-se uma referência no self para a janela

        button = Gtk.Button('Click')
        Gtk.Window.__init__(self, title = 'Main Window')
        button.connect('clicked', self.mostrar_janela)    # Mostra-a quando clicar no botão
        self.connect('delete-event', Gtk.main_quit)
        self.set_default_size(300, 200)
        self.add(button)
        self.show_all()

    def mostrar_janela(self):
        if not self.window2:
            self.window2 = Window2()
        # else mostrar janela ?
    
01.07.2014 / 19:52
0

I found a feasible solution to the question of allowing only one instance of a particular window in Gtk

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

from gi.repository import Gtk

class Main(Gtk.Window):
    def __init__(self):
        button = Gtk.Button('Click')
        Gtk.Window.__init__(self, title = 'Main Window')
        button.connect('clicked', self.run_window2)
        self.connect('delete-event', Gtk.main_quit)
        self.set_default_size(300, 200)
        self.add(button)
        self.show_all()

    def run_window2(self, widget):
        try:
            #Chama a janela para frente, se a janela ainda não existe,
            #ocorre um AttributeError, passando então para o except e assim criando a janela. 
            self.window2.present()
        except:
            self.window2 = Window2()

class Window2(Gtk.Window):
    def __init__(self):
        button = Gtk.Button('Exit')
        Gtk.Window.__init__(self, title = 'Window2')
        button.connect('clicked', Gtk.main_quit)
        self.set_default_size(300, 200)
        self.add(button)
        self.show_all()


if __name__ == '__main__':
    Main()
    Gtk.main()
    
11.01.2015 / 16:06
0

Without wanting to demean the other answers and although they are correct and solve the specific case, perhaps in a better way, also without going into merits if singleton is a good design pattern or not my suggestion is for other cases in general.

How to allow only one instance of a given class?

In other words:

How to create a singleton in python?

Using metaclasses:

class Singleton(type):
    _instances = {}
    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
        return cls._instances[cls]

class Window(object):
    __metaclass__ = Singleton

Or in Python 3

class Window(metaclass=Singleton):
    pass

And finally if you want __init__ to be called every time the class is called add:

    else:
        cls._instances[cls].__init__(*args, **kwargs)

source: Blatantly inspired link

    
11.01.2015 / 16:47