Welcome!
This is the community forum for my apps Pythonista and Editorial.
For individual support questions, you can also send an email. If you have a very short question or just want to say hello — I'm @olemoritz on Twitter.
Basic Pythonista Scene Button?
-
Hi, I was trying to make a basic button in the middle of a blank black screen, which did something when touched.
I’d like to make it play a sound when the button is touched, but nothing happens.
Any help with this would be greatly appreciated, thanks!
Here’s a link to my code: here - hope this link works
-
Update: I’ve finally got the button to work!
Basically the issue was, that the touches can only be used on the scene level, so the indentation of the touch functions matter a lot.
The working code is here! :)
-
These links make me nervous from a security perspective so I created the following snippet...
from urllib.parse import unquote text = """pythonista3://?exec=from%20scene%20import%20*%0Aimport%20ui%0Aimport%20sound%0Aimport%20os%0A%0Ax,y%20%3D%20get_screen_size%28%29%0A%0Abutton_font%20%3D%20%28%27Avenir%20Next%27,%2020%29%0A%0A%0Aclass%20ButtonNode%20%28SpriteNode%29:%0A%09def%20__init__%28self,%20title,%20args,%20kwargs%29:%0A%09%09SpriteNode.init%28self,%20%27pzl:Button1%27,%20args,%20**kwargs%29%0A%09%09button_font%20%3D%20%28%27Avenir%20Next%27,%2020%29%0A%09%09self.title_label%20%3D%20LabelNode%28title,%20font%3Dbutton_font,%20color%3D%27black%27,%20position%3D%280,1%29,%20parent%3Dself%29%0A%09%09self.title%20%3D%20title%0A%0Aclass%20button_scene%28Scene%29:%0A%09def%20setup%28self%29:%0A%09%09self.background_color%20%3D%20%27black%27%0A%09%09self.btn%20%3D%20ButtonNode%28%27dnndjdjdj%27%29%0A%09%09self.btn.position%20%3D%20%28x/2,y/2%29%0A%09%09self.add_child%28self.btn%29%0A%0A%09def%20touch_began%28self,%20touch%29:%0A%09%09self.handle_touch%28touch%29%0A%0A%09def%20touch_moved%28self,%20touch%29:%0A%09%09pass%0A%0A%09def%20touch_ended%28self,%20touch%29:%0A%09%09pass%0A%0A%09def%20handle_touch%28self,%20touch%29:%0A%09%09if%20touch.location%20in%20self.btn.frame:%0A%09%09%09sound.play_effect%28%278ve:8ve-tap-percussive%27%29%0A%0Aif%20__name__%20%3D%3D%20%27__main__%27:%0A%09run%28button_scene%28%29,%20orientation%3DLANDSCAPE,%20frame_interval%3D1,%20anti_alias%3DFalse,%20show_fps%3DTrue,%20multi_touch%3DTrue%29%0A""" print(unquote(text))
Which generates for the text of the second URL above:
pythonista3://?exec=from scene import * import ui import sound import os x,y = get_screen_size() button_font = ('Avenir Next', 20) class ButtonNode (SpriteNode): def __init__(self, title, args, kwargs): SpriteNode.init(self, 'pzl:Button1', args, **kwargs) button_font = ('Avenir Next', 20) self.title_label = LabelNode(title, font=button_font, color='black', position=(0,1), parent=self) self.title = title class button_scene(Scene): def setup(self): self.background_color = 'black' self.btn = ButtonNode('dnndjdjdj') self.btn.position = (x/2,y/2) self.add_child(self.btn) def touch_began(self, touch): self.handle_touch(touch) def touch_moved(self, touch): pass def touch_ended(self, touch): pass def handle_touch(self, touch): if touch.location in self.btn.frame: sound.play_effect('8ve:8ve-tap-percussive') if __name__ == '__main__': run(button_scene(), orientation=LANDSCAPE, frame_interval=1, anti_alias=False, show_fps=True, multi_touch=True)
This appears to be safe to me but could the text of one of these URLs be modified to do something far more dangerous?
-
@ccc, you’re right, this is pretty scary. Any way to whitelist what Pythonista will execute with a URL?
-
@Vile, if you are going to have a lot of buttons or similar, just a reminder that you can include components from the ui module in a scene.
-
The pythonista3 executable urls let you review the code before it executes, or gives you an option iirc to save without executing..
So reasonably safe.
-
@JonB options are cancel or run, not save but, of course, you could always copy/paste the listed code.
-
@ccc lol I’m too noob to be a hacker and do weird stuff to URLs so don’t worry (although this is probably what a hacker would say) XD
-
@mikael, could you give an example of using the ui module to make 4 buttons, which each play a different sound, in 4 different corners of the screen?
Rather than making a canvas, I’d like to use the size of the screen: x/4,y/4 to position the bottom left button, for example, and x/4,y/4*3 for the top left, etc, because I don’t want to have to make custom adjustments for different device screen sizes and ratios.
-
you can use flex to keep the buttons sized properly for different devices.
-
@JonB, thanks for the example!
However, I plan on using the buttons in a game, and I don’t think that the ui module is good for that.
This is because in all the ui examples I’ve seen, there’s an annoying white bar at the top of the screen with an X on it.
In contrast, when I set a background colour in the scene module, it looks neat and covers the whole screen.
Is there a way of getting rid of the white thing when using the ui module? I don’t think it’s artistically appropriate for games.
-
View.present(hide_title_bar=True)
-
@Vile, you can very well make a game using either ui or scene module, hide extra bars etc. To me ui module works better, but scene does have more game-like mechanics (e.g. better out-of-the-box support for animations).
As an example of combining the two worlds:
import scene import ui import sound class MyScene (scene.Scene): def setup(self): self.ship = scene.SpriteNode('spc:PlayerShip1Orange') self.ship.position = self.size / 2 self.add_child(self.ship) btn = ui.Button( title='Make sound', tint_color='white', background_color='blue', action=self.make_sound ) frm = btn.frame bnds = self.view.bounds btn.frame = frm.inset(-8,-8) btn.frame = ( bnds.width - btn.width - 8, bnds.height - btn.height - 8, btn.width, btn.height ) btn.flex = 'RTBL' self.view.add_subview(btn) def make_sound(self, sender): sound.play_effect('arcade:Laser_1') scene.run(MyScene())