Tkinter: установить цвет для точек, выбранных пользователем - PullRequest
0 голосов
/ 08 ноября 2018

У меня есть изображение, сохраненное как image.png. Рабочий процесс моей задачи таков:

  1. Загрузка изображения в Tkinter вместе с кнопкой «выбрать две точки» под изображением
  2. Пользователь дважды щелкает мышью по двум точкам изображения
  3. Когда он выбирает первую точку, эта конкретная точка выделяется (скажем, красным или любым другим цветом); затем он выбирает вторую точку, а также эта вторая точка выделяется
  4. Координаты (x, y) двух точек сохраняются в глобальных переменных и будут использоваться позже
  5. Как только пользователь выбрал две точки, появляется вторая «Готово!» кнопка появляется. Когда эта кнопка нажата, графический интерфейс закрывается. Н.Б. Мне бы хотелось, чтобы две точки оставались выделенными, пока пользователь не нажмет кнопку закрытия, чтобы у него было представление о том, где он / она нажал

Мне удалось решить все шаги, кроме шаг 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 голосов
/ 09 ноября 2018
  1. Когда он выбирает первую точку, эта конкретная точка выделяется (скажем, красным или любым другим цветом); затем он выбирает вторую точку, а также эта вторая точка выделяется

Мне удалось решить все шаги, кроме шага 3

Класс PhotoImage имеет методы для установки цвета пикселя. Например, чтобы установить пиксель в точке x / y события на красный, сделайте следующее:

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

Так как один пиксель действительно трудно увидеть, вы можете довольно легко нарисовать маленький прямоугольник 3x3 с центром вокруг точки. В следующем примере красный цвет пикселей отображается в квадрате от event.x-1, event.y-1 до event.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, которые определяют прямоугольную область.

0 голосов
/ 08 ноября 2018

Если вы не хотите делать больше, чтобы установить несколько пикселей, вам, вероятно, будет проще использовать виджет Canvas, который имеет некоторые высокоуровневые примитивы рисования (например, для прямоугольников и овалов).

(Вот довольно обширная документация Tkinter о Canvas виджетах.)

Ниже приведен ваш код с изменениями для этого (плюс несколько других, чтобы сделать его более читабельным, следуя рекомендациям PEP 8 - Руководство по стилю для кода Python и с удалением некоторых вещей, которые я считал ненужный и / или слишком избыточный).

Он определяет новую вспомогательную функцию с именем create_circle(), чтобы упростить вызов более общего метода Canvas widget 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...