Bottom Page

Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
 Button in one class, methods in another one
#1
Hi, I spent 2 days trying to solve this little exercice, creating a face with button open or closing his mouth.
I do have 2 questions about this code :

  1. I cannot delete the round face to create a closed mouth, line 40 and line 43, python says : AttributeError: 'Button_Can' object has no attribute 'opened_mouth'. How could I make this work ?
  2. How could I avoid to repeat the circle function on line 17 in the Button_Can Class ?

    Thanks for any help that could enlighten my poor coding skills

    from tkinter import *
    
    class Button_Can(Frame):
    	def __init__(self):
    		Frame.__init__(self)
    		self.larg,self.haut=200,200
    		self.can=Canvas(self.master,width=self.larg,height=self.haut,bg='ivory')
    		self.can.pack()
    		self.b1=Button(self.master,text='Open it !',command=self.openit)
    		self.b2=Button(self.master,text='Close it !',command=self.closeit)
    		self.b1.pack(side=RIGHT)
    		self.b2.pack(side=LEFT)
    	def openit(self):
    		Face.openMouth(self)
    	def closeit(self):
    		Face.closeMouth(self)
    	def circle(self,x, y, r, coul ='black'):
    		"Draw a circle center x,y radius r "
    		self.can.create_oval(x-r, y-r, x+r, y+r, outline=coul)
    
    class Face():
    	def __init__(self,can):
    		self.can=can
    		"Draw a face"
    		can.delete(ALL)
    		cc =[[100, 100, 80, 'red'],[70, 70, 15, 'blue'], 
    		[130, 70, 15, 'blue'],[70, 70, 5, 'black'],
    		[130, 70, 5, 'black'],[44, 115, 20, 'red'], 
    		[156, 115, 20, 'red'],[100, 95, 15, 'purple']] 
    		i =0
    		while i < len(cc):
    			el = cc[i] 
    			self.circle(el[0], el[1], el[2], el[3])
    			i += 1 
    
    	def circle(self,x, y, r, coul ='black'):
    		"Draw a circle center x,y radius r "
    		self.can.create_oval(x-r, y-r, x+r, y+r, outline=coul)
    	def openMouth(self):
    		self.can.delete(self.closed_mouth)
    		self.opened_mouth=self.circle(100, 145, 30, 'purple')
    	def closeMouth(self):
    		self.can.delete(self.opened_mouth)
    		self.closed_mouth=self.can.create_line(80,145,120,145,fill='purple')
    
    A=Button_Can()
    B=Face(A.can)
Quote
#2
That is not the best way to interact classes with each other. The best solution would be to make the Face object in the canvas class like this:

from tkinter import *
 
class Button_Can(Frame):
    def __init__(self):
        Frame.__init__(self)
        self.larg,self.haut=200,200
        self.can=Canvas(self.master,width=self.larg,height=self.haut,bg='ivory')
        self.can.pack()
        self.face = Face(self.can)
        self.b1=Button(self.master,text='Open it !',command=self.face.openMouth)
        self.b2=Button(self.master,text='Close it !',command=self.face.closeMouth)
        self.b1.pack(side=RIGHT)
        self.b2.pack(side=LEFT)
 
class Face():
    def __init__(self, can):
        self.can = can
        self.setup()
        
    def setup(self):
        self.can.delete(ALL)
        cc =[[100, 100, 80, 'red'],[70, 70, 15, 'blue'], 
        [130, 70, 15, 'blue'],[70, 70, 5, 'black'],
        [130, 70, 5, 'black'],[44, 115, 20, 'red'], 
        [156, 115, 20, 'red'],[100, 95, 15, 'purple']] 
        i =0
        while i < len(cc):
            el = cc[i] 
            self.circle(el[0], el[1], el[2], el[3])
            i += 1 
            
        self.opened_mouth = None
        self.closed_mouth = None
 
    def circle(self,x, y, r, coul ='black'):
        "Draw a circle center x,y radius r "
        self.can.create_oval(x-r, y-r, x+r, y+r, outline=coul)
    def openMouth(self):
        #self.can.delete(self.closed_mouth)
        self.setup()
        self.opened_mouth=self.circle(100, 145, 30, 'purple')
    def closeMouth(self):
        #self.can.delete(self.opened_mouth)
        self.setup()
        self.closed_mouth=self.can.create_line(80,145,120,145,fill='purple')

root = Tk()
A=Button_Can()
B=Face(A.can)
root.mainloop()
NOTE: I am more use to pygame's redraw everything style... every frame, so i am not sure if tkinter has a method to just delete a portion of the canvas or not. So i just redrew everything.
Quote
#3
Thanks for your very fast reply metulburr,
I am still trying to erase just the mouth. But I don't understand why my erase methode, using what you said above, doesn't work :
When I click the erase button, nothing happens, no error message either.
from tkinter import *

class C1(Frame):
	def __init__(self):
		Frame.__init__(self)
		self.larg,self.haut=100,100
		self.can=Canvas(self.master,width=self.larg,height=self.haut,bg='ivory')
		self.can.pack()
		self.c2=C2(self.can)
		self.b1=Button(self.master,text='Erase',command=self.c2.erase)
		self.b1.pack()
		
	

class C2():
	def __init__(self,can):
		self.can=can	
		self.redline=self.can.create_line(10, 10, 90, 90, fill ='red',width=5)

	def erase(self):
		self.can.delete(self.redline)


root = Tk()
A=C1()
canevas =A.can
B=C2(canevas)
root.mainloop()
Quote
#4
You are creaing two objects with C2 class. One inside C1 on line 9, and another at line 27. Comment out the line 27 one. What is happening is you are creating two lines overlapping each other, where one only has access to delete it.
from tkinter import *
 
class C1(Frame):
    def __init__(self):
        Frame.__init__(self)
        self.larg,self.haut=100,100
        self.can=Canvas(self.master,width=self.larg,height=self.haut,bg='ivory')
        self.can.pack()
        self.c2=C2(self.can)
        self.b1=Button(self.master,text='Erase',command=self.c2.erase)
        self.b1.pack()
         
     
 
class C2():
    def __init__(self,can):
        self.can=can    
        self.redline=self.can.create_line(10, 10, 90, 90, fill ='red',width=5)
 
    def erase(self):
        self.can.delete(self.redline)
 
 
root = Tk()
A=C1()
canevas =A.can
#B=C2(canevas)
root.mainloop()
Quote
#5
The easiest way to control or work with objects in tkinter is to use tags.
I don't see the need for 2 classes here
from tkinter import Tk,Frame,Canvas,Button,RIGHT,LEFT
  
class Button_Can(Frame):
    def __init__(self):
        Frame.__init__(self)
        self.pack(expand='yes',fill='both')
        self.larg,self.haut=200,200
        self.can=Canvas(self.master,width=self.larg,height=self.haut,bg='ivory')
        self.can.pack()        
        self.b1=Button(self.master,text='Open it !',command=self.openMouth)
        self.b2=Button(self.master,text='Close it !',command=self.closeMouth)
        self.b3=Button(self.master,text='delete it!',command=self.delete_mouth)
        self.b1.pack(side=RIGHT)
        self.b2.pack(side=LEFT)
        self.b3.pack(side='bottom')
        self.setup()
    def setup(self):
        
        cc =[[100, 100, 80, 'red'],[70, 70, 15, 'blue'], 
        [130, 70, 15, 'blue'],[70, 70, 5, 'black'],
        [130, 70, 5, 'black'],[44, 115, 20, 'red'], 
        [156, 115, 20, 'red'],[100, 95, 15, 'purple']] 
        i =0
        while i < len(cc):
            el = cc[i] 
            self.circle(el[0], el[1], el[2], el[3])
            i += 1 
        
  
    def circle(self,x, y, r, coul ='black'):
        "Draw a circle center x,y radius r "
        self.can.create_oval(x-r, y-r, x+r, y+r, outline=coul)
    def openMouth(self):
        self.can.delete('bouche')        
        self.opened_mouth= self.can.create_oval(70, 115, 130, 175,
                                                outline='purple',tag='bouche')
    def closeMouth(self):
        self.can.delete('bouche')        
        self.closed_mouth=self.can.create_line(80,145,120,145,
                                               fill='purple', tag='bouche')
    def delete_mouth(self):
        self.can.delete('bouche')
if __name__ == '__main__': 
    root = Tk()
    root.title('la visage')
    A=Button_Can()
    root.mainloop()
metulburr likes this post
Quote

Top Page

Possibly Related Threads...
Thread Author Replies Views Last Post
  [PySimpleGui] How to alter mouse click button of a standard submit button? skyerosebud 3 154 Jul-21-2019, 06:02 PM
Last Post: FullOfHelp
  wx.html2.WebView Methods ian 4 740 Apr-27-2018, 05:36 PM
Last Post: Larz60+
  Button click doesnt work from my second class/layout in Python imamideb 0 713 Feb-13-2018, 12:09 PM
Last Post: imamideb
  Overriding tkinter button methods Lubik_ 3 2,074 Sep-26-2017, 10:24 AM
Last Post: metulburr
  [Tkinter] Selected radio button in push button in Tkinter prashantfunde91 1 5,613 Jun-22-2017, 05:27 PM
Last Post: DeaD_EyE

Forum Jump:


Users browsing this thread: 1 Guest(s)