I want a certain function callable on a class. Something similar to:
class foo():
def __init__(self):
self.img = pygame.Surface((20, 20))
def magicfunction(self):
return self.img
bar = foo()
screen = pygame.display.set_mode((200, 200))
screen.blit(bar)
Which magic-function do I have to use?
If I understand you correctly, you want to create a class of your own, which is also a surface. That sounds exactly like inheritance! Try making foo a child of pygame.Surface:
class foo(pygame.Surface):
def __init__(self):
pygame.Surface.__init__(self, (20, 20))
more_data = "You should be able to extend this class freely"
Related
#This class is to be used with other classes of widgets, not with the class of kivy.app.
class TempatureFloatLayout(FloatLayout):
tempature = NumericProperty()
def __init__(self, **kwargs):
super().__init__(**kwargs)
Clock.schedule_interval(self.update, 1)
self.btn = Button()
self.btn.bind(on_press=self.do_something)
self.add_widget(self.btn)
def do_something(self, self_button):
pass
def update(self, dt):
self.btn.size = self.size # I can only resize and reposition the button here.
self.btn.pos = self.pos # pos and size are assigned with the pos and size
# values of the widget used
... the other codes
class TempatureFloatLayout(FloatLayout) can be used successfully in other classes. The code works correctly as it is. But, When every update, the position and size of the button is to be resized and repositioned. This doesn't feel right to me. How to bind a widget that is used and a button that is used in a different class. Where did I do wrong or is this usage correct?
I am trying to make a turtle race, but I get an error that the class "turtles" has no attribute "forward". Here is my code:
class turtles:
def __init__(self, color, posX):
self = turtle.Turtle(shape='turtle', visible=False)
self.color(color)
self.penup()
self.shape('turtle')
self.goto(posX, -300)
self.showturtle()
self.setheading(90)
def start_race(self):
self.forward(random.randrange(0,10))
t1 = turtles('red',-150)
t2 = turtles('orange', -100)
t3 = turtles('yellow',-50)
t4 = turtles('green', 0)
t5 = turtles('light blue', 50)
t6 = turtles('blue',100)
t7 = turtles('purple', 150)
def begin_race():
t1.start_race()
t2.start_race()
t3.start_race()
t4.start_race()
t5.start_race()
t6.start_race()
t7.start_race()
begin_race()
Replace your turtles class with this:
class turtles(turtle.Turtle):
def __init__(self, color, posX):
self.color(color)
self.penup()
self.shape('turtle')
self.goto(posX, -300)
self.showturtle()
self.setheading(90)
def start_race(self):
self.forward(random.randrange(0,10))
Inheritance in Python is done by specifying a class in brackets after declaring a class name.
In this case, your turtles class inherits from the turtle.Turtle class and then has its attributes changed. Seems there was also some repetition with specifying the turtle's colour and visibility (I removed that for you)
The reason you get this error is because there is no attribute (i.e. a variable or method) called forward in your turtles class. The forward method is part of the turtle.Turtle class. You could solve this in different ways:
Method 1: using inheritance
You could derive your turtles class from the existing turtle.Turtle class. To do that, you should make the following changes:
The class turtles should be defined as class turtles(turtle.Turtle) to derive from it.
In the __init__() method you should not reassign self, because this is a reference to the actual object that's being initialized.
You should call the __init__() method of the original Turtle class.
So the full code could be like below. I renamed start_race() to advance_race() because that better describes what it does. And I added an infinite loop so you'll see the turtles "racing". This is just for demonstration, of course.
import random
import turtle
class turtles(turtle.Turtle):
def __init__(self, color, posX):
super().__init__(shape='turtle', visible=False)
self.color(color)
self.penup()
self.goto(posX, -300)
self.showturtle()
self.setheading(90)
def advance_race(self):
self.forward(random.randrange(0,10))
t1 = turtles('red', -150)
t2 = turtles('orange', -100)
t3 = turtles('yellow', -50)
t4 = turtles('green', 0)
t5 = turtles('light blue', 50)
t6 = turtles('blue', 100)
t7 = turtles('purple', 150)
while True:
t1.advance_race()
t2.advance_race()
t3.advance_race()
t4.advance_race()
t5.advance_race()
t6.advance_race()
t7.advance_race()
Method 2: using a wrapper class
Alternatively, you could create a new class that "holds" a turtle object. Using this method, you should store the turtle "inside" self and access it as self.turtle (or any other name).
class turtles:
def __init__(self, color, posX):
self.turtle = turtle.Turtle(shape='turtle', visible=False)
self.turtle.color(color)
self.turtle.penup()
self.turtle.goto(posX, -300)
self.turtle.showturtle()
self.turtle.setheading(90)
def advance_race(self):
self.turtle.forward(random.randrange(0,10))
(rest of the code same as above)
I'm making a barcode generator. I need the input in class GUI to be read by class Barcode so it can print the lines on the canvas.
from tkinter import *
class GUI(Frame):
def __init__(self, master=None):
...
self.code_input = Entry(master)
self.code_input.pack()
self.code = self.code_input.get()
...
self.barcode = Barcode(master, height=250, width=200)
self.barcode.pack()
self.barcode.draw()
....
class Barcode(Canvas):
def draw(self):
self.ean = GUI.code
If I reference directly like the above it says AttributeError: type object 'GUI' has no attribute 'code'
If I do inheritance method (based on https://stackoverflow.com/a/19993844/10618936),class Barcode(Canvas, GUI) it says the same as the previous
If I use setter and getter methods:
class GUI(Frame)
def __init__(self, master=None):
...
#property
def code(self):
return self.__code
#code.setter
def code(self, code):
self.__code = code
then self.ean = GUI.code, it won't run the program and say
TypeError: 'property' object is not subscriptable instead
how do I fix this problem? Is the structure of my program really bad? I'm really not good at programming at all... I just want the variable in GUI to be transferred to class Barcode so it can compute and return the result back to GUI to display the barcode
You need to create an instance of the GUI, otherwise you are just referencing to the static class for which code is not defined. You could access it like in this example
class A():
def __init__(self):
self.code = "A"
class B():
def __init__(self):
self.code = "B"
def foo(self):
print(self.code + A().code)
b = B()
b.foo() # Outputs "BA"
Otherwise, to access it like an static variable within the class you need to define it inside the class root level
class A():
code = "C"
def __init__(self):
self.code = "A"
class B():
def __init__(self):
self.code = "B"
def foo(self):
print(self.code + A.code)
b = B()
b.foo() # Outputs "BC"
You should pass the GUI object to the Barcode class, which at the point you create the Barcode instance is self. If you want the Barcode to be inside the GUI frame, you can also directly use it as the Canvas master.
Another thing to notice is that with the way you have it now, self.code will be and remain an empty string, since you only define it right after you've created the Entry widget, at which point it is empty. You should use get on the Entry at the time you want to do something with the contents at that point.
from tkinter import *
class GUI(Frame):
def __init__(self, master=None):
Frame.__init__(self, master)
self.code_input = Entry(self)
self.code_input.pack()
self.barcode = Barcode(self, height=250, width=200)
self.barcode.pack()
Button(self, text="Update Barcode", command=self.barcode.draw).pack()
class Barcode(Canvas):
def __init__(self, master, height, width):
Canvas.__init__(self, master, height=height, width=width)
self.master = master
self.text = self.create_text((100,100))
def draw(self):
self.itemconfig(self.text, text=self.master.code_input.get())
root = Tk()
gui = GUI(root)
gui.pack()
root.mainloop()
For illustration purposes I create a text object on the canvas and update that with the current value of the Entry on a Button click.
I am using PyQt to create a GUI and need to create a periodic table made of buttons. Bellow is part of the code. Each button will require the following code in the method mainLayout(self).
class App(QMainWindow):
def __init___(self):
...
def mainLayout(self):
Element1 = QPushButton('shortname', self)
Element1.setToolTip('longname')
Element1.setCheckable(True)
Element1.resize(50, 50)
Element1.move(x, y)
Element1.clicked.connect(self.Element1_click)
This is a lot of repetitive code for one button when there will be 118 buttons. I made a GUI in the past which had this same problem and I remember I solved the issue with creating another class which I passed the argument for the unique attributes of each button.
I had something like this in mind where LayoutElm is a class.
LayoutElm(Element1 ,'shortname', 'longname', x, y, Element1_click)
Any ideas would be greatly appreciated.
You just have to create a function that creates the item:
class App(QMainWindow):
def __init___(self):
...
def mainLayout(self):
createLayoutElm('shortname', 'longname', (x, y), self.Element1_click)
createLayoutElm('shortname1', 'longname1', (100, 100), self.Element1_click2)
...
def createLayoutElm(self, name, tooltip, pos, callback):
btn = QPushButton(name, self)
btn.setToolTip(tooltip)
btn.setCheckable(True)
btn.resize(50, 50)
btn.move(*pos)
btn.clicked.connect(callback)
class Draw():
'''Class using, for example opengl, to display something on the screen'''
def add(self,size,file_name):
file_name= file_name
size = size
class Image(Draw):
def __init__(self,size,file_name):
self.size = size
self.add(self.size,file_name)
class Gui():
file_names = ['a.jpg','b.jpg']
images = {}
def __init__(self):
for e in self.file_names:
self.image = Image((50,50),file_name=e)
self.images[e] = self.image
def print_size(self):
print(self.image.size)
a = Gui()
a.print_size() #this gives me a proper (50,50) size
for e in a.images.values():
print(e.size) #this gives me wrong size
This is simplified version of my code. I don't have experience with storing objects in dictionary values.
My question is: is this normal that I don't access the right attributes of stored objects in dictionary? In this sample everything works ok, but is this a wrong way to writing code?
I run your code and it works as it should. In terminal there was printed
(50, 50)
(50, 50)
(50, 50)
Did you expected something else? Now I will try to explain few things.
class Draw():
'''Class using, for example opengl, to display something on the screen'''
I may not fully understand how it is supposed to work, but if you want to save size and file_name in add method you shouls use self. before variables, so it would look like
def add(self,size,file_name):
self.file_name = file_name
self.size = size
class Image(Draw):
def __init__(self,size,file_name):
self.size = size
self.add(self.size,file_name)
class Gui():
file_names = ['a.jpg','b.jpg']
images = {}
def __init__(self):
Now in every iteration you create new Image with the same size (50, 50), but diffrent filename and assing to map.
for e in self.file_names:
self.image = Image((50,50),file_name=e)
self.images[e] = self.image
In loop in above init method to self.image you assing the last image you created based on file_names ('b.jpg'), so self.image and self.images['b.jpg'] points to the same object.
Method print_size prints size of self.image / self.images['b.jpg'], which is (50, 50)
def print_size(self):
print(self.image.size)
a = Gui()
a.print_size() #this gives me a proper (50,50) size
Now you iterate on your images. There are 2: the one with file_name 'a.jpg' and second that was already printed before 'b.jpg'. Both of them has the same size of (50, 50).
for e in a.images.values():
print(e.size) #this gives me wrong size
I hope I clarified a little bit and it will help you