Закрытие окна PyGTK, если фокус увеличен, а затем потерян

#python-3.x #gtk3 #pygtk

Вопрос:

У меня есть программа на Python3, которая может изменять громкость моей системы. Поведение, которое я хочу, чтобы оно было похоже на всплывающее окно, которое уничтожит себя после того, как окно сначала сфокусируется, а затем потеряет фокус.

В моем коде есть две проблемы. Во-первых, он не закрывается сам по себе, когда фокус теряется, что дает мне ошибку:

 on_focus_out_event() takes 2 positional arguments, but 3 were given.
 

И все же, даже решив эту ошибку, я бы не добился желаемого поведения.

Это моя первая программа, написанная на Python, к сожалению, мне нужна близкая помощь в этом. Если бы кто-нибудь мог мне помочь, я был бы очень признателен.

 #!/usr/bin/python3
    
import sys
import subprocess
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
    
class AppWindow(Gtk.ApplicationWindow):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.set_border_width(0)
        self.set_size_request(500, -1)

        scale_float = Gtk.Scale.new_with_range(Gtk.Orientation.HORIZONTAL, 0.0, 153, 1.0)
        scale_float.set_value_pos(Gtk.PositionType.LEFT)
        scale_float.connect('value-changed', self.on_value_changed)
        scale_float.show_all()

        label_box = Gtk.Box()
        label_box.pack_start(
        Gtk.Image.new_from_icon_name('audio-volume-high', 1), False, False,5)
        label_box.pack_start(Gtk.Label(label=''), True, True, 0)
        label_box.show_all()

        notebook = Gtk.Notebook()
        notebook.append_page(scale_float, label_box)
        notebook.set_tab_pos(Gtk.PositionType.RIGHT)
            
        self.connect('focus-out-event', self.on_focus_out_event)
        self.add(notebook)
        self.show_all()


    def on_value_changed(self, scale_float):
        val = int(scale_float.get_value())
        proc = subprocess.Popen('pactl set-sink-volume 0 '   str(val)   '%', shell=True, stdout=subprocess.PIPE)
        proc.wait()

    def on_focus_out_event(self, event):
        self.destroy()

class Application(Gtk.Application):
    
    def __init__(self, *args, **kwargs):
        super().__init__(*args, application_id="org.example.volume_control",**kwargs)
        self.window = None
    
    def do_activate(self):
        if not self.window:
            self.window = AppWindow(application=self,title="")
            self.window.show_all()
            self.window.present()

if __name__ == "__main__":
    app = Application()
    app.run(sys.argv)
 

Ответ №1:

focus-out-event требуется три аргумента. Добавьте window аргумент self, event в строку 41.

     def on_focus_out_event(self, event, window):
        self.destroy()
 

введите описание изображения здесь

Ответ №2:

С ответом Альперена я смог создать приложение, которое может отключать звук и изменять громкость моей системы. Мое приложение закроется только в том случае, если масштаб был изменен или если кнопка была переключена хотя бы один раз, и после этого окно теряет фокус. Это не мое первое желаемое поведение, но я думаю, что сейчас оно реализовано еще лучше.

P.S.: Я не уверен, правильно ли выделен отступ в коде.

 #!/usr/bin/python3

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

class AppWindow(Gtk.ApplicationWindow):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.set_border_width(0)
        self.set_size_request(500, -1)

        volume = subprocess.Popen("pacmd dump-volumes | awk 'NR==1{print $8}' | sed 's/%//'", shell=True, stdout=subprocess.PIPE)
        volume_str = volume.stdout.read()

        scale_float = Gtk.Scale.new_with_range(Gtk.Orientation.HORIZONTAL, 0.0, 153, 1.0)
        scale_float.set_value(int(volume_str))
        scale_float.set_draw_value(False)
        scale_float.set_value_pos(Gtk.PositionType.LEFT)
        scale_float.connect('value-changed', self.on_value_changed)
        scale_float.show_all()

        ismuted = subprocess.Popen("pacmd list-sinks | grep muted | sed -e 's/.*: //g'", shell=True, stdout=subprocess.PIPE)

        if ismuted.stdout.read().decode() == b'yesn'.decode():
            image=Gtk.Image.new_from_icon_name('audio-volume-muted', 1)
        else:
            image=Gtk.Image.new_from_icon_name('audio-volume-high', 1)
        button = Gtk.Button()
        button.set_image(image)
        button.connect("clicked", self.on_button_clicked )
        button.show_all()

        notebook = Gtk.Notebook()
        notebook.append_page(scale_float, button)
        notebook.set_tab_pos(Gtk.PositionType.RIGHT)

        self.add(notebook)
        self.show_all()

    def on_value_changed(self, scale):
        val = int(scale.get_value())
        proc = subprocess.Popen('pactl set-sink-volume 0 '   str(val)   '%', shell=True, stdout=subprocess.PIPE)
        proc.wait()
        self.connect('focus-out-event', self.on_focus_out_event)

    def on_focus_out_event(self, widget, window):
        self.destroy()

    def on_button_clicked(self, button):
        subprocess.Popen("pactl set-sink-mute 0 toggle", shell=True, stdout=subprocess.PIPE)
        ismuted = subprocess.Popen("pacmd list-sinks | grep muted | sed -e 's/.*: //g'", shell=True, stdout=subprocess.PIPE)
        if ismuted.stdout.read().decode() == b'yesn'.decode():
            image=Gtk.Image.new_from_icon_name('audio-volume-muted', 1)
        else:
            image=Gtk.Image.new_from_icon_name('audio-volume-high', 1)
        button.set_image(image)
        self.connect('focus-out-event', self.on_focus_out_event)

class Application(Gtk.Application):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, application_id="org.example.volume_control",**kwargs)
        self.window = None

    def do_activate(self):
        if not self.window:
            self.window = AppWindow(application=self,title="")
            self.window.show_all()
            self.window.present()

if __name__ == "__main__":
    app = Application()
    app.run(sys.argv)