Tkinter拖放鼠标指针问题
Tkinter Drag & Drop Mouse Pointer Problem
我正在开发一款扫雷游戏,想制作一个自定义标题栏。到目前为止一切正常,但我在拖放机制上遇到了一些奇怪的错误。
def drag_app(event):
x = event.x + root.winfo_x()
y = event.y + root.winfo_y()
root.geometry(f"+{x}+{y}")
test.bind("<B1-Motion>", drag_app)
到目前为止,这是我的代码。
出于某种原因,当我开始拖动时,鼠标会跳到单击的小部件的 top-left 部分(在本例中为“test”,它只是一个标签)。
我正在使用网格来管理程序
提前致谢
编辑(最小的、可重现的例子):
from tkinter import *
root = Tk()
root.title("Mineswepper")
root.overrideredirect(True)
root.resizable(False, False)
mainframe = Frame(root, bg="#41a2cd")
mainframe.grid(column=0, row=0, sticky=(N, W, E, S))
root.columnconfigure(0, weight=1)
root.rowconfigure(0, weight=1)
title_bar = Frame(mainframe, bg="#41a2cd", relief="raised")
title_bar.grid(row=0, column=0)
test = Label(title_bar, text="titlebar")
test.grid(row=0, column=0)
example_button = Button(mainframe, text="minesweeper", font=("helvetica", 20))
example_button.grid(row=1, column=0)
def drag_app(event):
x = event.x + root.winfo_x()
y = event.y + root.winfo_y()
root.geometry(f"+{x}+{y}")
test.bind("<B1-Motion>", drag_app)
root.mainloop()
在此示例中,您可以通过单击标签“标题栏”来拖动 window
您没有提供完整的、可重现的代码。没有它很难提供帮助。假设您正在尝试使用自定义标题栏拖动 window。
解决方案
- 记录鼠标在小部件上的确切位置
- 将window的几何设置为鼠标位置+起始位置
示例
import tkinter as tk
class Window(tk.Tk):
def __init__(self, master=None, *args ,**kwargs):
super().__init__(master, *args, **kwargs)
self.overrideredirect(True)
self.geometry('400x100+200+200')
title_bar = tk.Frame(self, bg='grey')
title_bar.pack(fill=tk.X, side=tk.TOP)
close_button = tk.Button(title_bar, text='⤬', bg='darkgrey')
close_button.config(command=self.destroy, relief=tk.FLAT)
close_button.pack(side=tk.RIGHT)
title_bar.bind('<B1-Motion>', self.move_window)
title_bar.bind('<Button-1>', self.get_pos)
def get_pos(self, event):
self.ywin = self.winfo_x() - event.x_root
self.xwin = self.winfo_y() - event.y_root
def move_window(self, event):
self.geometry("+{0}+{1}".format(event.x_root + self.xwin, event.y_root + self.ywin))
root = Window()
root.mainloop()
完整代码
# try not to import globally
import tkinter as tk
root = tk.Tk()
root.title("Mineswepper")
root.overrideredirect(True)
root.resizable(False, False)
mainframe = tk.Frame(root, bg="#41a2cd")
mainframe.grid(column=0, row=0, sticky=(tk.N, tk.W, tk.E, tk.S))
root.columnconfigure(0, weight=1)
root.rowconfigure(0, weight=1)
title_bar = tk.Frame(mainframe, bg="#41a2cd", relief="raised")
title_bar.grid(row=0, column=0)
test = tk.Label(title_bar, text="titlebar")
test.grid(row=0, column=0)
example_button = tk.Button(mainframe, text="minesweeper", font=("helvetica", 20))
example_button.grid(row=1, column=0)
xwin = 0
ywin = 0
def refresh_pos(event):
global xwin, ywin
xwin = root.winfo_x() - event.x_root
ywin = root.winfo_y() - event.y_root
def drag_app(event):
root.geometry("+{0}+{1}".format(event.x_root + xwin, event.y_root + ywin))
test.bind('<Button-1>', refresh_pos)
test.bind("<B1-Motion>", drag_app)
root.mainloop()
我正在开发一款扫雷游戏,想制作一个自定义标题栏。到目前为止一切正常,但我在拖放机制上遇到了一些奇怪的错误。
def drag_app(event):
x = event.x + root.winfo_x()
y = event.y + root.winfo_y()
root.geometry(f"+{x}+{y}")
test.bind("<B1-Motion>", drag_app)
到目前为止,这是我的代码。 出于某种原因,当我开始拖动时,鼠标会跳到单击的小部件的 top-left 部分(在本例中为“test”,它只是一个标签)。
我正在使用网格来管理程序
提前致谢
编辑(最小的、可重现的例子):
from tkinter import *
root = Tk()
root.title("Mineswepper")
root.overrideredirect(True)
root.resizable(False, False)
mainframe = Frame(root, bg="#41a2cd")
mainframe.grid(column=0, row=0, sticky=(N, W, E, S))
root.columnconfigure(0, weight=1)
root.rowconfigure(0, weight=1)
title_bar = Frame(mainframe, bg="#41a2cd", relief="raised")
title_bar.grid(row=0, column=0)
test = Label(title_bar, text="titlebar")
test.grid(row=0, column=0)
example_button = Button(mainframe, text="minesweeper", font=("helvetica", 20))
example_button.grid(row=1, column=0)
def drag_app(event):
x = event.x + root.winfo_x()
y = event.y + root.winfo_y()
root.geometry(f"+{x}+{y}")
test.bind("<B1-Motion>", drag_app)
root.mainloop()
在此示例中,您可以通过单击标签“标题栏”来拖动 window
您没有提供完整的、可重现的代码。没有它很难提供帮助。假设您正在尝试使用自定义标题栏拖动 window。
解决方案
- 记录鼠标在小部件上的确切位置
- 将window的几何设置为鼠标位置+起始位置
示例
import tkinter as tk
class Window(tk.Tk):
def __init__(self, master=None, *args ,**kwargs):
super().__init__(master, *args, **kwargs)
self.overrideredirect(True)
self.geometry('400x100+200+200')
title_bar = tk.Frame(self, bg='grey')
title_bar.pack(fill=tk.X, side=tk.TOP)
close_button = tk.Button(title_bar, text='⤬', bg='darkgrey')
close_button.config(command=self.destroy, relief=tk.FLAT)
close_button.pack(side=tk.RIGHT)
title_bar.bind('<B1-Motion>', self.move_window)
title_bar.bind('<Button-1>', self.get_pos)
def get_pos(self, event):
self.ywin = self.winfo_x() - event.x_root
self.xwin = self.winfo_y() - event.y_root
def move_window(self, event):
self.geometry("+{0}+{1}".format(event.x_root + self.xwin, event.y_root + self.ywin))
root = Window()
root.mainloop()
完整代码
# try not to import globally
import tkinter as tk
root = tk.Tk()
root.title("Mineswepper")
root.overrideredirect(True)
root.resizable(False, False)
mainframe = tk.Frame(root, bg="#41a2cd")
mainframe.grid(column=0, row=0, sticky=(tk.N, tk.W, tk.E, tk.S))
root.columnconfigure(0, weight=1)
root.rowconfigure(0, weight=1)
title_bar = tk.Frame(mainframe, bg="#41a2cd", relief="raised")
title_bar.grid(row=0, column=0)
test = tk.Label(title_bar, text="titlebar")
test.grid(row=0, column=0)
example_button = tk.Button(mainframe, text="minesweeper", font=("helvetica", 20))
example_button.grid(row=1, column=0)
xwin = 0
ywin = 0
def refresh_pos(event):
global xwin, ywin
xwin = root.winfo_x() - event.x_root
ywin = root.winfo_y() - event.y_root
def drag_app(event):
root.geometry("+{0}+{1}".format(event.x_root + xwin, event.y_root + ywin))
test.bind('<Button-1>', refresh_pos)
test.bind("<B1-Motion>", drag_app)
root.mainloop()