#python #tkinter
Вопрос:
Я пытаюсь понять, почему у меня всегда окно на переднем плане. Если я нажму на другую область, окно станет «неактивным», и я больше не смогу получить к нему доступ (что не является реальной проблемой). Например, когда я открываю браузер или игру, я хочу, чтобы это было на переднем плане, даже когда я нажимаю на другие поверхности. «- самый верхний» уже доступен, окно исчезает только для других действий.
я публикую код для лучшего обзора того, что я имею в виду (но я сам предполагаю, что будет небольшое решение, если оно есть).
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()
Комментарии:
1. В этом случае вам, возможно, придется воспользоваться
keyboard
библиотекой.2. библиотека клавиатур? извините за этот вопрос,но я не знаю, что именно вы имеете в виду
3. Прямо сейчас вы хотите иметь возможность обнаруживать нажатия клавиш, даже если
tkinter
окно не в фокусе, верно? Я не думаю, что вы можете это сделать,tkinter
поэтому вам нужно будет использовать такую библиотеку, какkeyboard
.4. да, это то, чего я хочу. хорошо, тогда спасибо за ссылку, никогда об этом не слышал.
5. Я работал над проектом, похожим на инструмент для обрезки экрана, который использует то же
keyboard
самое для захвата нажатий клавиш и создания горячих клавиш
Ответ №1:
Попробуйте что-нибудь вроде этого:
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
циклом для обработки событий.
Комментарии:
1. хм, я не знаю почему, но процесс заканчивается, не сделав ничего раньше. Я установил
keyboard
2. @JoeMo Это работает на меня. Я запустил его с помощью
cmd
Windows 10.3. я также использую Windows 10. Я не понимаю, я тоже пробовал, но что-то идет не так.
cmd
но я знаю, что ты хорошо работаешь, и это будет хорошо работать. я пытаюсь это понять.4. @JoeMo Я все еще хочу разобраться в проблеме :D. Дает ли это вам ошибку? У вас есть
root.mainloop()
в конце кода?5. нет, я нажимаю в pycharm при запуске (или пытаюсь начать с cmd), и я получаю это =
Process finished with exit code 0
(и да, я нажал на основной файл, в котором я хочу запустить этот xD)