关闭 PyGTK window,如果获得焦点,然后失去焦点

Closing a PyGTK window, if the focus is gain and, after, lost

我在 Python3 中有一个程序可以改变我系统的音量。我想要的行为是它像一个弹出窗口 window,它将在 window 之后自行销毁,首先获得焦点,然后失去焦点。

我的代码有两个问题。第一,失去焦点时它不会自行关闭,给我一个错误:

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)

focus-out-event 需要三个参数。将 window 参数添加到第 41 行的 self, event

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

在 Alperen 的回答下,我能够制作一个可以静音和更改系统音量的应用程序。我的应用程序只会在比例已更改或按钮至少被切换一次并且之后 window 失去焦点时关闭。这不是我第一个想要的行为,但我认为现在实施得更好。

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 }' | 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'yes\n'.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'yes\n'.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)