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

Posted

技术标签:

【中文标题】关闭 PyGTK 窗口,如果获得焦点,然后失去焦点【英文标题】:Closing a PyGTK window, if the focus is gain and, after, lost 【发布时间】:2021-10-12 22:49:24 【问题描述】:

我有一个 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 需要三个参数。在第 41 行将 window 参数添加到 self, event

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

【讨论】:

【参考方案2】:

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

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==1print $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'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)

【讨论】:

以上是关于关闭 PyGTK 窗口,如果获得焦点,然后失去焦点的主要内容,如果未能解决你的问题,请参考以下文章

GTKMM/C++ 窗口事件失去/重新获得焦点?

关闭字体对话框时窗口失去焦点

失去焦点时自动关闭 ExtJS 窗口

jsp一个文本框在失去焦点的时候,显示其输入的值,如果没有输入该文本框获得焦点

WPF虚拟键盘如何不获得当前焦点

C# WinForm 文本框离开焦点事件 问题???