error while binding functions to buttons in a loop - python

I am using kivy to make a small music player but i have some issues with it. I am using a screen manager which will direct the user to either his libraries, or the entire tracks list. When one of the two is selected i want to find and load all the titles as buttons, to be played when pressed. Here's the basic track class:
class Track(Button):
path = 'C:/Users/...../tracks/'
def __init__(self,title,**kwargs):
self.title = title
super(Track,self).__init__(text=self.title,**kwargs)
def playTrack(self):
self.sound = SoundLoader.load(self.path+self.title)
self.sound.play()
also here is a music class that finds all the tracks in the directory and adds them to a list:
class mymusic():
path = 'C:/Users/...../tracks'
def __init__(self,**kwargs):
self.tracks=os.listdir(self.path)
print self.tracks
def loadTracks(self):
trackslist = []
for i in self.tracks:
trackslist.append(Track(i))
return trackslist
Finally, here is the code i use, that is supposed to create the buttons (the sm below is the screen manager, and root,libraries and music are subclasses of screen):
f = lambda obj: obj.playTrack()
Music = music(name='Music')
layout = BoxLayout()
Music.add_widget(layout)
sm.add_widget(root(name='Root'))
sm.add_widget(libraries(name='My libaries'))
sm.add_widget(Music)
musicobj = mymusic()
tracklist = musicobj.loadTracks()
for i in tracklist:
print i
i.bind(on_press=f(i))
This does not work. By running it i get the following error:
Traceback (most recent call last):
File "C:\Users\Vlassis\Desktop\test.py", line 108, in <module>
i.bind(on_press=f(i))
File "kivy\_event.pyx", line 430, in kivy._event.EventDispatcher.bind (kivy\_event.c:5903)
AssertionError: None is not callable
also the last track in the directory plays in the background. I can't figure out why. Is the logic behind the code correct? How should i go about doing this? Thanks in advance.

Related

plyer stt encounter error on huawei device

I am trying to implement a kivy app which include the plyer.stt module, but it return error on stt.start() and return empty list
When I compile it, I made sure to give all all the permission needed (INTERNET,RECORD_AUDIO,FOREGROUND_SERVICE), I also made sure to allow microphone permission.
When I call stt.start(), I did not hear any 'beep' sound, I instead an error:
File "jnius/jnius_utils.pxi", line 91, in jnius.jnius.check_exception 10-31 22:13:49.969 28130 28130 I python : jnius.jnius.JavaException: JVM exception occurred: Not allowed to bind to service Intent { act=android.speech.RecognitionService cmp=com.huawei.vassistant/.voiceui.service.FakeRecognitionService } java.lang.SecurityException
and stt.result return me an empty list.
Can someone enlighten me on what is the reason that this happen and how can I bypass it?
Here are some snippets of my functions
Code:
def listen(self):
print(stt.exist())
if stt.listening:
self.stop_listening()
return
#Change button text
start_button = self.ids.start_button
start_button.text = 'Stop'
stt.start()
Clock.schedule_interval(self.check_state, 1 / 5)
def stop_listening(self):
start_button = self.ids.start_button
start_button.text = 'Start Listening'
stt.stop()
self.update()
Clock.unschedule(self.check_state)
def update(self):
#Display the result to a label on screen
app.root.append(str(stt.partial_results))
app.root.append(str(stt.results))
It seems that I get the error after executing stt.start()

'bool' object has no attribute 'idKey' using while

I'm writing a graphic application that gives a word after I press a key in my electric piano using a database.
I'm using PyGame, Tkinter and Sqlite.
The application is pretty simple and is almost finished,
but I'm stuck with that error between my piano.py and the frontEnd.py.
The thing is that I want a Label that writes what was the last key I pressed and put it on a canvas.
I know the problem is related to the 'while True' and already changed it with 'while idKey < 176' but with this change I receive the "noneType" error.
This is the current code in my file piano.py
piano.py
import pygame
import pygame.midi
from pygame.locals import *
class backPiano():
def funcPiano(self):
self = backPiano
pygame.init()
pygame.fastevent.init()
event_get = pygame.fastevent.get
event_post = pygame.fastevent.post
pygame.midi.init()
input_id = pygame.midi.get_default_input_id()
i = pygame.midi.Input( input_id )
while True:
events = event_get()
if i.poll():
midi_events = i.read(10)
idKey = midi_events[0][0][0]
if idKey == 176:
return False
And the code in my frontEnd (only the function with the problem):
frontEnd.py
from tkinter import *
from tkinter import ttk, font
import multiprocessing
import time
import os
from database import dictionary, path
from piano import backPiano
class frontEnd(Frame):
def __init__(self, parent):
self.backPiano = backPiano()
def capturePiano(self):
backPiano.funcPiano(self)
superPiano = StringVar()
superPiano.set(backPiano.funcPiano(self).idKey)
labelPiano.configure(textvariable=superPiano)
self.parent.update()
canvasWidth = 500
canvasHeight = 500
w = Canvas(parent, width=canvasWidth, height=canvasHeight)
w.place(x=monitorWidth/2,y=monitorHeight/2, anchor=CENTER)
w.create_image(canvasWidth/2, canvasHeight/2, image=img, anchor=CENTER)
labelPiano = Label(parent)
labelPiano.place(x=monitorWidth/2,y=monitorHeight/2)
In the line 'superPiano.set(backPiano.funcPiano(self).idKey)' I tried:
"superPiano.set(backPiano.idKey)"
But because the variable is inside a function it can't be called with that.
The exact error I have is this:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\admin\AppData\Local\Programs\Python\Python37\lib\tkinter\__init__.py", line 1705, in __call__
return self.func(*args)
File "C:\Users\admin\Desktop\python\frontEnd.py", line 202, in <lambda>
command=lambda : capturePiano(self)).place(x=monitorWidth/9,y=monitorHeight/2,anchor=CENTER)
File "C:\Users\admin\Desktop\python\frontEnd.py", line 187, in capturePiano
superPiano.set(backPiano.funcPiano(self).idKey)
AttributeError: 'bool' object has no attribute 'idKey'
I can't upload all the code, but the error is in the While True but removing it destroys all my code because I need the loop.
Thank you very much (and sorry if I made grammar mistakes).
As the error message says: funcPiano is returning a boolean (True) so when you try to take the idKey it fails, because booleans don't have that.

python 3.4, setting up QWidgets.QMessageBox

an update to my code, based on the reply of Israel Unterman:
The Error-Class is now
from PyQt5 import QtWidgets
from PyQt5.QtWidgets import QMainWindow
class Error(QtWidgets.QMainWindow):
reply = False
last_reply_id = None
last_id = 0
def __init__(self, error_code_string, parent=None):
super().__init__(parent)
QtWidgets.QMessageBox.warning(self, "Warnung", error_code_string, QtWidgets.QMessageBox.Ok)
id = give_id(self)
def give_id(self):
self.last_id += 1
return self.last_id
def give_reply(self):
if last_id == last_reply_id:
return self.reply
else:
return None
def set_reply(self, button, id):
if button in (QMessageBox.Ok, QMessageBox.Yes):
reply = True
else:
reply = False
self.last_reply_id = id
return reply
And the Test-Script comes with
from ErrorHandling import Error
Error('Test')
If I am using the normal Code (practically the same Code, just wrapped in a class) the message appears and then at the line
id = give_id(self)
the Code stops without any errormessage from python, just:
Process finished with exit code 1
If I use the test-script, there is nothing (No QMessageBox!) than this:
Process finished with exit code 1
If I debug the Code, init() gets the same Objects and variables, but
super().__init__(parent)
fails without any message.
So where is the mistake, or difference.
Here a shortend Version of the Class (it's too long to show all code here), from which the "Error" works nearly fine:
from ErrorHandling import Error
class MainWindow(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
# set some variables
self.create_layout()
def create_layout(self):
# creates a GUI using QWidgets with some Inputboxes and one button
[...]
def button_start_clicked(self):
Error('Check the input')
Here is the old question:
I have a problem regarding the setup of QtWidgets.QMessageBox.
All Code follows the description.
The ErrorHandling-Modul should give a message about an error.
If needed it may ask a question too.
The function ErrorMsg.errorMessage is called from other Moduls in case of an catched exception.
There will be more functions added.
If I run the code the following error occurs:
Connected to pydev debugger (build 145.1504)
Traceback (most recent call last):
File "C:\Program Files (x86)\JetBrains\PyCharm Community Edition 2016.1.4\helpers\pydev\pydevd.py", line 1531, in <module>
globals = debugger.run(setup['file'], None, None, is_module)
File "C:\Program Files (x86)\JetBrains\PyCharm Community Edition 2016.1.4\helpers\pydev\pydevd.py", line 938, in run
pydev_imports.execfile(file, globals, locals) # execute the script
File "C:\Program Files (x86)\JetBrains\PyCharm Community Edition 2016.1.4\helpers\pydev\_pydev_imps\_pydev_execfile.py", line 18, in execfile
exec(compile(contents+"\n", file, 'exec'), glob, loc)
File "C:/Quellcode/AllgTest.py", line 5, in <module>
reply = errm.errorMessage('Test')
File "C:/Quellcode\ErrorHandling.py", line 20, in errorMessage
msg_box.setIcon(QMessageBox.Warning)
TypeError: QMessageBox.setIcon(QMessageBox.Icon): first argument of unbound method must have type 'QMessageBox'
Process finished with exit code 1
I tried quite some variations and googled, but I have no idea what the problem is since I found some examples that are using the line
QMessageBox.setIcon(QMessageBox.Icon)
So where is my mistake?
And now the Code:
There is the following testscript to test my ErrorMsg-class
from ErrorHandling import ErrorMsg
errm = ErrorMsg()
reply = errm.errorMessage('Test')
And here is my ErrorHandling-Modul
from PyQt5.QtWidgets import QMessageBox
from PyQt5.QtWidgets import QMainWindow
class ErrorMsg(QMainWindow):
def __init__(self):
pass
def giveback(self,button):
if button in (QMessageBox.Ok, QMessageBox.Yes):
reply = True
else:
reply = False
return reply
def errorMessage(self, error_msg, buttons='OK'):
msg_box = QMessageBox
msg_box.setIcon(QMessageBox.Warning)
msg_box.setWindowTitle('Warning')
if buttons == 'OK':
msg_box.setStandardButtons(QMessageBox.Ok)
elif buttons == 'YesNo':
msg_box.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
else:
error_msg = 'Unknown Button >' + buttons + '<, use >OK< or >YesNo<'
raise ValueError(error_msg)
msg_box.setText(error_msg)
clicked_button = msg_box.exec()
return giveback(clicked_button)
Thanks for your help
James
You didn't create an object of the message box. To create an object use:
msg_box = QMessageBox()
But you don'y need to go through all this, since QMessageBox has static functions for showing messages, which you can call directly on the QMessageBox class. For example:
QMessageBox.warning(None, 'title', 'msg')
You also have some control over the butons, see QMessageBox

Global name error when importing class as wild card Python

I am trying to make a multiple "page" GUI using tkinter and couldn't really find a good method. I resorted to using grid_forget and seperating the "pages" in methods and it works like a charm. However I am trying to seperate the methods into a seperate file to make everything a little cleaner but I keep getting a global name error upon trying to run one of the methods with all of the widgets from my main file/class.
Traceback (most recent call last):
File "C:/Users/Derek/PycharmProjects/whites/Main.py", line 3, in <module>
from screens import *
File "C:\Users\Derek\PycharmProjects\whites\screens.py", line 4, in <module>
import Main
File "C:\Users\Derek\PycharmProjects\whites\Main.py", line 54, in <module>
app = Application(master=main, w=main.winfo_width(), h=main.winfo_height())
File "C:\Users\Derek\PycharmProjects\whites\Main.py", line 20, in __init__
home_screen(self,True)
NameError: global name 'home_screen' is not defined
I also tried importing it such as import screens and tried to run screens.home_screen(self,True) and that yeilds
AttributeError: 'module' object has no attribute 'home_screen'
Even though it does
Example Main.py
from screens import *
import globals
class Application(tk.Frame):
globals.init()
def __init__(self, w, h, master=None):
tk.Frame.__init__(self, master)
self.grid()
self.window_width = w
self.window_height = h
home_screen(self,True)
query_screen(False)
res_screen(False)
settings_screen(False)
screens.py
import tkinter as tk
import globals
import Main
def home_screen(self, state):
*define widgets for this "screen"
[EDIT]
Here is a copy of the full files.screens , Main , globals
[EDIT: 2]
So I changed the code around to try a different solution and it basically the same error. module object has no attribute if I attempt to convert the screens.py into a class and initialize it as an object but nothing. So I am guessing this means it is not python at all and more my project settings have somewhere gone askew
You define:
def home_screen(self, state):
but it's not in any class!
Remove the self from the function signature and call it using only state variable only
EDIT:
If you create main.py:
from screens import *
class Application():
def __init__(self):
home_screen(True)
# then later on
a = Application() # this will print 'True'
and in file screens.py:
def home_screen(state):
print state
it will work (assuming both are in the same directory).
The solutions was to run the screens.py and not the main.py. Why that is I have no idea but it still ultimately fits my goal. If anyone would like to weigh in go for it.
[EDIT]
Final solution, change the way the program starts.It now runs just fine.
if __name__ == "__main__":
main = tk.Tk()
main.wm_title("White's Canoe Livery")
main.state("zoomed")
main.update()
# print(main.winfo_width())
app = Application(master=main, w=main.winfo_width(), h=main.winfo_height())
app.mainloop()

Python Attribute Error with multiple classes and Tkinter

I'm trying create a gui using Tkinter that grabs a username and password and connects to a remote server and does a function. I slapped together some messy code and it more or less worked, but when I tried to recreate it in a tidy module, it broke. Its probably a newbie python error, but I can't spot it. EDIT: to clarify, when it worked, the only class was setupGui and any methods were under that class. Now that I've separated the gui from the methods, its not working.
class setupGui(object):
def __init__(self, parent):
##omited general frame stuff
self.userIn = ttk.Entry(self.topFrame, width = 20)
self.userIn.grid(row = 1, column = 1)
self.passIn = ttk.Entry(self.topFrame, width = 20, show ="*")
self.passIn.grid(row = 2, column = 1)
#Buttons
self.setupbtn = ttk.Button(self.topFrame, text = "Start Setup", command = setup().startSetup())
self.setupbtn.grid(row = 3, column = 0, pady = 10)
class setup(object):
def__init__(self):
self.userName = setupGui.userIn.get()
self.userPass = setupGui.passIn.get()
def startSetup(self):
self.another_related_fucntion # about 4 related functions actually
if __name__ == '__main__':
root = Tk()
gui = setupGui(root)
root.mainloop()
And if I don't have the command attached to the button, everything works fine (but obviously does diddly squat except look pretty). And when I attached the command, I get this error:
Traceback (most recent call last):
File "macSetup.py", line 211, in <module>
gui = setupGui(root)
File "macSetup.py", line 45, in __init__
self.setupbtn = ttk.Button(self.topFrame, text = "Start Setup", command = setup().startSetup())
File "macSetup.py", line 69, in __init__
self.userName = setupGui.userIn.get()
AttributeError: type object 'setupGui' has no attribute 'userIn'
In your code, userIn is set up as an instance variable of setupGui objects, not as an attribute of the setupGui class itself.
The simplest solution would be to merge the setupGui and setup classes to move startSetup in as a method of setupGui, then use command=self.startSetup when you initialize setupbtn—this calls startSetup as a bound method, and self should thus refer to the setupGui object, which you can then use e.g. self.userIn.get() and self.passIn.get() on.
If you'd rather keep the logic you have in the setup class out of the setupGui class, you can separate it out like this:
class setup(object):
def __init__(self, username, userpass):
self.userName = username
self.userPass = userpass
def startSetup(self):
# as before
then add this method to the setupGui class:
def dosetup(self):
setup(self.userIn.get(), self.passIn.get()).startSetup()
and instantiate the Button with command=self.dosetup. (I would personally make the setup class a standalone function, but I don't know how complicated your startSetup routine actually is, so I assume you have a good reason for making it a class.)
The command attribute takes a reference to a function, but you're calling the function and giving the result to the command attribute. The net result is that you're calling the setup function at the time that you create the button, not at the time that you click the button. Things aren't fully initialized yet, so you get the error.
You're doing this:
self.setupbtn = ttk.Button(self.topFrame, text = "Start Setup", command = setup().startSetup())
... when you should be doing something like this:
self.setupbtn = ttk.Button(self.topFrame, text = "Start Setup", command = setup().startSetup)
Note the lack of the trailing () on startSetup.
If you don't want to instantiate setup until the button is clicked, you have a couple of choices. The best, arguably, is to create a method:
def _launch_setup(self):
setup().setupGui()
...
self.setupbtn = ttk.Button(..., command=self._launch_setup)
You could also use a lambda, but in this case I recommend a named method.
The class setupGui itself doesn't have the attribute userIn.
In the __init__ method of setupGui you give the attribute to the instance, not the class.

Categories

Resources