我正在开发一个程序,该程序可以跟踪用户的语言,并根据检测到的语言在光标附近显示相应的标志。该标志仅应在文本光标(工字形)处于活动状态时显示,而不是在显示标准鼠标箭头时显示。
当文本光标再次变为鼠标箭头时,标志停止更新,之后标志不再变化
程序应根据检测到的语言在光标附近显示一个标志。
当光标第二次变为工字形(文本光标)时,标志不再更新
无论是工字形光标还是标准箭头光标,该标志都应该更新并正确显示在光标附近。
import pyautogui
import win32api
import win32con
import win32gui
import ctypes
from PIL import Image, ImageTk
import tkinter as tk
import os
# Configuration
PNG_FLAGS_DIR = r'D:\work\pyProj\Mova\icons'
CURSOR_WIDTH = 20
CURSOR_HEIGHT = 16
current_language = None
# Get system language based on keyboard layout
def get_system_language():
lang_id = ctypes.windll.user32.GetKeyboardLayout(0)
lang_id = lang_id & 0xFFFF
language_map = {
0x0409: 'en',
0x0809: 'uk',
0x0422: 'ukr',
0x0415: 'pl',
}
lang = language_map.get(lang_id, 'en')
global current_language
if current_language != lang:
current_language = lang
return current_language
# Update the flag image on the canvas based on the system language
def update_flag_image():
lang = get_system_language()
file_names = {
'en': 'united-states-flag-icon.webp',
'uk': 'united-kingdom-flag-icon.webp',
'ukr': 'ukraine-flag-icon.webp',
'pl': 'poland-flag-icon.webp',
}
png_file = file_names.get(lang, 'united-states-flag-icon.webp')
flag_path = os.path.join(PNG_FLAGS_DIR, png_file)
if os.path.exists(flag_path):
try:
flag_img = Image.open(flag_path).resize((CURSOR_WIDTH, CURSOR_HEIGHT))
flag_img_tk = ImageTk.PhotoImage(flag_img)
canvas.delete("all") # Clear existing images
canvas.create_image(0, 0, anchor='nw', image=flag_img_tk)
canvas.image = flag_img_tk
except Exception as e:
print(f"Error updating flag: {e}")
else:
print(f"File not found: {flag_path}")
# Check if the cursor is a caret
def is_caret_cursor():
x, y = win32api.GetCursorPos()
hwnd = win32gui.WindowFromPoint((x, y))
cursor_info = win32gui.GetCursorInfo()
cursor_handle = cursor_info[1]
return cursor_handle == win32gui.LoadCursor(None, win32con.IDC_IBEAM)
# Update the flag position and visibility based on the cursor type
def update_position():
x, y = pyautogui.position()
flag_width, flag_height = CURSOR_WIDTH, CURSOR_HEIGHT
if is_caret_cursor():
root.geometry(f'{flag_width}x{flag_height}+{int(x) + 10}+{int(y) + 10}')
if not root.winfo_viewable():
root.deiconify()
update_flag_image() # Update flag when caret is visible
else:
if root.winfo_viewable():
root.withdraw()
update_flag_image() # Update flag even when caret is not visible
root.after(100, update_position)
# Periodically check and update the language flag
def periodic_language_check():
update_flag_image()
root.after(1000, periodic_language_check)
# Tkinter setup
root = tk.Tk()
root.title("Mova")
root.geometry(f"{CURSOR_WIDTH}x{CURSOR_HEIGHT}+0+0")
root.attributes('-topmost', True)
root.attributes('-transparentcolor', 'white')
root.overrideredirect(True)
canvas = tk.Canvas(root, width=CURSOR_WIDTH, height=CURSOR_HEIGHT, bg='white', highlightthickness=0)
canvas.pack()
# Start the main loop
root.withdraw()
update_position() # Update position and visibility
periodic_language_check() # Update flag based on language change
root.mainloop()
当光标在文本和鼠标模式之间切换时,您的代码似乎无法保持标志图像更新。这导致标志意外消失。
为了确保标志仅在可见时更新,我们将修改 update_flag_image 函数以在更新图像之前检查窗口是否显示。这是改进后的代码:
def update_flag_image():
lang = get_system_language()
# ... (rest of your code to get flag path)
if os.path.exists(flag_path) and root.winfo_viewable(): # Only update if window is visible
try:
# ... (rest of your code to update the image on canvas)
except Exception as e:
print(f"Error updating flag: {e}")
else:
print(f"File not found: {flag_path}")
通过添加条件 root.winfo_viewable(),我们确保仅当窗口在屏幕上实际可见时才更新标志图像。这可以防止不必要的更新并确保标志在需要时正确显示。
还有,
您可能会考虑使用更高效的图像格式(例如 PNG)以获得更好的性能。 可以通过使用更具体的异常类型来改进错误处理。 对于更复杂的标志逻辑,请考虑使用专用标志类来管理其状态和行为。
我希望这有帮助!如果您还有其他问题,请告诉我。 HTH