how can I start again when pressing image? - python

How can I start again when pressing image?
I want it to start again when I press the last images or 2/3 second later
class MyButton(ButtonBehavior, Image):
def __init__(self, **kwargs):
super(MyButton, self).__init__(**kwargs)
self.source = 's'
def on_press(self):
a = (random.randint(1, 1014124315124124))
if (int(a) % 2 == 0):
self.source = 's'
else:
self.source = 'd'
class SampleApp(App):
def build(self):
return MyButton()
SampleApp().run()

Look into kivy's Clock.schedule_once. The basic idea is, when the button is pressed, you will set it to a new image, and schedule another function (let's call it resetImage) to run in 2/3 seconds. Then when resetImage is called, it sets the button's image back to normal.
You'd want something like Clock.schedule_once(resetImage, 0.66).

Related

Clean way to close splashscreen in kivy after a delay

In Kivy, if you have a ScreenManager with multiple screens already added, you can not change screens with the switch_to function, as that also tries to first add the Screen to the Screenmanager, before switching to it.
Instead, you switch screens simply by setting the current property, like this:
screenmanager.current = "new_screen_name"
The problem is, I wish my SplashScreen to automatically transition to MainScreen after a short delay, using Clock.schedule_once(). But that can only take a function as a parameter, so I I have to write a another function just to change screen, like this:
class MyScreenManager(ScreenManager):
def __init__(self, **kwargs):
super(MainScreenManager, self).__init__(**kwargs)
Clock.schedule_once(switch_to_main_screen, 3)
def switch_to_main_screen(self, *args):
self.current = "main_screen
I'm just wondering if there is a more efficient way to do this? e.g can I somhow directly set the "self.current" property in Clock.schedule_once? Or, generally speaking, is there a better way to do this simple task? (i.e have a parameter be set a few seconds in the future)
You can use the setattr() python built-in. Try replacing:
Clock.schedule_once(switch_to_main_screen, 3)
with:
Clock.schedule_once(lambda dt: setattr(self, 'current', 'main_screen'), 3)
See the documentation.
Consider this, its my ready sheet in kivy:
import #what u need
Builder.load_file('the.kv')
class fscreen(Widget):
def __init__(self, **kwargs):
super().__init__(**kwargs)
class secscreen(Widget):
def __init__(self,**kwargs):
super().__init__(**kwargs)
pass
class thscreen(Widget):
def __init__(self,**kwargs):
super().__init__(**kwargs)
pass
class theapp(App):
def build(self):
self.screenm = ScreenManager()
self.fscreen = fscreen() ## as default this is my
screen = Screen(name = "first screen") # my first screen
screen.add_widget(self.fscreen) # if i want second screen
self.screenm.add_widget(screen) # as first i move this below
## secscreen its waay
self.secscreen = secscreen() ### efficient
screen = Screen(name = "secondscreen")
screen.add_widget(self.secscreen)
self.screenm.add_widget(screen)
self.thscreen = thscreen()
screen = Screen(name = "thirdscreen")
screen.add_widget(self.thscreen)
self.screenm.add_widget(screen)
return self.screenm
if __name__ == "__main__":
theapp = theapp()
theapp.run()
This way the fscreen is by default the first screen after the presplash

Kivy togglebutton only turning sound on/off once

Ive tried looking for an answer to this without much luck.
Im trying to build an application in kivy that starts and stops a sound as the button is toggled. The sound does what I want the first time the button is toggled, but the second time the button only starts the sound, but does not stop the sound.
Here is my code so far.
'''code'''
class MainApp(App):
def build(self):
layout = BoxLayout(padding=10)
self.oceanButton = ToggleButton(text='Ocean',
background_normal='C:/Users/micha/Desktop/Code/Soothing Sounds/picture/oceanpic.jpg')
self.oceanButton.bind(on_press=self.on_press_button)
layout.add_widget(self.oceanButton)
return layout
def on_press_button(self, *args):
waveSound = SoundLoader.load(
'C:/Users/micha/Desktop/Code/Soothing Sounds/sounds/ocean.wav'
)
if self.oceanButton.state == 'down':
waveSound.play()
waveSound.loop = True
print('On')
else:
waveSound.stop()
print('Off')
The problem is that your on_press_button() method always creates a new instance of Sound (using SoundLoader). So, when the ToggleButton state is not down, it calls the stop() method on that new instance, and the Sound that was created on the previous call continues to play.
You can fix that by keeping a reference to the created Sound instance, and using that instance to call stop():
def on_press_button(self, *args):
if self.oceanButton.state == 'down':
self.waveSound = SoundLoader.load(
'C:/Users/micha/Desktop/Code/Soothing Sounds/sounds/ocean.wav'
)
self.waveSound.play()
self.waveSound.loop = True
print('On')
else:
self.waveSound.stop()
print('Off')

How to only do add_widget once in Kivy

I have a dynamic Screen which is generated based on a button you clicked on another screen. Issue is dat every time I enter the Screen, the buttons are regenerated and added to the existing buttons.
The reason is that I use the on_enter method, but I don't know how I can use on_kv_post for example, as these events happen on starting the app.
How can I initialise the screen every time I return to this screen?
class ClientEnvsGrid(Screen):
envProp = StringProperty('')
def __init__(self, **kwargs):
super(ClientEnvsGrid, self).__init__(**kwargs)
def on_enter(self, *args):
clientProp = self.manager.get_screen('clientlist').clientProp
try:
client_filepath = os.path.join('clients', clientProp, "environments.json")
client_file = open(client_filepath)
clientdata = json.loads(client_file.read())
print(clientdata)
self.ids.clientlabel.text = clientdata["clientname"]
for envs in clientdata["environments"]:
print(envs["name"])
envbutton = Button(text=envs["name"])
envbutton.bind(on_press=lambda *args: self.pressed('envbtn', *args))
self.ids.environments.add_widget(envbutton)
except:
print("No client data found")
self.manager.current = 'clientlist'
def pressed(self, instance, *args):
self.envProp = args[0].text
I've managed to fix it to include clear_widgets in the environments GridLayout in the on_leave event.
def on_leave(self, *args):
self.ids.environments.clear_widgets()

TypeError: accept missing 2 required arguments (Still functional)

This is a curiosity question. I have a block of code that executes upon an accepted.connect().
It throws out this error but when I check the results they still work. And from what I understand from button box: upon pressing OK or cancel, the dialog should close on it's own. I haven't even initialized self.buttonBox.canceled.connect but when I push cancel the window closes. When I push OK though the window stays open and gives the following error:
TypeError: accept() missing 2 required positional arguments: 'player' and 'window'
So here's some code:
class UIinit(QtGui.QDialog, UI.Buy_Cargo.Ui_Dialog):
"""The Dialog for initiation"""
def __init__(self, player, window):
super(UIinit, self).__init__()
self.window = window
self.player = player
self.setupUi(self)
#for i in Config.port_prices:
# up = getattr(self, "btn_" + i + "_up")
# up.clicked.connect(partial(self.up, i, player))
# down = getattr(self, "btn_" + i + "_down")
# down.clicked.connect(partial(self.down, i))
# add_price = getattr(self, "H_" + i)
# add_price.setText(i +
# " (" + str(self.player.port.price[i]) + ")")
self.buttonBox.accepted.connect( # the important part
partial(self.accept, player, window))
def accept(self, player, window):
if int(self.V_Total.text()) <= player.money:
for i in player.ship.cargo:
num = int(getattr(self, "V_" + i).text())
player.ship.cargo[i] += num
window.to_shipyard()
dia = UIinit(player, window)
dia.exec_()
I've tried connect(lambda: self.accept(player, window)) and using self.player and self.window as the arguments.
This simplified snippets below does work as expected, so your problem is elsewhere. Just a wildguess - if you copy/pasted you code, there are tabs in it and if you have a mix of tabs and spaces you can get really weird results - like having def accept actually being defined in __init__ itself instead of being a proper method, in which case self is not automagically passed to the function. Doesn't really match your error message but that might be worth checking....
from functools import partial
class Button(object):
def __init__(self):
self.callbacks = []
def connect(self, callback):
self.callbacks.append(callback)
def click(self):
for callback in self.callbacks:
callback()
class UI(object):
"""The Dialog for initiation"""
def __init__(self, player, window):
self.window = window
self.player = player
self.button = Button()
self.button.connect( # the important part
partial(self.accept, player, window))
self.button.connect(
lambda: self.accept(player, window))
def accept(self, player, window):
print "accept %s %s" % (player, window)
def exec_(self):
self.button.click()
player = "p"
window = "w"
dia = UI(player, window)
dia.exec_()
It seems that it has to do with me overwriting the dialog's accept function. Once I changed the accept() to GoNinjaGoNinjaGo() everything worked just fine.

python non-specific argument

I have the code
class Button(object):
'''A simple Button class to represent a UI Button element'''
def __init__(self, text = "button"):
'''Create a Button and assign it a label'''
self.label = text
def press(self):
'''Simply print that the button was pressed'''
print("{0} was pressed".format(self.label))
class ToggleButton(Button):
def __init__(self, text, state=True):
super(ToggleButton, self).__init__(text)
self.state = state
def press(self):
super(ToggleButton, self).press()
self.state = not self.state
print('{0} is now'.format(self.label), 'ON' if self.state else 'OFF')
When I input
tb = ToggleButton("Test", False)
tb.press()
tb.press()
it works fine and returns
Test was pressed
Test is now ON
Test was pressed
Test is now OFF
but what I want is to have the text parameter optional, so that if I input
b = ToggleButton()
b.press()
it will return
ToggleButton was pressed
ToggleButton is now OFF
any help would be much appreciated!
Follow the example of the state parameter and give text a default value as well.
class ToggleButton(Button):
def __init__(self, text="ToggleButton", state=True):
super(ToggleButton, self).__init__(text)
self.state = state
Consider something adaptive such as this:
class ToggleButton(Button):
def __init__(self, *args, **kwargs):
super(ToggleButton, self).__init__(*args)
self.state = kwargs.get('state', True)

Categories

Resources