我有一个带有“下一步”按钮的窗口。单击时,或按下键盘按钮“N”时,它会在浏览器中打开一个 URL。期望的行为是窗口应始终成为焦点,即 url 在后台打开(目标是不断输入键盘按钮“N”,而不必再次单击窗口以突出显示它)。 我有一个在下面工作的实现,除了当浏览器打开时,浏览器窗口接收焦点,因此“N”的键盘按下由浏览器接收,而不是由主窗口接收。我尝试过其他解决方案(请参阅在此处输入链接描述),建议使用
Gtk.window.present
或将窗口设置为“始终在顶部”,但这两种方法都不起作用。
下面代码中的注释可以从我的实现切换到所提供的链接中描述的实现,该实现继承自 Gtk.Application。可悲的是,结果是一样的。 类似的问题还有很多,却没有一个有效的解决方案。我怀疑其实施方式存在根本性错误?有什么见解吗?
import threading
import gi
gi.require_version('Gtk', '3.0')
gi.require_version('Gdk', '3.0')
from gi.repository import Gio, Gdk, Gtk
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.backends.backend_gtk3agg import FigureCanvas
plt.switch_backend('GTK3Agg')
import webbrowser
#class consoleGUI(Gtk.Application):
class consoleGUI():
urls = ('www.google.com', 'www.amazon.com', 'www.lenovo.com', 'www.ford.com')
def __init__(self,):
self.i = 0
#super().__init__(application_id='org.gnome.Ee',
# flags = Gio.ApplicationFlags.FLAGS_NONE)
self.win = Gtk.Window()
#self.win.set_application(self)
self.win.connect('destroy', self.quit)
self.grid = Gtk.Grid()
self.win.add(self.grid)
self.fig, self.axes = plt.subplots(1, 1)
self.canvas = FigureCanvas(self.fig)
self.canvas.set_hexpand(True)
self.canvas.set_vexpand(True)
self.grid.attach(self.canvas, 0, 0, 4, 3)
self.axes.plot(np.arange(10))
self.nav_box = self._add_navigation_toolbar()
self.grid.attach(self.nav_box, 0, 3, 4, 1)
self.win.show_all()
Gtk.main()
def next(self, *args):
self.i = (self.i + 1) % len(self.urls)
#threading.Thread(
# target=webbrowser.open, args=(self.urls[self.i], 2,), ).start()
webbrowser.open(self.urls[self.i], 2)
self.win.present() # This won't work!
def quit(self, *args):
plt.close(self.fig)
Gtk.main_quit()
def _add_navigation_toolbar(self):
box = Gtk.Box()
box.set_orientation(Gtk.Orientation.HORIZONTAL)
box.set_spacing(1)
next_button = Gtk.ToolButton()
next_button.set_label('Next')
next_button._signal_handler = next_button.connect('clicked', self.next)
next_button.set_tooltip_text('Show next\n(key: n)')
self.next_accel = Gtk.AccelGroup()
self.next_accel.connect(
Gdk.keyval_from_name('n'), 0, 0, self._next_target_acc)
self.win.add_accel_group(self.next_accel)
quit_button = Gtk.ToolButton()
quit_button.set_label('Quit') # TODO connect
quit_button._signal_handler = quit_button.connect(
'clicked', self.quit)
quit_button.set_tooltip_text('Close inzimar and discard\nunsaved progress (key: q)')
_accel = Gtk.AccelGroup()
_accel.connect(Gdk.keyval_from_name('q'), 0, 0, self._quit_acc)
self.win.add_accel_group(_accel)
for button in (
next_button, Gtk.SeparatorToolItem(),
quit_button,
Gtk.SeparatorToolItem()):
box.pack_start(button, True, True, 0)
return box
def _next_target_acc(self, *args):
self.next(*args)
def _quit_acc(self, *args):
self.quit(*args)
if __name__=="__main__":
consoleGUI()
我将其简单地称为
python3 console_gui.py
由于网络浏览器是另一个应用程序,因此通常您只能请求窗口管理器,也许会尊重您的要求,让您的窗口获得焦点。许多窗口管理器都会遵守,但不是全部。
尝试present_with_time或set_urgency_hint。 AFAIK 这些是使其工作的功能,但在某些窗口管理器上,如果用户不返回到您的窗口,它可能永远不会工作。
如果您确实确定自己在做什么,您也可以抓住键盘,因此即使焦点在其他地方,按键仍然会转到您的应用程序。但这可能会被用户视为破坏性的(如果我点击您的应用程序,然后尝试切换到聊天并向某人写消息怎么办?)