所以我有一个简单的程序,当您单击网格中的按钮时,它将填充一种颜色。我希望能够拖动按钮并填充它们,而不像现在您必须单击每个按钮。这可以吗?
这是我的代码,可能不是最好的:
from tkinter import *
root=Tk()
grid= Frame(root)
grid.pack()
img0=PhotoImage(file="0.png")
img1=PhotoImage(file="1.png")
img2=PhotoImage(file="2.png")
fill = 1
class button:
def __init__(self, x, y):
self.type=0
self.but=Button(grid,command=self.change, image=img0, borderwidth=0)
self.but.grid(row=y, column=x)
def change(self):
if self.type==fill:
self.but.config(image=img0)
self.type=0
else:
self.but.config(image=eval("img"+str(fill)))
self.type=fill
def create(x,y):
grid_buttons = []
for Y in range(y):
grid_buttons.append([])
for X in range(x):
grid_buttons[Y].append(button(X, Y))
create(15,15)
root.mainloop()
最佳答案
这是一种方法:
from tkinter import *
root=Tk()
grid= Frame(root)
grid.pack()
img0=PhotoImage(file="0.png")
img1=PhotoImage(file="1.png")
img2=PhotoImage(file="2.png")
fill = 1
class button:
def __init__(self, x, y):
self.type=0
self.but=Button(grid,command=self.change, image=img0, borderwidth=0)
self.but.grid(row=y, column=x)
#Changed
self.already_changed = False
def change(self):
if self.type==fill:
self.but.config(image=img0)
self.type=0
else:
self.but.config(image=eval("img"+str(fill))) #I left this in here, but you should NEVER use eval(). It's unsafe.
self.type=fill
#Changed
def mouse_entered(self):
if not self.already_changed:
self.change()
self.already_changed = True
def mouse_up(self):
self.already_changed = False
#Changed
class Container:
def __init__(self, x, y):
grid_buttons = []
for Y in range(y):
grid_buttons.append([])
for X in range(x):
grid_buttons[Y].append(button(X, Y))
self.buttons = grid_buttons
grid.bind_all("<Button-1>", self.mouse_down)
grid.bind_all("<ButtonRelease-1>", self.mouse_up)
grid.bind_all("<B1-Motion>", self.mouse_motion)
self.mouse_pressed = False
def mouse_down(self, e):
self.mouse_pressed = True
def mouse_up(self, e):
self.mouse_pressed = False
for row in self.buttons:
for but in row:
but.mouse_up()
def mouse_motion(self, e):
for row in self.buttons:
for but in row:
if grid.winfo_containing(e.x_root, e.y_root) is but.but:
but.mouse_entered()
container = Container(15,15)
root.mainloop()
现在,我注意到您所做的一些事情不太符合 Python 风格。因此,这里有一个更严格遵循 Python 约定的版本。请注意,这是完全不同的。
from tkinter import *
root = Tk()
images = {0: PhotoImage(file="0.png"),
1: PhotoImage(file="1.png"),
2: PhotoImage(file="2.png")}
fill = 1
class MyButton(Button): #Convention is for class names to start with uppercase letters
def __init__(self, master):
super(MyButton, self).__init__(master, image = images[0], borderwidth = 0)
self.type = 0
self.already_changed = False
def change(self):
if self.type == fill:
self.type = 0
else:
self.type = fill
self.config(image=images[self.type])
def mouse_entered(self):
if not self.already_changed:
self.change()
self.already_changed = True
def mouse_up(self):
self.already_changed = False
class Container(Frame):
def __init__(self, master, width, height):
super(Container, self).__init__(master)
buttons = []
for y in range(height):
buttons.append([])
for x in range(width):
button = MyButton(self)
button.grid(row = x, column = y)
buttons[y].append(button)
self.buttons = buttons
self.bind_all("<Button-1>", self.mouse_down)
self.bind_all("<ButtonRelease-1>", self.mouse_up)
self.bind_all("<B1-Motion>", self.mouse_motion)
self.mouse_pressed = False
def mouse_down(self, e):
self.update_containing_button(e)
self.mouse_pressed = True
def mouse_up(self, e):
self.mouse_pressed = False
for row in self.buttons:
for button in row:
button.mouse_up()
def mouse_motion(self, e):
self.update_containing_button(e)
def update_containing_button(self, e):
for row in self.buttons:
for button in row:
if self.winfo_containing(e.x_root, e.y_root) is button:
button.mouse_entered()
grid = Container(root, 15, 15)
grid.pack()
root.mainloop()
为什么要同时发布这两个内容?因为看起来您在实际应用程序中有更多代码(这很好,这是一个最小的示例)。我不想强制您重写我的代码以使其与您的其余代码兼容,反之亦然。
两个版本之间的功能差异:
第二个版本已进行修改,因此它使用面向对象的功能而不是全局变量,使其更加灵活且更易于更改。
第二个版本删除了按钮本身的绑定(bind),而是让容器处理所有内容。
关于python - tkinter,如何跨按钮拖动?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46865046/