Найти - Пользователи
Полная версия: вопрос по tkinter
Начало » Python для новичков » вопрос по tkinter
1
Aturo
Доброго времени, форумчане. Написал функцию, которая заполняет холст квадратами, но не пойму как поймать нажатия по ним. Т.е. при щелчке по квадрату он должен поменять цвет.
 from tkinter import *
root = Tk()
root.geometry('500x600')
canv = Canvas(root, width=479, height=479, bg="#111")##padx='15', pady='80')
                  
def s():
    x1=0 
    d=24
    y=0
    y1=24
    for i in range(20):            
        for i in range(20):
            canv.create_rectangle(y,x1,y1,d, fill='#002', outline="#009") 
            x1+=24 
            d+=24
        y+=24
        y1+=24
        x1=0 
        d=24
s()
canv.pack(side='bottom')
root.mainloop()
Пробовал пользоваться биндами, но не особо понял как они работают.
 def lkm(self):
    canv.create_rectangle['black']='fill'
root.bind("<Button-1>", lkm)
Заранее признателен всем кто поможет.
DamMercul
Биндить можно. Только зачем тебе делать квадраты. Юзай Button. У него тоже есть параметры высота-ширина. А биндить если кнопки не надо. Но если так зацепило, то:
 def lkm(event):  # не понимаю зачем тут тебе self.
    if event.keysym == "Enter":
        canv.create_rectangle["black"] = "fill"  # Менять цвет по-другому надо. Ты создаешь новый квадрат, и то не верно
root.bind("<KeyPress>", lkm)

P. S. Бинд в ткинтере работает по принципу Нажал-Сделал. Возможно сделал не по задаче. Если хочешь сделать, чтобы можно было нажать на квадрат, то надо отслеживать координаты мышки на root'е и сравнивать с коорд. квадрата
Aturo
 from tkinter import *
root = Tk()
root.geometry('600x600')
                  
def s():
    x1=0 
    y1=0
    for i in range(20):            
        for i in range(20):
            Button(root, command=click).place(x=x1, y=y1, width=30, height=30) 
            x1+=30
        y1+=30
        x1=0
s()
root.mainloop()
Попробовал сделать с кнопками, но проблема так и осталась, т.к. не знаю что писать в def click(event): чтобы поменять цвет той кнопки на которую нажал. Ищу литературу по данному вопросу, но пока нашёл только как при нажатии создать поверх другую кнопку с нужными мне параметрами.
PEHDOM
Aturo
не знаю что писать в def click(event): чтобы поменять цвет той кнопки на которую нажал
ну дык event он достаточно сложный обьект.
http://effbot.org/tkinterbook/tkinter-events-and-bindings.htm
например event.widget содержит виджет который являеться источнико события.
Aturo
Проблему решил. Оставлю свой говнокод, авось кому тоже зададут в школе/универе.
 from tkinter import *
root = Tk()
root.geometry('500x600')
canv = Canvas(root, width=479, height=479, bg="white")
spis = []
spis2 = []
                  
def s():
    x1=0 
    d=24
    y=0
    y1=24
    for i1 in range(20):            
        for i2 in range(20):
            m = y, x1, y1, d                     
            spis.append(list(m))
            x1+=24 
            d+=24
        y+=24
        y1+=24
        x1=0 
        d=24
s()
def click1(event):
    for i in range(400):
        if ((event.x > spis[i][0]) and (event.x < spis[i][2])) and (
            (event.y > spis[i][1]) and (event.y < spis[i][3])):
            canv.create_rectangle(spis[i][0],spis[i][1],spis[i][2],spis[i][3], 
                                  fill='#009',outline="#009") 
            m = spis[i][0], spis[i][1], spis[i][2], spis[i][3]
            spis2.append(list(m))
def click2(event):
    for i in range(400):
        if ((event.x > spis2[i][0]) and (event.x < spis2[i][2])) and (
            (event.y > spis2[i][1]) and (event.y < spis2[i][3])):
            canv.delete(i+1)
canv.pack(side='bottom')
canv.bind('<Button-1>', click1)
canv.bind('<Button-3>', click2)
root.mainloop()
PEHDOM
честно, за тако код бил бы по рукам, каждый раз раз щелкая по канвасу, вы перебираете все пикселы? + вы еще храните чтото в двух списках. + даже если вы нашли нужный вам прямоугольник вы продолжаете перебирать все пикселы. Вы серьезно?
это задание на 10-15 строк от силы.

 from tkinter import *
root = Tk()
root.geometry('500x600')
canv = Canvas(root, width=479, height=479, bg="white")
rect_size = 25 # размер квадрата
def click1(event):
            x_pos = event.x
            y_pos = event.y
            left = rect_size//2
            right = rect_size - left
            canv.create_rectangle(x_pos - left, y_pos - left, x_pos + right, y_pos + right,
                                  fill='#009',outline="#009")
def click2(event):
            canv.delete(CURRENT)
canv.pack(side='bottom')
canv.bind('<Button-1>', click1)
canv.bind('<Button-3>', click2)
root.mainloop()
Aturo
PEHDOM
Вы серьезно?
Дело в том, что я только начал знакомство с программированием как таковым и пока ещё полный ноль в этом, посему и код такой. Со временем, полагаю, исправлюсь. Крайне признателен за конструктивную критику, вы очень помогаете. (вдвойне благодарен за CURRENT, не знал что так можно, сильно упрощает задачу)
По поводу списков, забыл сразу написать, квадраты должны быть расположены “сеткой”. Т.е. каждый на определённом месте. При вашем варианте написания квадраты могут накладываться друг на друга, поэтому складываю координаты в список (лучше пока не придумал). Собственно задание заключается в написании игры Game of life, но с остальным попробую справиться сам, иначе так ничему и не научусь.
PEHDOM
Aturo
По поводу списков, забыл сразу написать, квадраты должны быть расположены “сеткой”. Т.е. каждый на определённом месте. При вашем варианте написания квадраты могут накладываться друг на друга, поэтому складываю координаты в список (лучше пока не придумал)
это решаеться парой строчек. Исправленый вариант, квадраты размещаються сеткой, также добавлена проверка нет ли там уже кадврата, чтобы оно не рисовало один поверх другого :
 from tkinter import *
root = Tk()
root.geometry('500x600')
canv = Canvas(root, width=479, height=479, bg="white")
rect_size = 24 # размер квадрата
def click1(event):
            if canv.find_withtag(CURRENT): # проверка, есть ли там уже виджет
                return
            x_pos = event.x
            y_pos = event.y
            x1 = x_pos-x_pos%rect_size
            y1 = y_pos-y_pos%rect_size
            canv.create_rectangle(x1, y1, x1 + rect_size, y1 + rect_size,
                                  fill='#009',outline="#009")
def click2(event):
            canv.delete(CURRENT)
canv.pack(side='bottom')
canv.bind('<Button-1>', click1)
canv.bind('<Button-3>', click2)
root.mainloop()
ЗЫ на всякий случай дока по канвасу http://effbot.org/tkinterbook/canvas.htm
Aturo
Как получить теги всех элементов на холсте?
На холсте 400 эл-в с тегами ‘y’ или ‘n’. Пишу
 canv.gettags(all)
и получаю пустой список. Подскажите пожалуйста где ошибся.
Пока сделал так, но хотелось бы попроще и поадекватней.
     z = []
    all1 = canv.find_all()
    for lk in all1:
        z1 = canv.gettags(lk)
        z.append(z1)
PEHDOM
Aturo
На холсте 400 эл-в с тегами ‘y’ или ‘n’. Пишу canv.gettags(all) и получаю пустой список.
gettags не принимает ALL, а itemcget принимает, но вернет результат для первого найденого элемента.И честно говоря не пойму зачем? вы вед и так знаете теги все элементов, это ‘y’ или ‘n’.
Но если так уж нужно, то ваш способ достаточно адекватный, по крайней мере другого я не знаю именно в той постановке задачи. Хотя если вам нужна проверка чтобы например на поле (не)осталось элементов с какимто одним тагом, то есть другие более простые способы.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB