Tkinter:为用户选择的点设置颜色

时间:2018-11-08 16:17:58

标签: python tkinter

我有一个另存为image.png的图像。我任务的工作流程是这样的:

  1. 在Tkinter中加载图像以及图像下方的“选择两个点”按钮
  2. 用户在图像的两个点上用鼠标左键单击两次
  3. 当他选择第一个点时,该特定点会突出显示(例如用红色或任何一种颜色显示);然后他选择第二点,第二点也被突出显示
  4. 两点的(x,y)坐标存储在全局变量中,以后将使用
  5. 一旦用户选择了两个点,第二个“完成!”按钮出现。单击此按钮后,GUI关闭。 N.B我希望在用户单击关闭按钮之前,这两点一直保持突出显示,以便他能知道他/她单击的位置

我设法解决了所有步骤,但第3步除外。我发现的最相似的东西是用canvas.create_rectangle(x,y,x+1,y+1,fill="red")创建一个矩形,但是首先我希望使用一个圆形,其次我无法将canvas链接到我的Label

任何帮助将不胜感激:D

到目前为止,这是我的代码:

root = Tk()  # create a window

frame = Frame(root)  # define upper frame
middleframe = Frame(root)  # define middle frame
exitFrame = Frame(root)  # define exit frame
frame.pack()  # pack the frame
middleframe.pack()  # pack the subframe
exitFrame.pack(side = 'bottom')  # pack the exit frame

# function that closes the GUI
def close_window(): 
    root.destroy()

# load the image
img = PhotoImage(file="image.png")  # save the image
panel = Label(frame, image=img)  # display the image as a label
panel.grid(row=0, column=0)  # pack the image

# make the user select some points
global x_Coordinates  # initialize empty list for storing x-axis coordinates
global y_Coordinates  # initialize empty list for storing y-axis coordinates
x_Coordinates = []
y_Coordinates = []

clicks = 0
def countClicks():
  global clicks # this will use the variable to count
  clicks = clicks + 1  # increment "clicks"
  if clicks == 2: # if the user has selected 2 points, add a button that closes the window
      exit_button = Button(exitFrame, state = "normal", text = "Done!", command = close_window)  # link the closing function to the button
      exit_button.grid(row=2, column=0, pady=5)  # set button position with "grid"        
pass

def selectPoints():  # function called when user clicks the button "select two points"
    panel.bind("<Button 1>", saveCoordinates)  #  link the function to the left-mouse-click event
    exit_button = Button (exitFrame, state = "disabled", text = "Done!", command = close_window)  # link closing function to the button
    exit_button.grid(row=2, column=0, pady=5)  # set button position with "grid"
    button_select_points.config(state = "disabled") # switch button state to "disabled"

def saveCoordinates(event): # function called when left-mouse-button is clicked   
    x_coordinate = event.x  # save x and y coordinates selected by the user
    y_coordinate = event.y
    x_Coordinates.append(x_coordinate)  # append to external list
    y_Coordinates.append(y_coordinate)  # append to external list
    countClicks()  # invoke function "countClicks"

button_select_points = Button(middleframe, text = "select two points", command = selectPoints)  # insert button and link it to "selectPoints"
button_select_points.grid(row=1, column=0, pady=5)  # set button position with "grid"

root.mainloop()  # keep the GUI open

2 个答案:

答案 0 :(得分:2)

除非您想做更多的工作来设置几个像素,否则使用Canvas小部件可能会更容易,该小部件具有一些更高级的绘制基元(例如,矩形和椭圆形)。 / p>

(这是有关Canvas小部件的一些相当全面的Tkinter文档。)

下面是对您的代码进行修改的方法(通过遵循PEP 8 - Style Guide for Python Code准则使代码更具可读性,并删除了一些我认为不必要和/或过于多余的内容)。 / p>

它定义了一个名为create_circle()的新辅助函数,以简化对更通用的Canvas小部件的create_oval()方法的调用。现在,在您的saveCoordinates()函数中调用了该函数(现在,该函数已绑定到新"<Button 1>"对象的Canvas事件而不是您使用的Label上)。

from tkinter import *

root = Tk()  # create a window

frame = Frame(root)  # define upper frame
middleframe = Frame(root)  # define middle frame
exitFrame = Frame(root)  # define exit frame
frame.pack()  # pack the frame
middleframe.pack()  # pack the subframe
exitFrame.pack(side='bottom')  # pack the exit frame

# function that closes the GUI
def close_window():
    root.destroy()

img = PhotoImage(file="myimage.png")  # load the image
canvas = Canvas(frame, width=img.width(), height=img.height(), borderwidth=0)
canvas.grid(row=0, column=0)
canvas.create_image(0, 0, image=img, anchor=NW)

# make the user select some points
x_Coordinates = []  # list for storing x-axis coordinates
y_Coordinates = []  # list for storing y-axis coordinates
clicks = 0

def create_circle(canvas, x, y, radius, **kwargs):
    return canvas.create_oval(x-radius, y-radius, x+radius, y+radius, **kwargs)

def countClicks():
    global clicks

    clicks += 1
    # if the user has selected 2 points, add a button that closes the window
    if clicks == 2:
        # link the closing function to the button
        exit_button = Button(exitFrame, state="normal", text="Done!",
                             command=close_window)
        exit_button.grid(row=2, column=0, pady=5)  # set button position with "grid"

def selectPoints():  # function called when user clicks the button "select two points"
    # link the function to the left-mouse-click event
    canvas.bind("<Button 1>", saveCoordinates)
    # link closing function to the button
    exit_button = Button (exitFrame, state="disabled", text="Done!",
                          command=close_window)
    exit_button.grid(row=2, column=0, pady=5)  # set button position with "grid"
    button_select_points.config(state="disabled") # switch button state to "disabled"

def saveCoordinates(event): # function called when left-mouse-button is clicked
    x_coordinate = event.x  # save x and y coordinates selected by the user
    y_coordinate = event.y
    x_Coordinates.append(x_coordinate)
    y_Coordinates.append(y_coordinate)
    # Display a small dot showing position of point.
    create_circle(canvas, x_coordinate, y_coordinate, radius=3, fill='red')
    countClicks()

# insert button and link it to "selectPoints"
button_select_points = Button(middleframe, text="select two points",
                              command=selectPoints)
button_select_points.grid(row=1, column=0, pady=5)

root.mainloop()  # keep the GUI open

答案 1 :(得分:2)

  
      
  1. 当他选择第一个点时,该特定点会突出显示(例如用红色或任何一种颜色显示);然后他选择第二点,第二点也被突出显示
  2.   
     

我设法解决了所有步骤,除了步骤3

PhotoImage类具有用于设置像素颜色的方法。例如,要将事件的x / y处的像素设置为红色,请执行以下操作:

img.put(("red",), to=(event.x, event.y))

由于很难看到单个像素,因此可以相当容易地绘制围绕该点的3x3矩形小像素。以下示例将红色放置在event.x-1, event.y-1event.x+1, event.y+1的正方形像素中:

img.put(("red",), to=(event.x-1, event.y-1, event.x+1, event.y+1))

put方法的第一个参数是颜色列表,这些颜色可以是已知的颜色名称或rgb规范(例如:#ff0000用于红色等)。如果此处的数据不足以填充指定的区域,则将对提供的数据进行平铺。

to参数指定一个x / y坐标或两个x / y坐标,它们定义一个矩形区域。