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
相关产品推荐
相关产品推荐

