Уведомления

Группа в Telegram: @pythonsu

#1 Май 2, 2016 04:16:50

vito-Z80
Зарегистрирован: 2015-09-10
Сообщения: 50
Репутация: +  0  -
Профиль   Отправить e-mail  

Передать переменную из функции в функцию одного класса.

Решил попробовать с классами, вроде говорят “компактно”:

class PrintText():
    def __init__(self,canvas=canvas,x=x,y=y,text='',font="Arial 10",outline=bg,fill='yellow'):
        self.x=x
        self.y=y
        self.canvas=canvas
        self.text=text
        self.font=font
        canvas.delete('all')
        canvas.create_text(x,y,text=text,anchor='nw',fill=fill)
        y1=font.split(' ')
        y1=int(y1[1])+(int(y1[1])/2)+y
        x1=width-(x*2)
        canvas.create_rectangle(x,y,x1,y1,outline=outline)
        outline1=outline
        global x1,y1,outline1
    def activateOutLine(event):
        xCoord=canvas.canvasx(event.x)
        yCoord=canvas.canvasx(event.y)
        outline=outline1
        if x < xCoord < x1 and y < yCoord < y1:
            outline=activeOutLine
        canvas.create_rectangle(x,y,x1,y1,outline=outline)
text='some text'
PrintText(text=text)
bodyOne.bind('<Motion>', PrintText.activateOutLine)
Пишут что не желательно объявлять переменные из функций глобальными.
global x1,y1,outline1 нужны в функции событии activateOutLine
x1,y1 - будут меняться в процессе…

Вообщем делал я то что ниже, но сам уже начал запутываться в том что делаю и решил в классы… в которых до сих пор туплю.
import call
import configurations
from tkinter import *
root = Tk()
width=1024
height=768
x=root.winfo_screenwidth()/2-(width/2)
y=root.winfo_screenheight()/2-(height/2)
root.wm_geometry("+%d+%d" % (x, y))
root.geometry("1024x768")
root.title('Стальной канат')
colorBg='red'
colorText='#07485b'
colorActiveText='#0d6986'
colorActiveOutLine='#0d6986'
x=10
y=10
widthMenu=int(width*0.20)    # ширина Главного Меню (слева)
widthMenuBorder=widthMenu-(x*2)
widthDb=int(width*0.35)
widthDbSelect=int(width*0.44)
print(widthDb)
heightCanvass=height-100-6
bodyTop = Canvas(root, width=1020, height=98,bg=colorBg, cursor="hand2")
bodyMenu = Canvas(root, width=widthMenu, height=heightCanvass,bg=colorBg, cursor="hand2")
bodyDb = Canvas(root, width=widthDb, height=heightCanvass,bg=colorBg, cursor="hand2")
bodyDbSelect = Canvas(root, width=widthDbSelect, height=heightCanvass,bg=colorBg, cursor="hand2")
img = PhotoImage(file="img/logo.gif")
bodyTop.create_image(8,10, image=img, anchor='nw') # координаты x, y
coordsDb=[]
coordsMenu=[]
fontMenu=configurations.fontMenu
fontSubMenu=configurations.fontSubMenu
fontDb=configurations.fontDb
fileMenu=call.callMenu()
fileDb=call.callDb()
fileArhive=call.callArhive
def coordsForCanvss(xx=0,yy=0,body=bodyDb,fileName=0,coords=FALSE,font='Arial '+str(10),
                    setCoords=FALSE,active=FALSE,fill=colorBg,activeBorder=colorBg):
    body.delete('all')              #   очистка холста
    nextY=font.split(' ')           #   берем из font цифровое значение 'Arial N'
    nextY=int(nextY[1])*2           #   для "резинового" просчета следующей строки
    fileName=fileName.readlines()   #   содержимое файла заданного в fileName
    print('RRRRRRRR ',fileName)
    for i in fileName:
        if setCoords != False:      #   если перепечатывать строки то не создавать новые координаты
            a=[xx,yy]
            coords.append(a)        #   создаем новые координаты в список
        xRazbor=0                   #   параметр прибавления к Х
        one=i.split('*')
        if body == bodyMenu:        #   если печатаем меню, то только первое слово (второе идет на имя файла)
            one=one[:1]             #   вытаскиваем первое слово
        for getRazbor in one:       #   печатаем содержимое ONE от одног до нескольких слов
            if active==[xx,yy]:     #   цвета текста при фокусе мышью
                fill=colorActiveText
                if activeBorder==1: #   цвет бордюра при фокусе мышью. НОЛЬ = цвет фона холста
                                    #   1 = colorActiveOutLine
                    activeBorder=colorActiveOutLine
                bodyMenu.create_rectangle(xx,yy,xx+widthMenuBorder,yy+nextY,
                                      fill=colorBg,outline=activeBorder)
            else:
                fill=colorText
            body.create_text(xx+xRazbor+x+(x/2),yy,text=getRazbor,font=font,anchor='nw',
                             fill=fill)
            xRazbor+=60             #   + N пикселей к следующему слову
        yy+=nextY                   #   + Y для следующей строки
coordsForCanvss(xx=x,yy=y,body=bodyMenu,fileName=fileMenu,coords=coordsMenu,font='Arial '+str(fontMenu),setCoords=True)
coordsForCanvss(xx=x,yy=y,body=bodyDb,fileName=fileDb,coords=coordsDb,setCoords=True)
print(coordsMenu)
def menuSelect(event):
    import call
    def menuPressed(event):
        getNewFile=enterMenu.split('*')
        getNewFile=str(getNewFile[1])
        getNewFile=getNewFile.split('\n')
        fileName=getNewFile[0]
        fileName=open(fileName,'r')
        print(fileName)
        if enterMenu == True:
            coordsForCanvss(xx=x,yy=y,body=bodyDb,fileName=fileName,coords=coordsDb,
                            font='Arial '+str(fontDb))
    bodyMenu.delete('all')
    xCoord=bodyDb.canvasx(event.x)
    yCoord=bodyDb.canvasx(event.y)
    getFile=call.callMenu()
    enterMenu=''
    coordsForCanvss(xx=x,yy=y,body=bodyMenu,fileName=call.callMenu(),coords=coordsMenu,
                        font='Arial '+str(fontMenu),fill=colorText)
    for i in coordsMenu:
        printString=getFile.readline()
        if i[0] < xCoord < i[0]+widthDb and i[1] < yCoord < i[1]+fontMenu+8:
            enterMenu=printString
            print('sdfsdfsd',enterMenu)
            coordsForCanvss(xx=x,yy=y,body=bodyMenu,fileName=call.callMenu(),coords=coordsMenu,
                            font='Arial '+str(fontMenu),active=i,fill=colorText,activeBorder=1)
    bodyMenu.bind('<Button-1>', menuPressed)
bodyMenu.bind('<Motion>',menuSelect)
bodyTop.grid(row=0,column=0,columnspan=3,sticky='nw')
bodyMenu.grid(row=1,column=0,sticky='nw')
bodyDb.grid(row=1,column=1,sticky='nw')
bodyDbSelect.grid(row=1,column=2,sticky='nw')
mainloop()

Я уже подумываю заплатить кому нибудь, что бы разжевали мне КЛАССЫ по скайпу, нормальным языком…

Глянул тут, оказывается self делает переменную глобальную по всему классу, которую можно использовать в любой функции класса, когда читал Лутца до меня это не дошло.
Но я не могу сделать так в событии
def activateOutLine(self,event=NONE):
        self.event=event
        xCoord=canvas.canvasx(event.x)
        yCoord=canvas.canvasx(event.y)
        outline=self.outline
        if x < self.xCoord < self.x1 and y < self.yCoord < self.y1:
            outline=activeOutLine
        canvas.create_rectangle(x,y,self.x1,self.y1,outline=outline)
Как быть?

Отредактировано vito-Z80 (Май 2, 2016 05:03:33)

Офлайн

#2 Май 2, 2016 08:12:57

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 10010
Репутация: +  857  -
Профиль   Отправить e-mail  

Передать переменную из функции в функцию одного класса.

vito-Z80
Глянул тут, оказывается self делает переменную глобальную по всему классу, которую можно использовать в любой функции класса, когда читал Лутца до меня это не дошло.
Классы лучше изучать отдельно.
wiki. класс
wiki. подкласс



Отредактировано py.user.next (Май 2, 2016 08:15:28)

Офлайн

#3 Май 2, 2016 09:28:41

vito-Z80
Зарегистрирован: 2015-09-10
Сообщения: 50
Репутация: +  0  -
Профиль   Отправить e-mail  

Передать переменную из функции в функцию одного класса.

py.user.next
Спасибо - загляну, но читать и смотреть видосы это одно ((( книга мне не ответит на мои вопросы где я не до понял… а не до понял я походу везде…

А не подскажите как быть с обработчиком событий ? можно передать только 1 аргумент, а хотелось бы больше, или это как то можно обрулить?

Отредактировано vito-Z80 (Май 2, 2016 09:31:04)

Офлайн

#4 Май 2, 2016 10:46:59

4kpt_IV
Зарегистрирован: 2016-01-08
Сообщения: 999
Репутация: +  49  -
Профиль   Отправить e-mail  

Передать переменную из функции в функцию одного класса.

vito-Z80

Можно и больше, но зачастую не нужно В event очень много информации. Посмотрите в документации.

Передать больше

ops = 100
but.bind("<Button-1>", lambda event: my_caller(event, ops))

Офлайн

#5 Май 2, 2016 21:32:54

vito-Z80
Зарегистрирован: 2015-09-10
Сообщения: 50
Репутация: +  0  -
Профиль   Отправить e-mail  

Передать переменную из функции в функцию одного класса.

короче не догоняю я зачем эти классы если все тоже самое делается функциями…

Офлайн

#6 Май 2, 2016 22:14:18

4kpt_IV
Зарегистрирован: 2016-01-08
Сообщения: 999
Репутация: +  49  -
Профиль   Отправить e-mail  

Передать переменную из функции в функцию одного класса.

Наследование, инкапсуляция, полиморфизм.

Или пример “ближе к телу”. Хочу сделать виджет, который автоматом бы строил каскад кнопок 4х4. Причем чтобы его можно было встраивать именно как обычный виджет типа рамки или кнопки…

Отредактировано 4kpt_IV (Май 2, 2016 22:15:40)

Офлайн

#7 Май 3, 2016 03:30:31

vito-Z80
Зарегистрирован: 2015-09-10
Сообщения: 50
Репутация: +  0  -
Профиль   Отправить e-mail  

Передать переменную из функции в функцию одного класса.

4kpt_IV
Наследование, инкапсуляция, полиморфизм.Или пример “ближе к телу”. Хочу сделать виджет, который автоматом бы строил каскад кнопок 4х4. Причем чтобы его можно было встраивать именно как обычный виджет типа рамки или кнопки…

если я тебя правильно понял:
from tkinter import *
root=Tk()
#root.resizable(0,0)
body = Canvas(root, width=600, height=600,bg='#a0a0a0')
buttonText={('But1')}
text=['Button1','Button2','Button3','Button4',
      'Button5','Button6','Button7','Button8',
      'Button9','Button10','Button11','Button12',
      'Button13','Button14','Button15','Button16']
def bName(event):
    print(event.widget)
def kaskad(x=0,y=0,rowB=0,columnB=0,text='',width=10,height=1,font='Arial 12',outline='#000000'):
    count=0
    y1=y
    actualRowB=rowB
    for actualColumn in range(columnB):
        x1=x
        actualRow=text[count:actualRowB]
        for numberInRow in actualRow:
            b=Button(root,text=numberInRow,anchor='nw',width=width,height=height,font=font)
            bWidth=Button.winfo_reqwidth(b)
            body.create_window((x1, y1), anchor="nw", window=b)
            x1=x1+bWidth
        actualRowB+=rowB
        bHeight=Button.winfo_reqheight(b)
        count+=rowB
        y1+=bHeight
    body.create_rectangle(x-1,y-1,x1,y1,outline=outline)
xx=40
yy=40
x=100
y=50
for i in range(4):
    kaskad(text=text,rowB=4,columnB=4,x=x,y=y,font='Arial 8')
    x+=xx
    y+=yy
root.bind('<Button-1>',bName)
body.pack()
mainloop()
Хотя да, доделывать надо что бы можно было выделить или закрыть каждое из 4х4, или даже переместить )

Отредактировано vito-Z80 (Май 3, 2016 04:15:41)

Офлайн

#8 Май 3, 2016 09:16:28

4kpt_IV
Зарегистрирован: 2016-01-08
Сообщения: 999
Репутация: +  49  -
Профиль   Отправить e-mail  

Передать переменную из функции в функцию одного класса.

Нее. Неправильно. Совершенно неправильно.

Я хочу использовать эту сбойку как один виджет. Например:

buttons = MyWidget(root, bg="red")
buttons.pack()

И использовать везде где хочу. Получается автономный блок кода у которого есть методы и атрибуты (ничего не напоминает).

Офлайн

#9 Май 3, 2016 12:12:54

vito-Z80
Зарегистрирован: 2015-09-10
Сообщения: 50
Репутация: +  0  -
Профиль   Отправить e-mail  

Передать переменную из функции в функцию одного класса.

4kpt_IV
Нее. Неправильно. Совершенно неправильно.Я хочу использовать эту сбойку как один виджет. Например:

Прости, но мне ни чего не напоминает))) я только учусь, и еще мало что понимаю.
Я думал что можно этот модуль просто засунуть в tkinter и импортировать как и другие (ну цикл можно внутри задать + все переменные не обязательные.

Если бы соображал в классах может и получилось бы что.))

Но пока баловался вот что еще сделал:
from tkinter import *
root=Tk()
body=Canvas(root, width=600, height=600,bg='#a0a0a0',cursor='hand2')
class Move():
    def __init__(self,x=0,y=0,widthX=100,heightY=100,titleWidgetHeight=20):
        self.x=x
        self.y=y
        self.widthX=widthX
        self.heightY=heightY
        self.titleWidgetHeight=titleWidgetHeight
        root.bind('<Motion>',lambda event:Move.go(event,titleWidgetHeight,widthX,heightY))
    def go(event,titleWidgetHeight,widthX,heightY):
        body.delete('all')
        getX=event.x
        getY=event.y
        body.create_rectangle(x,y,x+widthX,y+heightY,fill='#ffffff',outline='blue')
        body.create_text(x,y,text='Hello',fill='#8a02f3', anchor='nw')
        body.create_rectangle(x,y,x+widthX,y+titleWidgetHeight,outline='blue')
        if x < getX < x+widthX  and y < getY < y+titleWidgetHeight:
            print('getY',getY)
            body.create_rectangle(x,y,x+widthX,y+titleWidgetHeight,outline='green')
            root.bind('<B1-Motion>',lambda event:PushMove.go(event,oldX=getX,
                oldY=getY,titleWidgetHeight=titleWidgetHeight,widthX=widthX,heightY=heightY))
class PushMove(Move):
    def go(event,oldX,oldY,titleWidgetHeight,widthX,heightY):
        getX=event.x
        getY=event.y
        print(x)
        print('getY=',getY,'oldy=',oldY)
        print('+',x+(getX-(oldX-x)),',',getX-(oldX-x))
        if getX-(oldX-x) < getX < getX-(oldX-x)+widthX  and getY-(oldY-y) < getY < getY-(oldY-y)+titleWidgetHeight:
            body.delete('all')
            body.create_rectangle(getX-(oldX-x),getY-(oldY-y),
                                  getX+(widthX-(oldX-x)),getY+heightY-(oldY-y),fill='#ffffff',outline='blue')
            body.create_rectangle(getX-(oldX-x),getY-(oldY-y),getX+(widthX-(oldX-x)),getY+titleWidgetHeight-(oldY-y),outline='green')
            body.create_text(getX-(oldX-x),getY-(oldY-y),text='Hello',fill='green', anchor='nw')
x=150
y=50
Move(x,y,titleWidgetHeight=15,widthX=150,heightY=300)
dir(Canvas)
body.pack()
mainloop()
Тут уже можно двигать виджет по холсту, и за холстом ))) ограничения не делал. Пробовал влипить туда ту каскадку так же через create_window - но не знаю как чистить create_window, ну то есть canvas.delete('all') его удаляет только с холста - а в памяти оно по всей видимости остается, так как вылетало предупреждение в консоли мол много create_window налепил - тормози. Если виджет уже двигали, то при нажатии в любом месте на холсте - виджет появится там, отпускаем и получаем опять глобальные координаты х,y.
…на самом деле я много тут не понимаю:
1)почему если функция-событие то я не могу использовать self. что бы получать все переменные класса?
2) если в .bind() не использовать lambda то передать переменные в нужную функцию по событию вообще не возможно(точнее не знаю как правильно - не смог вообщем).
3) не смог сделать что бы: при отпускании кнопки мыши виджет принимал текущие координаты (он возвращается на глобальные х,y) пробовал global x но вроде как нельзя употреблять(да и не получилось что-то, какое то дерганье рывками пошло - не стал разбираться уже башка кипит).
4) не знаю как получить id множества фигур на холсте заданных в цикле - для обработчика событий.
5) …и много еще чего.


3) убрал верхний delete('all') - посплю - попробую дальше разобраться)

Отредактировано vito-Z80 (Май 3, 2016 12:26:48)

Офлайн

#10 Май 3, 2016 14:06:26

4kpt_IV
Зарегистрирован: 2016-01-08
Сообщения: 999
Репутация: +  49  -
Профиль   Отправить e-mail  

Передать переменную из функции в функцию одного класса.

Открываем документацию по tkiner и смотрим атрибуты event, которые падают в функцию обработчик…

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version