'''
Python程序,实时显示鼠标位置,左键单击后记录点击位置。
'''
'''
Python程序,实时显示鼠标位置,左键单击后记录点击位置。
'''
import tkinter as tk
from tkinter import ttk, messagebox
import pyautogui
import threading
import time
class MouseTrackerApp:
def init(self, root):
self.root = root
self.root.title("鼠标位置追踪器")
self.root.geometry("400x500+100+100")
变量初始化
self.tracking = True
self.always_on_top = False
self.records = [] # 存储记录的坐标 [(x, y, timestamp), ...]
设置UI
self.setup_ui()
启动鼠标位置更新
self.update_mouse_position()
设置全局快捷键
self.setup_hotkeys()
绑定窗口关闭事件
self.root.protocol("WM_DELETE_WINDOW", self.on_closing)
def setup_ui(self):
"""设置用户界面"""
主框架
main_frame = tk.Frame(self.root, padx=10, pady=10)
main_frame.pack(fill=tk.BOTH, expand=True)
控制面板
control_frame = tk.LabelFrame(main_frame, text="控制面板", padx=10, pady=5)
control_frame.pack(fill=tk.X, pady=(0, 10))
实时位置显示区域
position_frame = tk.LabelFrame(main_frame, text="实时鼠标位置", padx=10, pady=5)
position_frame.pack(fill=tk.X, pady=(0, 10))
self.position_label = tk.Label(position_frame, text="X: --- Y: ---",
font=("Arial", 24, "bold"), fg="blue")
self.position_label.pack(pady=10)
坐标说明
coord_info = tk.Label(position_frame, text="屏幕分辨率: {}x{}".format(
pyautogui.size().width, pyautogui.size().height),
font=("Arial", 9), fg="gray")
coord_info.pack()
按钮框架
button_frame = tk.Frame(control_frame)
button_frame.pack(fill=tk.X, pady=5)
置顶按钮
self.top_btn = tk.Button(button_frame, text="🔝 置顶窗口", command=self.toggle_always_on_top,
bg="#4CAF50", fg="white", font=("Arial", 10, "bold"))
self.top_btn.pack(side=tk.LEFT, padx=5)
清除记录按钮
clear_btn = tk.Button(button_frame, text="🗑 清除记录", command=self.clear_records,
bg="#FF9800", fg="white", font=("Arial", 10, "bold"))
clear_btn.pack(side=tk.LEFT, padx=5)
复制所有按钮
copy_all_btn = tk.Button(button_frame, text="📋 复制所有", command=self.copy_all_records,
bg="#2196F3", fg="white", font=("Arial", 10, "bold"))
copy_all_btn.pack(side=tk.LEFT, padx=5)
说明标签
help_text = """使用说明:
• 鼠标移动时实时显示坐标
• 鼠标左键点击自动记录当前位置
• 点击记录可复制该坐标
• 右键点击记录可删除"""
help_label = tk.Label(control_frame, text=help_text, font=("Arial", 9),
justify=tk.LEFT, fg="gray")
help_label.pack(pady=5)
记录区域
records_frame = tk.LabelFrame(main_frame, text="点击记录", padx=10, pady=5)
records_frame.pack(fill=tk.BOTH, expand=True)
创建Treeview表格
self.create_record_table(records_frame)
状态栏
self.status_bar = tk.Label(self.root, text="就绪 | 鼠标左键点击记录位置",
relief=tk.SUNKEN, anchor=tk.W, font=("Arial", 9))
self.status_bar.pack(side=tk.BOTTOM, fill=tk.X)
def create_record_table(self, parent):
"""创建记录表格"""
创建框架包含表格和滚动条
frame = tk.Frame(parent)
frame.pack(fill=tk.BOTH, expand=True)
创建滚动条
scrollbar = tk.Scrollbar(frame)
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
创建Treeview
self.tree = ttk.Treeview(frame, columns=("序号", "X坐标", "Y坐标", "时间"),
show="headings", yscrollcommand=scrollbar.set)
设置列
self.tree.heading("序号", text="序号")
self.tree.heading("X坐标", text="X坐标")
self.tree.heading("Y坐标", text="Y坐标")
self.tree.heading("时间", text="时间")
self.tree.column("序号", width=50, anchor="center")
self.tree.column("X坐标", width=100, anchor="center")
self.tree.column("Y坐标", width=100, anchor="center")
self.tree.column("时间", width=150, anchor="center")
self.tree.pack(fill=tk.BOTH, expand=True, side=tk.LEFT)
scrollbar.config(command=self.tree.yview)
绑定事件
self.tree.bind("<Button-1>", self.on_tree_click)
self.tree.bind("<Button-3>", self.on_tree_right_click) # 右键删除
self.tree.bind("<Double-Button-1>", self.on_tree_double_click) # 双击复制
def update_mouse_position(self):
"""实时更新鼠标位置"""
if self.tracking:
x, y = pyautogui.position()
self.position_label.config(text=f"X: {x:4d} Y: {y:4d}")
每50毫秒更新一次
self.root.after(50, self.update_mouse_position)
def setup_hotkeys(self):
"""设置全局热键监听"""
创建一个单独的线程来监听鼠标点击
self.listening = True
self.listener_thread = threading.Thread(target=self.mouse_listener, daemon=True)
self.listener_thread.start()
绑定键盘快捷键
self.root.bind('<Control-c>', lambda e: self.copy_selected_record())
self.root.bind('<Control-a>', lambda e: self.copy_all_records())
self.root.bind('<Delete>', lambda e: self.delete_selected_record())
def mouse_listener(self):
"""鼠标点击监听器(独立线程)"""
import pyautogui
from pynput import mouse
def on_click(x, y, button, pressed):
if pressed and button == mouse.Button.left and self.tracking:
在主线程中添加记录
self.root.after(0, self.add_record, x, y)
with mouse.Listener(on_click=on_click) as listener:
listener.join()
def add_record(self, x, y):
"""添加记录"""
import time
timestamp = time.strftime("%H:%M:%S")
record_id = len(self.records) + 1
record = {
'id': record_id,
'x': x,
'y': y,
'time': timestamp,
'display_str': f"{record_id}. ({x}, {y}) - {timestamp}"
}
self.records.append(record)
添加到表格
self.tree.insert("", "end", values=(record_id, x, y, timestamp))
自动滚动到底部
self.tree.yview_moveto(1.0)
更新状态栏
self.status_bar.config(text=f"已记录坐标: ({x}, {y})")
def clear_records(self):
"""清除所有记录"""
if messagebox.askyesno("确认", "确定要清除所有记录吗?"):
self.records.clear()
for item in self.tree.get_children():
self.tree.delete(item)
self.status_bar.config(text="已清除所有记录")
def copy_coordinate(self, x, y):
"""复制坐标到剪贴板"""
self.root.clipboard_clear()
coord_text = f"({x}, {y})"
self.root.clipboard_append(coord_text)
self.status_bar.config(text=f"已复制: {coord_text}")
def copy_all_records(self):
"""复制所有记录"""
if not self.records:
self.status_bar.config(text="没有记录可复制")
return
格式化为文本
lines = []
for record in self.records:
lines.append(f"{record['id']}. ({record['x']}, {record['y']}) - {record['time']}")
all_text = "\n".join(lines)
self.root.clipboard_clear()
self.root.clipboard_append(all_text)
self.status_bar.config(text=f"已复制 {len(self.records)} 条记录")
def copy_selected_record(self):
"""复制选中的记录"""
selected = self.tree.selection()
if selected:
item = self.tree.item(selected[0])
values = item['values']
if values:
x, y = values[1], values[2]
self.copy_coordinate(x, y)
else:
self.status_bar.config(text="请先选择要复制的记录")
def delete_selected_record(self):
"""删除选中的记录"""
selected = self.tree.selection()
if selected:
找到对应的记录并删除
index = self.tree.index(selected[0])
if 0 <= index < len(self.records):
del self.records[index]
self.tree.delete(selected[0])
重新编号
self.reindex_records()
self.status_bar.config(text="已删除记录")
def reindex_records(self):
"""重新编号记录"""
清空表格
for item in self.tree.get_children():
self.tree.delete(item)
重新添加并编号
for i, record in enumerate(self.records, 1):
record['id'] = i
self.tree.insert("", "end", values=(i, record['x'], record['y'], record['time']))
def on_tree_click(self, event):
"""单击表格项"""
region = self.tree.identify_region(event.x, event.y)
if region == "cell":
row = self.tree.identify_row(event.y)
if row:
self.tree.selection_set(row)
def on_tree_double_click(self, event):
"""双击表格项复制坐标"""
selected = self.tree.selection()
if selected:
item = self.tree.item(selected[0])
values = item['values']
if values:
self.copy_coordinate(values[1], values[2])
def on_tree_right_click(self, event):
"""右键菜单"""
row = self.tree.identify_row(event.y)
if row:
self.tree.selection_set(row)
创建右键菜单
menu = tk.Menu(self.root, tearoff=0)
menu.add_command(label="复制坐标", command=self.copy_selected_record)
menu.add_separator()
menu.add_command(label="删除记录", command=self.delete_selected_record)
menu.post(event.x_root, event.y_root)
def toggle_always_on_top(self):
"""切换窗口置顶"""
self.always_on_top = not self.always_on_top
self.root.attributes('-topmost', self.always_on_top)
if self.always_on_top:
self.top_btn.config(text="📌 已置顶", bg="#FF5722")
self.status_bar.config(text="窗口已置顶")
else:
self.top_btn.config(text="🔝 置顶窗口", bg="#4CAF50")
self.status_bar.config(text="窗口已取消置顶")
def on_closing(self):
"""关闭程序"""
self.tracking = False
self.listening = False
self.root.destroy()
def main():
"""主函数"""
检查依赖
try:
import pyautogui
from pynput import mouse
except ImportError as e:
print(f"缺少必要的库: {e}")
print("请运行以下命令安装依赖:")
print("pip install pyautogui pynput")
return
root = tk.Tk()
app = MouseTrackerApp(root)
显示启动提示
print("鼠标位置追踪器已启动")
print("功能: 实时显示鼠标坐标 | 鼠标左键自动记录 | 点击记录复制坐标")
root.mainloop()
if name == "main":
main()