You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PyGTK窗口获得焦点后失焦自动销毁的报错及功能实现问题

问题修复方案

1. 修复参数不匹配报错

focus-out-event信号的回调方法需要接收3个参数(self、触发事件的控件实例、事件对象),原方法少定义了控件参数,修改方法定义即可:

# 替换原有的on_focus_out_event方法定义
def on_focus_out_event(self, widget, event):
    self.destroy()
    # 可选返回True阻止事件冒泡,避免触发多余的默认行为
    return True

2. 修复失焦不生效的功能问题

需要补充导入Gdk库,给窗口设置弹窗类型标识,让窗口管理器将其识别为临时弹窗,失焦时会正常触发目标事件:
首先在gi导入部分补充Gdk的版本声明和导入:

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

然后在AppWindow的__init__方法中添加窗口属性配置:

# 设置为实用工具弹窗类型,适配临时弹出的交互逻辑
self.set_type_hint(Gdk.WindowTypeHint.UTILITY)
# 可选:去掉标题栏,更符合音量调节弹窗的样式
self.set_decorated(False)

优化建议(非必须)

音量调节的subprocess调用可以去掉shell=True,避免潜在的安全风险,修改如下:

proc = subprocess.Popen(['pactl', 'set-sink-volume', '0', f'{val}%'], stdout=subprocess.PIPE)

完整可运行代码

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

        self.set_border_width(0)
        self.set_size_request(500, -1)
        # 新增窗口属性配置
        self.set_type_hint(Gdk.WindowTypeHint.UTILITY)
        self.set_decorated(False)

        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', f'{val}%'], stdout=subprocess.PIPE)
        proc.wait()

    def on_focus_out_event(self, widget, event):
        self.destroy()
        return True

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)

内容的提问来源于stack exchange,提问作者R. W. Prado

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 03:27:05