So I'm writing a drum pad:
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.gridlayout import GridLayout
from kivy.uix.button import Button
from kivy.core.audio import SoundLoader
class GridAction(Button):
pass
class MakingGrid(GridLayout):
def __init__(self, *args, **kwargs):
super(MakingGrid, self).__init__(*args, **kwargs)
for i in range(16):
grid_action = GridAction()
grid_action.bind(on_release=self.button_pressed)
self.add_widget(grid_action)
def button_pressed(self, button):
print('pressed')
class MyApp(App):
def build(self):
return MakingGrid(cols=4)
if __name__ == "__main__":
MyApp().run()
There is a grid of buttons as a result, and the purpose is to make them sound different, but I don't know how to do this. Please, help. Thanks in advance) Also, if you see any disadvantages in this code, please, tell me about them, I`m a beginner.
A simple way to play audio is with kivy's soundloader.
Beyond this, I'm not clear on what your question actually is. The general answer is to do something like give each GridAction its own audio_file property holding a filepath to the sound you want, and bind the on_press events to play the sound at this location.
Related
I am a beginner in Python and Kivy. I want to create a simple program that should have an exit button on a window that must exit the app when pressed. Hi there, please help me. It's a request, please keep the code simple for a beginner. ^_^
Okay, I don't know how your code is, but this code could be copy-pasted as is and it will work (just import the necessary modules from kivy though):
.py
from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.button import Button
class yourscreen(FloatLayout):
def __init__(self, **kwargs):
#NEEDED
super(yourscreen, self).__init__(**kwargs)
self.button = Button(
text='exit',
size_hint=(0.5, 0.2)
)
self.button.bind(on_release= lambda x:self.exit())
self.add_widget(self.button)
def exit(self):
return MyApp().stop()
class MyApp(App):
def build(self):
return yourscreen()
if __name__ == '__main__':
MyApp().run()
You could pull out what you need which is MyApp().stop()
I'm working on an app, and I need the images to display independently at a specific timing. I have set up a thread using python's stock threading module, it runs and works normally instead of the image it displays a black square. Does anyone know how to fix it?
Here is my code to reproduce the issue:
import threading
from kivy.app import App
from kivy.uix.image import Image
from kivy.uix.button import Button
from kivy.uix.floatlayout import FloatLayout
class TestApp(App):
def build(self):
self.fl = FloatLayout()
self.fl.add_widget(Button(text="show image", on_press=self.start_thread))
return self.fl
def insertfunc(self):
self.fl.add_widget(Image(source="HeartIcon.png"))
def start_thread(self, instance):
threading.Thread(target=self.insertfunc).start()
TestApp().run()
Any help will be appreciated!
The add_widget() must be done on the main thread. I assume that you are using threading because you have additional things to do on the Thread aside from just the add_widget(). Based on that assumption, here is a modified version of your code that does what I think you want:
import threading
from kivy.app import App
from kivy.clock import Clock
from kivy.uix.image import Image
from kivy.uix.button import Button
from kivy.uix.floatlayout import FloatLayout
class TestApp(App):
def build(self):
self.fl = FloatLayout()
self.fl.add_widget(Button(text="show image", on_press=self.start_thread))
return self.fl
def insert_image(self, dt):
self.fl.add_widget(Image(source="HeartIcon.png"))
def insertfunc(self):
# do some calculations here
Clock.schedule_once(self.insert_image)
def start_thread(self, instance):
threading.Thread(target=self.insertfunc).start()
TestApp().run()
If you are not doing anything else in the new thread, then you don't actually need another thread. The start_thread() method can just do the:
self.fl.add_widget(Image(source="HeartIcon.png"))
I have problem with disabling of buttons in kivy library. When I disable button, it simply not disable. It waits in some strange way.
Let me show you my code:
import kivy
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.floatlayout import FloatLayout
import time
class MainApp(App):
def build(self):
self.l = FloatLayout()
b = Button(text="BUTTON", pos_hint={"top":0.8, "right": 0.8}, size_hint=(0.6, 0.6))
b.bind(on_press=self.press)
self.l.add_widget(b)
return self.l
def press(self, btn):
btn.disabled = True
time.sleep(3.0)
btn.disabled = False
app = MainApp()
app.run()
When I press button, I want to disable it for 3 sec. But instead of it program "freeze" (without disabling of button), and then after 3 secs do animation of press (button blinks with blue color). Of cource program must "freeze" because of time.sleep(3.0), but after disabling of button (Which must be gray, but it dont change color...)
How to solve it? If I put there instead time.sleep() something like for cycle (with about 10 milions of cycle) to imitate of "doing something" by program, it behaves in the same way...
So how I can solve it? How to disable button in kivy, then do something and after it is done enable button again?
Thanks!
EDIT: My problem isn't, that program freezes for 3 seconds. I understand that calling time.sleep() is blocking. What I don't understand is why button is not disabled before (and during) sleep...
The time.sleep is blocking the code. Instead you need to use Clock to enable the button after 3 seconds. Below is the corrected code to achieve your target:
import kivy
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.floatlayout import FloatLayout
from kivy.clock import Clock
from functools import partial
class MainApp(App):
def build(self):
self.l = FloatLayout()
b = Button(text="BUTTON", pos_hint={"top":0.8, "right": 0.8}, size_hint=(0.6, 0.6))
b.bind(on_press=self.press)
self.l.add_widget(b)
return self.l
def press(self, btn):
btn.disabled = True
Clock.schedule_once(partial(self.btn_enable, btn), 3)
def btn_enable(self, btn, *args):
btn.disabled = False
app = MainApp()
app.run()
TL; DR
The animation happens after the press function is called. This means that you freeze the program when doing time.sleep.
What to do about it?
Instead, you need to do something non-blocking, meaning that it runs in three seconds, but it doesn't cause the program to freeze. Something that would probably work is to utilize threads (something similar to the example, but dealing with sending variables across threads).
Example
Here is an example for your code that does not work, so you can understand the gist of it. Most likely, you are going have to deal with passing variables across threads:
import kivy
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.floatlayout import FloatLayout
# import time
import threading
class MainApp(App):
def build(self):
self.l = FloatLayout()
b = Button(text="BUTTON", pos_hint={"top":0.8, "right": 0.8}, size_hint=(0.6, 0.6))
b.bind(on_press=self.press)
self.l.add_widget(b)
return self.l
def press(self, btn):
btn.disabled = True
# time.sleep(3.0)
threading.Timer(3.0, lambda: btn.disabled = False).start()
app = MainApp()
app.run()
This was inspired by this answer.
I found this piece of code:
from kivy.app import App
from kivy.lang import Builder
from kivy.core.window import Window
from kivy.uix.boxlayout import BoxLayout
class Test(BoxLayout):
def __init__(self, **kwargs):
super(Test, self).__init__(**kwargs)
Window.bind(on_touch_down=self.window_on_touch_down)
def window_on_touch_down(self, *args):
print(args)
# scrolling the wheel down will give <MouseMotionEvent button="scrollup"
if '<MouseMotionEvent button="scrollup"' in args:
print('hello')
class TestApp(App):
def build(self):
return Test()
if __name__ == '__main__':
TestApp().run()
and while it prints the scrollup motion I can't use it... args has the string in it but the if doesn't work and "hello" isn't printed... anybody know why?
What you see in the prints are python objects not strings.
So you can't just check for a string.
A better way to get what you want is to check what button produces the MouseMotionEvent
def window_on_touch_down(self, window, mouse_event):
# scrolling the wheel down will give <MouseMotionEvent button="scrollup"
if mouse_event.button == "scrollup":
print('hello')
Audio unload does not seem to actually release memory, at least as far as top on linux is concerned. Repeatedly loading and unloading causes memory usage to creep upward. Did I miss something obvious?
from __future__ import print_function
import kivy
kivy.require('1.9.0') # replace with your current kivy version !
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.core.audio import SoundLoader
class SoundTest(BoxLayout):
def __init__(self, **kwargs):
super(SoundTest, self).__init__(**kwargs)
button = Button(text='Play sound')
self.add_widget(button)
button.bind(on_release=self.PlaySound)
def PlaySound(self, widget):
snd = SoundLoader.load('test.ogg')
snd.bind(on_stop=self.UnloadSoundWhenDone)
snd.play()
print ("play", snd)
def UnloadSoundWhenDone(self, snd):
print ("unload", snd)
snd.unload()
class MyApp(App):
def build(self):
return SoundTest()
if __name__ == '__main__':
MyApp().run()
Update: this seems to be using the kivy.core.audio.audio_gstplayer.SoundGstplayer backend.
Actually, the memory does not appear to creep upward indefinitely, so while SoundGstplayer seems to allocate itself much more than the SDL2 backend, this probably as intended.
del an_obj
Try to delete the actual object, maybe? I am not exactly sure what you are doing.