Как обработать сигнал "notify :: active" от Gtk.Switch? (Архитектура MVC) - PullRequest
0 голосов
/ 09 мая 2018

Я не могу понять, как обрабатывать сигнал notify::active для Gtk.Switch. Я работаю с архитектурой MVC (шаблон) предлагается здесь .

Я получил следующую ошибку:

TypeError: _on_switch_serial_toggled() missing 1 required positional argument: 'state'

Вот мой минимальный рабочий пример (без модели):

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


class Application(Gtk.Application):
    def __init__(self):
        app_id = "org.iea.etc"
        flags = Gio.ApplicationFlags.FLAGS_NONE

        super(Application, self).__init__(application_id=app_id, flags=flags)

    def do_activate(self):
        # c.Controller(m.Model(), v.View(application=self))
        Controller(None, View(application=self))

    def do_startup(self):
        Gtk.Application.do_startup(self)


class Controller(object):
    def __init__(self, model, view):
        self._model = model
        self._view = view

        self._view.connect('switch_serial_toggled',
                           self._on_switch_serial_toggled)

        self._view.show_all()

    def _on_switch_serial_toggled(self, switch, state):
            if switch.get_active():
                print('Switch ON')
            else:
                print('Switch OFF')


class View(Gtk.ApplicationWindow):
    __gsignals__ = {
        'switch_serial_toggled': (GObject.SIGNAL_RUN_FIRST, None, ())
    }

    def __init__(self, **kw):
        super(View, self).__init__(**kw)

        self._switch_serial = Gtk.Switch()
        self._switch_serial.connect("notify::active",
                                    self.on_switch_serial_toggled)

        self.add(self._switch_serial)

    def on_switch_serial_toggled(self, switch, state):
        self.emit('switch_serial_toggled')


if __name__ == '__main__':
    app = Application()
    exit_status = app.run(sys.argv)
    sys.exit(exit_status)

1 Ответ

0 голосов
/ 10 мая 2018

Прежде всего, вы правильно обрабатываете сигнал notify для свойства active Gtk.Switch почти . Проблема заключается в обработке пользовательского сигнала, который вы добавили в свое представление.

Важно понимать, что вы делаете: вы создали класс View, у которого есть свойство, которое представляет собой Gtk.Switch. Вы также создали сигнал с именем switch_serial_toggled, связанный с этим классом. Внутри класса вы хотите, чтобы, когда внутренний Gtk.Switch изменял состояние, View запускал свой собственный «переключаемый» сигнал.

Как говорится, давайте исправим ваш код:

1 - позволяет добавить состояние переключения в представление switch_serial_toggled как логическое значение

class View(Gtk.ApplicationWindow):
    __gsignals__ = {
        'switch_serial_toggled': (GObject.SIGNAL_RUN_FIRST, None, (bool,))
    }

2 - позволяет дать правильные имена аргументам обработчика внутреннего сигнала View и добавить состояние к излучаемому сигналу:

def on_switch_serial_toggled(self, obj, pspec):
    self.emit('switch_serial_toggled', self._switch_serial.get_active ())

Обработчик сигнала уведомления GObject.Object имеет значение , описанное здесь

3 - Теперь перейдем к контроллеру и правильно обработаем сигнал просмотра:

def _on_switch_serial_toggled(self, widget, active):
        if active is True:
            print('Switch ON')
        else:
            print('Switch OFF')

widget аргумент - это экземпляр View внутри экземпляра Controller, а state - логическое значение, которое передается с излучением сигнала.

Полный код с приведенными выше исправлениями должен выглядеть следующим образом:

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


class Application(Gtk.Application):
    def __init__(self):
        app_id = "org.iea.etc"
        flags = Gio.ApplicationFlags.FLAGS_NONE

        super(Application, self).__init__(application_id=app_id, flags=flags)

    def do_activate(self):
        # c.Controller(m.Model(), v.View(application=self))
        Controller(None, View(application=self))

    def do_startup(self):
        Gtk.Application.do_startup(self)


class Controller(object):
    def __init__(self, model, view):
        self._model = model
        self._view = view

        self._view.connect('switch_serial_toggled',
                           self._on_switch_serial_toggled)

        self._view.show_all()

    def _on_switch_serial_toggled(self, widget, active):
            if active is True:
                print('Switch ON')
            else:
                print('Switch OFF')


class View(Gtk.ApplicationWindow):
    __gsignals__ = {
        'switch_serial_toggled': (GObject.SIGNAL_RUN_FIRST, None, (bool,))
    }

    def __init__(self, **kw):
        super(View, self).__init__(**kw)

        self._switch_serial = Gtk.Switch()
        self._switch_serial.connect("notify::active", self.on_switch_serial_toggled)

        self.add(self._switch_serial)

    def on_switch_serial_toggled(self, obj, pspec):
        self.emit('switch_serial_toggled', self._switch_serial.get_active ())


if __name__ == '__main__':
    app = Application()
    exit_status = app.run(sys.argv)
    sys.exit(exit_status)

В результате получается что-то вроде этого:

enter image description here

PS : обратите внимание, что на шаге 2 obj - это объект, к которому вы подключили обработчик сигнала, аналогичный self._switch_serial. Это означает, что вы можете использовать obj.get_active () вместо:

def on_switch_serial_toggled(self, obj, pspec):
    self.emit('switch_serial_toggled', obj.get_active ())
...