python - 键模拟器始终在顶部/前景(tkinter)
问题描述
我试图找出我如何总是将窗口放在前台。如果我单击另一个区域,则该窗口处于“非活动状态”并且我无法再访问它(这不是真正的问题)。例如,当我打开浏览器或游戏时,我希望它位于前台,即使我单击其他表面也是如此。“-topmost”已经可用,该窗口只对其他活动消失。
我发布代码是为了更好地概述我的意思(但我自己认为如果有一个小解决方案,就会有一个小解决方案)
from tkinter import *
from tkinter import ttk
class MainWindow(Tk):
def __init__(self):
super(MainWindow, self).__init__()
self.style = ttk.Style()
self.style.theme_use("clam")
self.style.configure("TButton", background="red", borderwidth=0, focuscolor="none")
self.style.configure("TONE.TButton", background="#1e2224", font=("Unispace", 12), borderwidth=1,
foreground="#a1e0ff", bordercolor="lime", darkcolor="lime", lightcolor="lightgreen")
self.bgFrame = []
for x in range(5):
frm = Frame(self, bg="red")
frm.pack(fill="x", ipady=30)
self.bgFrame.append(frm)
Button(self.bgFrame[0], text="\u26cc", bg="red", bd=0, command=self.destroy).pack(side="right", anchor="ne")
self.firstRow = []
x1 = 0
width1 = [80, 80, 80, 80, 80, 80]
for x in range(6):
firstRow = ttk.Button(self.bgFrame[0])
firstRow.place(x=x1, y=0, width=width1[x], height=60)
self.firstRow.append(firstRow)
x1 += 80
self.secondRow = []
x2 = [0, 100, 180, 260, 340, 420, 500]
width2 = [100, 80, 80, 80, 80, 80]
for x in range(6):
secondRow = ttk.Button(self.bgFrame[1])
secondRow.place(x=x2[x], y=0, width=width2[x], height=60)
self.secondRow.append(secondRow)
x3 = [0, 120, 200, 280, 360, 440, 520]
width3 = [120, 80, 80, 80, 80, 80]
self.thirdRow = []
for x in range(6):
thirdRow = ttk.Button(self.bgFrame[2])
thirdRow.place(x=x3[x], y=0, width=width3[x], height=60)
self.thirdRow.append(thirdRow)
self.fourthRow = []
x4 = [0, 100, 180, 260, 340, 420, 500]
width4 = [100, 80, 80, 80, 80, 80]
for x in range(6):
fourthRow = ttk.Button(self.bgFrame[3])
fourthRow.place(x=x4[x], y=0, width=width4[x], height=60)
self.fourthRow.append(fourthRow)
x5 = 0
width5 = [100, 100, 100, 300]
self.fithRow = []
for x in range(4):
fithRow = ttk.Button(self.bgFrame[4])
fithRow.place(x=x5, y=0, width=width5[x], height=60)
self.fithRow.append(fithRow)
x5 += 100
self.bind("<Key>", self.keyBind)
self.bind("<KeyRelease>", self.keyRelease)
def keyBind(self, event):
for i, num in enumerate(range(5), 1):
if event.char == str(i).upper() or event.char == str(i).lower():
self.firstRow[i].config(text=event.char.upper(), style="TONE.TButton")
for i, txt in enumerate(["q", "w", "e", "r", "t"], 1):
if event.char == str(txt).upper() or event.char == str(txt).lower():
self.secondRow[i].config(text=event.char.upper(), style="TONE.TButton")
for i, txt in enumerate(["a", "s", "d", "f", "g"], 1):
if event.char == str(txt).upper() or event.char == str(txt).lower():
self.thirdRow[i].config(text=event.char.upper(), style="TONE.TButton")
for i, txt in enumerate(["<", "y", "x", "c", "v"], 1):
if event.char == str(txt).upper() or event.char == str(txt).lower():
self.fourthRow[i].config(text=event.char.upper(), style="TONE.TButton")
if event.keysym == "Tab":
self.secondRow[0].config(text="\u2B7E", style="TONE.TButton")
if event.keysym == "Shift_L":
self.fourthRow[0].config(text="\u21E7", style="TONE.TButton")
if event.keysym == "Control_L":
self.fithRow[0].config(text="STRG", style="TONE.TButton")
if event.keysym == "Alt_L":
self.fithRow[2].config(text="ALT", style="TONE.TButton")
if event.keysym == "space":
self.fithRow[3].config(text="SPACE", style="TONE.TButton")
def keyRelease(self, event):
for i in range(6):
self.firstRow[i].config(text="", style="TButton")
for i in range(6):
self.secondRow[i].config(text="", style="TButton")
for i in range(6):
self.thirdRow[i].config(text="", style="TButton")
for i in range(6):
self.fourthRow[i].config(text="", style="TButton")
for i in range(4):
self.fithRow[i].config(text="", style="TButton")
if __name__ == '__main__':
mw = MainWindow()
mw.geometry("700x340+0+0")
mw["bg"] = "red"
mw.overrideredirect(1)
mw.wm_transient()
mw.attributes("-transparentcolor", "red")
mw.attributes("-topmost", True)
mw.mainloop()
解决方案
尝试这样的事情:
from tkinter import ttk
import tkinter as tk
import keyboard
class MainWindow(tk.Tk):
# Some constants:
CHARACTERS_ROW_1 = tuple("qwertyuiop")
CHARACTERS_ROW_2 = tuple("asdfghjkl")
CHARACTERS_ROW_3 = tuple("zxcvbnm")
CHARACTERS = (CHARACTERS_ROW_1, CHARACTERS_ROW_2, CHARACTERS_ROW_3)
def __init__(self):
super().__init__()
self.event_queue = []
self.alive = True
self.style = ttk.Style()
self.style.theme_use("clam")
self.style.configure("TButton", background="red", borderwidth=0, focuscolor="none", font=("Unispace", 12))
self.style.configure("TONE.TButton", background="#1e2224", font=("Unispace", 12), borderwidth=1,
foreground="#a1e0ff", bordercolor="lime", darkcolor="lime", lightcolor="lightgreen")
self.buttons = {} # A dictionary of all of the buttons
for row, characters in enumerate(self.CHARACTERS):
for column, character in enumerate(characters):
button = ttk.Button(self, style="TButton")
button.grid(row=row, column=column)
self.buttons.update({character: button})
# Add a global system binding:
keyboard.hook(self.hook)
# Start the loop:
self.handle_events_loop()
# An easy way to escape the program:
super().bind("<Escape>", lambda e: self.destroy())
def destroy(self) -> None:
self.alive = False
super().destroy()
def hook(self, event:keyboard.KeyboardEvent) -> None:
if self.alive:
self.event_queue.append(event)
def handle_events_loop(self) -> None:
if len(self.event_queue) > 0:
# Get the first event:
event = self.event_queue.pop(0)
if event.name not in self.buttons.keys():
return None
if event.event_type == "down":
self.show_key(event.name)
elif event.event_type == "up":
self.hide_key(event.name)
# After 10 ms call `self.handle_events_loop` again
super().after(10, self.handle_events_loop)
def show_key(self, character:str) -> None:
button = self.buttons[character]
button.config(text=character, style="TONE.TButton")
def hide_key(self, character:str) -> None:
button = self.buttons[character]
button.config(text="", style="TButton")
if __name__ == '__main__':
root = MainWindow()
# Removed for debugging
# root.overrideredirect(True)
root.transient()
root.attributes("-topmost", True)
root.attributes("-transparentcolor", "red")
root.config(bg="red")
root.mainloop()
我用keyboard.hook
钩住了所有系统范围的键盘事件。然后我使用带有tkinter
循环的队列来处理事件。
推荐阅读
- android - 将 ByteBuffer 转换为 OpenCV Mat
- html - 在 if 条件 XSLT 中查找特殊节点
- javascript - 使用带有 CSS 过渡的 SVG 图像调整 div 的大小会导致 Firefox 中出现奇怪的交叉线
- c# - 如何在代码中指定 ListView ScrollViewer 而不显示 ListView
- css - 动态显示带有网格的右侧面板
- android - Android Instant 应用导航创建多个最近的任务。为什么?
- java - 为什么我不能在编译时将整数添加到泛型集合中,即使使用引用类型作为数字创建的泛型?
- android - Android 蓝牙 LE SCAN_FAILED_OUT_OF_HARDWARE_RESOURCES
- javascript - javascript es6模块类包含在头中
- javascript - 如何在单击链接时显示多个元素