#python #wxpython #focus #pyhook
#python #wxpython #фокус #pyhook
Вопрос:
Я пытался использовать pyxhook с wxPython. Предполагается, что программа должна делать, когда окно скрыто или свернуто, когда пользователь нажимает «R_Control», даже когда другое приложение все еще находится в фокусе, окно wxPython должно отображаться и находиться в фокусе. Но вместо этого он просто запросил userattention, мигая на панели задач. Я пробовал использовать Raise()
, Restore()
, но он по-прежнему не работает. Вот упрощенная версия кода
import wx, pyxhook
class Frame(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__(self, name='', parent=parent, title='test')
self.panel = wx.Panel(self, wx.ID_ANY)
self.text_input = wx.TextCtrl(self.panel)
self.moduleSizer = wx.BoxSizer(wx.VERTICAL)
self.panel.SetSizer(self.moduleSizer)
self.moduleSizer.Add(self.text_input, flag=wx.ALIGN_CENTER)
self.text_input.Bind(wx.EVT_KEY_DOWN, self.onKeyDown)
self.moduleSizer.Fit(self)
self.text_input.SetFocus()
def onKeyDown(self, event):
if event.GetKeyCode() == wx.WXK_ESCAPE: self.Hide()
event.Skip()
class HookMan(pyxhook.HookManager):
def __init__(self,frame,master=None):
pyxhook.HookManager.__init__(self,master)
self.frame = frame
self.KeyDown = self.key_down
self.HookKeyboard()
def key_down(self,event):
if event.Key == 'Control_R':
self.frame.Show()
if __name__ == '__main__':
app = wx.App()
frame = Frame(None)
hookman = HookMan(frame)
hookman.start()
frame.Show()
app.MainLoop()
Я пробовал это с TkInter, и это просто работает. root.deconify()
просто установите окно в фокусе. Как мне воссоздать это поведение в wxPython?
import pyxhook
import tkinter as tk
class Root(tk.Tk):
def __init__(self,master=None):
tk.Tk.__init__(self,master)
self.title('test')
self.text_input = tk.Entry(self)
self.text_input.pack()
self.bind("<Escape>", self.minimize)
def minimize(self,event):
self.withdraw()
class HookMan(pyxhook.HookManager):
def __init__(self,frame,master=None):
pyxhook.HookManager.__init__(self,master)
self.frame = frame
self.KeyDown = self.key_down
self.HookKeyboard()
def key_down(self,event):
if event.Key == 'Control_R':
self.frame.deiconify()
if __name__ == '__main__':
root = Root()
hookman = HookMan(root)
hookman.start()
root.text_input.focus_set()
root.mainloop()
Комментарии:
1. Вы уверены? Запустите его, не имея ничего на рабочем столе, оно вполне может находиться под другими окнами. Если не добавить свою платформу к вопросу, это может иметь значение.
2. Мой плохой .. после того, как я повозился с некоторыми настройками, я понял, что речь идет о моей среде рабочего стола. Я использую KDE Plasma 5.18, и есть опция предотвращения кражи фокуса. Программа работает нормально, когда я отключаю предотвращение кражи фокуса.
Ответ №1:
Для справки, представленный вами код (по крайней мере, в Linux с wx 4.1.0) действительно работал. Окно было восстановлено под существующими окнами.
Используя SetWindowStyle
и перенастраивая вызовы pyxhook
, мы можем заставить этот код функционировать надлежащим образом.
import wx
import pyxhook
class Frame(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__(self, name='', parent=parent, title='test')
self.SetWindowStyle(wx.STAY_ON_TOP)
self.panel = wx.Panel(self, wx.ID_ANY)
self.text_input = wx.TextCtrl(self.panel)
self.moduleSizer = wx.BoxSizer(wx.VERTICAL)
self.panel.SetSizer(self.moduleSizer)
self.moduleSizer.Add(self.text_input, flag=wx.ALIGN_CENTER)
self.text_input.Bind(wx.EVT_KEY_DOWN, self.onKeyDown)
self.Bind(wx.EVT_CLOSE, self.onExit)
self.moduleSizer.Fit(self)
self.text_input.SetFocus()
self.hookman = HookMan(self)
self.hookman.start()
def onKeyDown(self, event):
if event.GetKeyCode() == wx.WXK_ESCAPE:
self.Hide()
event.Skip()
def onExit(self, event):
self.hookman.cancel()
self.hookman.join()
self.Destroy()
class HookMan(pyxhook.HookManager):
def __init__(self,parent,master=None):
pyxhook.HookManager.__init__(self,master)
self.frame = parent
self.KeyDown = self.key_down
def key_down(self,event):
if event.Key == 'Control_R':
self.frame.Show()
def close(self):
self.close()
if __name__ == '__main__':
app = wx.App()
frame = Frame(None)
frame.Show()
app.MainLoop()
Комментарии:
1. Мой плохой .. после того, как я повозился с некоторыми настройками, я понял, что речь идет о моей среде рабочего стола. Я использую KDE Plasma 5.18, и есть опция предотвращения кражи фокуса. Программа работает нормально, когда я отключаю предотвращение кражи фокуса. Спасибо…
2. @RunningRay Нет проблем, обратите внимание на мое изменение в коде pyxhook, которое правильно закрывает поток и позволяет вашему коду завершаться, а не зависать.