I am trying to make a small tetris game for learning python with kivy. I am trying to create a custom widget with size 20,20. When I add it to the float layout and run the below code I receive the following error:
Error:
File "D:\OS Files\workspace\Tetris\holder.py", line 10, in __init__ self.add_widget(c)
File "C:\Kivy180\kivy\kivy\uix\floatlayout.py", line 115, in add_widget pos_hint=self._trigger_layout)
TypeError: descriptor 'bind' of 'kivy._event.EventDispatcher' object needs an argument
Code:
holder.py File:
from items import Cell
class Holder(FloatLayout):
def __init__(self, **kwargs):
super(Holder,self).__init__(**kwargs)
self.size=(300,300)
c=Cell
#c.pos= (20,20)
self.add_widget(c)
#self.add_widget(c)
items.py File:
from kivy.uix.widget import Widget
from kivy.graphics import *
class Cell(Widget):
def __init__(self, **kwargs):
super(Cell,self).__init__(**kwargs)
with self.canvas:
Color(1, 0, 0)
Rectangle(pos=(0, 0), size=(50, 50))
self.height=50
self.width=50
main.py File:
from kivy.app import App
from holder import Holder
class start(App):
def build(self):
return Holder()
if __name__ == '__main__':
start().run()
Could you please explain where I went wrong, I am stuck at the starting point itself. Regarding the error, I haven't written any events also, and it is just a widget class. Could you please explain where I went wrong in understanding kivy.
c=Cell
I bet you want c to be an instance of the Cell class. If you want to do that, you need to do:
c=Cell()
Related
I am trying to create a simple programe that animates my label widget to desired position upon clicking on the kivy window. Just trying to experiment with inheritance to access all the elements in the parent element.
ani is the parent class and transit is the child class. I am trying to access the label attribute in transit via inheritance. But this throws error.
from kivy.app import App
from kivy.uix.label import Label
from kivy.animation import Animation
from kivy.uix.widget import Widget
class transit(ani,Widget):
def __init__(self,**kwargs):
ani.__init__(self,**kwargs)
def on_touch_down(self,touch):
val = 5
print(touch.x,touch.y)
self.val +=10
animation = Animation(x = touch.x,y =touch.y,font_size=self.val,d=2,t='in_out_quad')
animation.start(self.parent.label)
class ani(App):
def __init__(self,**kwargs):
self.label = Label(text='increase')
def build(self):
return transit()
root = ani()
root.run()
I believe you are trying to use inheritance with the wrong class. If you want to move a Label, you need to put the Label in a container and make sure the size of the Label does not fill the container. Since the position of the Label is controlled by its container, you need to use inheritance with the container. Here is a simple code, similar to yours, that uses a FloatLayout as the container:
from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.label import Label
from kivy.animation import Animation
class MyFloatLayout(FloatLayout):
def on_touch_down(self, touch):
if self.collide_point(*touch.pos):
val = 5
label = App.get_running_app().label
animation = Animation(x = touch.x,y =touch.y,font_size=val,d=2,t='in_out_quad')
animation.start(label)
return super(MyFloatLayout, self).on_touch_down(touch)
class ani(App):
def build(self):
root = MyFloatLayout()
self.label = Label(text='increase', size_hint=(None, None), size=(100,40))
root.add_widget(self.label)
return root
if __name__ == '__main__':
ani().run()
This code uses inheritance to define a new MyFloatLayout class that adds a new on_touch_down() method that does the animation. Note that the new on_touch_down() also calls super(MyFloatLayout, self).on_touch_down(touch). Unless there is a specific reason for not doing that, you normally want to call the super method in an inherited method.
I'm new to python and PyQt and was developing my first app using it, and I've been stuck in a problem when trying to instantiate a class I made again. I've got the following error:
Traceback (most recent call last):
File "ConfiguradorAnx.py", line 16, in <lambda>
self.ProductInfo.clicked.connect(lambda: self.newWindow(InfoProduct))
TypeError: 'InfoProduct' object is not callable
Aborted
The code goes like this:
from PyQt5 import QtCore, QtGui, QtWidgets, uic
import sys
class StartWindow(QtWidgets.QMainWindow): #This function should inherit the class
#used to make the ui file
def __init__(self):
super(StartWindow,self).__init__() #Calling the QMainWindow constructor
uic.loadUi('Janela_inicial.ui',self)
#defining quit button from generated ui
self.QuitButton = self.findChild(QtWidgets.QPushButton, 'QuitButton')
self.QuitButton.clicked.connect(QtCore.QCoreApplication.instance().quit)
#defining product info button
self.ProductInfo = self.findChild(QtWidgets.QPushButton, 'ProductInformation')
self.ProductInfo.clicked.connect(lambda: self.newWindow(InfoProduct))
self.show() #Show the start window
def newWindow(self, _class):
self.newWindow = _class()
del self.newWindow
class InfoProduct(QtWidgets.QMainWindow):
def __init__(self):
super(InfoProduct,self).__init__()
uic.loadUi('informacao_prod.ui',self)
self.QuitButton = self.findChild(QtWidgets.QPushButton, 'pushButton')
self.QuitButton.clicked.connect(lambda: self.destroy())
self.show()
def main():
app = QtWidgets.QApplication(sys.argv) #Creates a instance of Qt application
InitialWindow = StartWindow()
app.exec_() #Start application
if __name__ == '__main__':
main()
The first time I click on self.ProductInfo button it works and the InfoProduct window opens, but when I close the window and click on the same button again, I've got the error. I can't figure out what is it that I'm missing, I hope you guys could help!
Cheers!
You're overwriting the newWindow function in its execution:
def newWindow(self, _class):
self.newWindow = _class()
By doing this, the result is that the next time you click the button, the lambda will try to call self.newWindow(InfoProduct), but at that point self.newWindow is an instance of InfoProduct, which obviously is not callable.
The solution is simple (and very important) use different names for the function and the variable that points to the instance:
self.ProductInfo.clicked.connect(lambda: self.createNewWindow(InfoProduct))
def createNewWindow(self, _class):
self.newWindow = _class()
Two small side notes:
There's no need to use findChild, as loadUi already creates python instance attributes for widgets: you already can access self.QuitButton, etc.
Avoid using capitalized names for variables and attributes. Read more about this and other code styling suggestions on the Style Guide for Python Code (aka, PEP-8).
I was trying to get continuous touch motion in Kivy to move a rectangle for which I wrote a code
from kivy.app import App
from kivy.uix.button import Label
from kivy.uix.widget import Widget
from kivy.graphics import Rectangle
from kivy.core.window import Window
class Game(Widget):
def __init__(self,**kwargs):
super().__init__(**kwargs)
with self.canvas:
Color=(0,1,0,1)
self.player=Rectangle(pos=(50,0),size=(20,50))
#touch and motion of our player
def on_motion(self,etype,motionevent,**kwargs):
print('hello')
touch_condition=False
x_touch=motionevent.spos[0]
xa=self.player.pos[0]
ya=self.player.pos[1]
if etype=='begin' or etype=='update':
touch_condition=True
if etype=='end':
touch_condition=False
if touch_condition and x_touch>0.5:
xa+=10
if touch_condition and x_touch<0.5:
xa-=10
self.player.pos=(xa,ya)
Window.bind(on_motion=on_motion)
class Try(App):
def build(self):
return Game()
if __name__=="__main__":
Try().run()
On mouse click as an input its giving an error
File "kiv.py", line 21, in on_motion
xa=self.player.pos[0] AttributeError: 'WindowSDL' object has no attribute 'player'
I read all documentation on Kivy inputs and Window.bind but I am still unable to understand how to solve it.
Your class structure is messed up, you're binding on_motion at the class level. I'm surprised this is the error you get, but that looks like the problem.
Add Window.bind(on_motion=self.on_motion) in the __init__ of your Game widget instead.
I am relatively new to OOP and I have a problem with my code. In an attempt to arrange my code, I would like to save functions in separate files (here menu.py) and then initialize them through def __init__(self): in class (file name app.py) (better than trying to understand my weird description is to look directly on my code ☻). It returns AttributeError and I have no clue how to repair it. Can anyone help me please? (P.S. if you understand what I am trying to do and you know better way how to do that, please tell me ☻)
app.py
import tkinter
from tkinter import *
from menu import Menu
class App(Menu):
def __init__(self):
self.root = tkinter.Tk()
...
self.Menu_Bar()
...
self.root.mainloop()
menu.py
import tkinter
from tkinter import *
class Menu():
def Menu_Bar(self):
self.menuBar = Menu(self.root)
self.menuBar.add_cascade(label="File", menu = self.fileMenu)
...
self.root.config(menu = self.menuBar)
AttributeError: 'App' object has no attribute 'Menu_Bar'
Im trying to make function, which passes 8 values to the progress bars in window app made with QtDesigner.
That is there is a function which actually generates this values. I want to execute it every second in order to get theese values and update progress bars which displays values.
I combined tutorials about making a graphic app with Python and making an app with dynamically updating progess bars:
Python Qt Development: https://www.youtube.com/watch?v=eD91nE8q8Nk
PyQt Progress bar with Thread: https://www.youtube.com/watch?v=ivcxZSHL7jM
The problem is that values are passed correctly, but when it comes to send the signal, the whole app crashes with message:
Process finished with exit code 139 (interrupted by signal 11:
SIGSEGV)
Here is my code:
Module which generates the values (probkowanie.py):
import time
from random import randint
import threading
def getSignals():
time.sleep(1)
signals = (randint(0, 100), randint(0, 100), randint(0, 100), randint(0, 100), randint(0, 100), randint(0, 100), randint(0, 100), randint(0, 100), )
return signals
and here is main program code:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from PySide.QtCore import *
from PySide.QtGui import *
from PyQt4 import QtCore
import sys
import time
import signalPreview # window library
import probkowanie # values generating library
class MainDialog(QDialog, signalPreview.Ui_mainDialog):
def __init__(self, parent=None):
super(MainDialog, self).__init__(parent)
self.setupUi(self)
self.threadclass = ThreadClass()
self.threadclass.start()
self.connect(self.threadclass, QtCore.SIGNAL('MYO_SIGNALS'), self.updateProgressBars)
def updateProgressBars(self, signals):
self.progressBar.setValue(signals[0])
class ThreadClass(QtCore.QThread):
def __init__(self, parent = None):
super(ThreadClass, self).__init__(parent)
def run(self):
while 1:
signals = probkowanie.getSignals()
self.emit(QtCore.SIGNAL('MYO_SIGNALS'), 5) # this line causes crash
print signals # it works correctly
app = QApplication(sys.argv)
form = MainDialog()
form.show()
app.exec_()
I think it may be caused by mixing libraries. I use QtCore from PySide even though tutorial number 2 is based on PyQt4. My decision is because tutorial number 1 is based on PySide.
I tried changing:
from PySide import QtCore
to
from PyQt4 import QtCore
but then I get another bunch of errors, which I don't know what to do with:
Traceback (most recent call last):
File "/usr/lib/pycharm/helpers/pydev/pydevd.py", line 1580, in <module>
globals = debugger.run(setup['file'], None, None, is_module)
File "/usr/lib/pycharm/helpers/pydev/pydevd.py", line 964, in run
pydev_imports.execfile(file, globals, locals) # execute the script
File "/mnt/Grubas/Projekty/Biomed/MYO/myo.py", line 36, in <module>
form = MainDialog()
File "/mnt/Grubas/Projekty/Biomed/MYO/myo.py", line 20, in __init__
self.connect(self.threadclass, QtCore.SIGNAL('MYO_SIGNALS'), self.updateProgressBars)
TypeError: 'PySide.QtCore.QObject.connect' called with wrong argument types:
PySide.QtCore.QObject.connect(ThreadClass, str, instancemethod)
Supported signatures:
PySide.QtCore.QObject.connect(PySide.QtCore.QObject, str, callable, PySide.QtCore.Qt.ConnectionType = Qt.AutoConnection)
PySide.QtCore.QObject.connect(PySide.QtCore.QObject, PySide.QtCore.QMetaMethod, PySide.QtCore.QObject, PySide.QtCore.QMetaMethod, PySide.QtCore.Qt.ConnectionType = Qt.AutoConnection)
PySide.QtCore.QObject.connect(PySide.QtCore.QObject, str, PySide.QtCore.QObject, str, PySide.QtCore.Qt.ConnectionType = Qt.AutoConnection)
PySide.QtCore.QObject.connect(PySide.QtCore.QObject, str, str, PySide.QtCore.Qt.ConnectionType = Qt.AutoConnection) PySide.QtCore.QObject.connect(str, callable, PySide.QtCore.Qt.ConnectionType = Qt.AutoConnection)
PySide.QtCore.QObject.connect(str, PySide.QtCore.QObject, str, PySide.QtCore.Qt.ConnectionType = Qt.AutoConnection)
#EDIT
After providing changes proposed by #ekhumoro script doens't crash, but now I'm getting another error:
QObject::connect: Cannot queue arguments of type 'object' (Make sure
'object' is registered using qRegisterMetaType().)
I tried to look for solution on my own, but I didn't find the exact code which I need. I also tried transforming type of signal from (object) to (tuple) or (list), but it leads to another errors:
TypeError: Unknown type used to call meta function (that may be a
signal): tuple
The most solutions I found are based on PyQT. Is there an easy way to rewrite it for PySide?
Here is an example of solution, which seems to be correct but is made using PyQT:
https://stackoverflow.com/a/2595607/2550466
You are right to think that mixing PySide and PyQt will cause problems, so you will need to remove one of them. However, the crash itself is probably caused by a bug in PySide. There is an SO question with a similar problem shown here:
How to send None with Signals across threads?
So you also need to change the way you define and emit MYO_SIGNALS.
Below is a fixed version of your script (the changed lines are commented):
# from PySide.QtCore import *
# from PySide.QtGui import *
# from PyQt4 import QtCore
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import sys
import time
import signalPreview # window library
import probkowanie # values generating library
class MainDialog(QDialog):
def __init__(self, parent=None):
super(MainDialog, self).__init__(parent)
self.setupUi(self)
self.threadclass = ThreadClass()
self.threadclass.start()
# self.connect(self.threadclass, QtCore.SIGNAL('MYO_SIGNALS'), self.updateProgressBars)
self.connect(self.threadclass, SIGNAL('MYO_SIGNALS'), self.updateProgressBars)
def updateProgressBars(self, signals):
self.progressBar.setValue(signals[0])
# class ThreadClass(QtCore.QThread):
class ThreadClass(QThread):
def __init__(self, parent = None):
super(ThreadClass, self).__init__(parent)
def run(self):
while 1:
signals = probkowanie.getSignals()
# self.emit(QtCore.SIGNAL('MYO_SIGNALS'), 5) # this line causes crash
self.emit(SIGNAL('MYO_SIGNALS'), signals)
print signals # it works correctly
app = QApplication(sys.argv)
form = MainDialog()
form.show()
app.exec_()