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.
scenes updating each other’s variables
-
@cvp @JonB I have incorporated your guises recommendations into my practice code and I’m getting an error I’ve never seen and can’t figure out. I’ve listed the error and the updated code below.
Error...
TypeError: bad argument type for built-in operation
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/var/containers/Bundle/Application/F3A42D55-5CB1-4DC2-AFF5-5BE7BB053375/Pythonista3.app/Frameworks/Py3Kit.framework/pylib/site-packages/scene.py", line 216, in _touch_began
self.presented_scene._touch_began(x, y, touch_id)
File "/var/containers/Bundle/Application/F3A42D55-5CB1-4DC2-AFF5-5BE7BB053375/Pythonista3.app/Frameworks/Py3Kit.framework/pylib/site-packages/scene.py", line 226, in _touch_began
self.touch_began(touch)
File "/private/var/mobile/Library/Mobile Documents/iCloud~com~omz-software~Pythonista3/Documents/modal_practice.py", line 111, in touch_began
self.main.bankroll_amount_label.text = f'{self.main.bankroll_amount:,}',
File "/var/containers/Bundle/Application/F3A42D55-5CB1-4DC2-AFF5-5BE7BB053375/Pythonista3.app/Frameworks/Py3Kit.framework/pylib/site-packages/scene.py", line 280, in setattr
self.update_texture()
File "/var/containers/Bundle/Application/F3A42D55-5CB1-4DC2-AFF5-5BE7BB053375/Pythonista3.app/Frameworks/Py3Kit.framework/pylib/site-packages/scene.py", line 285, in update_texture
w, h = ui.measure_string(self.text, font=self.font)
SystemError: <built-in function measure_string> returned a result with an error setfrom scene import * import sound import random import math A = Action class MyScene (Scene): def setup(self): self.bankroll_amount = 0 self.text = LabelNode( 'MAIN SCREEN', ('Apple Color Emoji', 40), position= self.size/2, parent=self ) self.next_screen = LabelNode( 'Next SCREEN', ('Apple Color Emoji', 20), position= (self.size.w/2 * 0.55, self.size.h/2 * 1.33), parent=self ) self.bankroll_amount_label = LabelNode( f'{self.bankroll_amount:,}', font = ('Bodoni 72', 28), position = (self.size.w/2 * 1.79, self.size.h/2 * 1.66), color = 'gold', parent=self ) def update(self): pass def touch_began(self, touch): if touch.location in self.next_screen.frame: sc1 = Screen_1() sc1.main = self self.present_modal_scene(sc1) def touch_ended(self, touch): pass class Screen_1(Scene): def setup(self): self.bg_color = SpriteNode('plc:Grass_Block', position= (self.size/2), scale=25, parent=self) self.text_1 = LabelNode( '1st SCREEN', ('Apple Color Emoji', 40), position = (self.size.w/2 * 0.55, self.size.h/2 * 0.99), parent=self) self.next_screen_1 = LabelNode( '1st button', ('Apple Color Emoji', 20), position= (self.size.w/2 * 0.40, self.size.h/2 * 1.33), parent=self ) self.loan_amount = 0 self.loan_label = LabelNode( 'Loan Amount', ('DIN Condensed', 40), color= 'black', position = (self.size.w/2, self.size.h/2 * 1.10) ) self.loan_amount_label = LabelNode( f'${self.loan_amount}', ('Bodoni 72', 35), color= 'black', position = (self.size.w/2, self.size.h/2 * 0.85) ) self.take_loan = LabelNode( 'Take Loan', ('Avenir Next Condensed', 30), position = (self.size.w/2, self.size.h/2 * 0.55), color= 'black' ) self.inc_loan_btn = SpriteNode( 'emj:Red_Triangle_1', position= (self.size.w/2 * 1.33, self.size.h/2 * 1.25), scale=2 ) self.dec_loan_btn = SpriteNode( 'emj:Red_Triangle_2', position= (self.size.w/2 * 1.33, self.size.h/2 * 0.75), scale=2 ) self.add_child(self.loan_label) self.add_child(self.loan_amount_label) self.add_child(self.take_loan) self.add_child(self.inc_loan_btn) self.add_child(self.dec_loan_btn) def touch_began(self, touch): if touch.location in self.next_screen_1.frame: self.present_modal_scene(Screen_2()) if touch.location in self.take_loan.frame: self.main.bankroll_amount = self.loan_amount self.main.bankroll_amount_label.text = f'{self.main.bankroll_amount:,}', self.dismiss_modal_scene() #--- inc loan --- if touch.location in self.inc_loan_btn.frame: self.loan_amount += 500 self.loan_amount_label.text = f'${self.loan_amount}' if self.loan_amount >= 10_000: self.loan_amount = 10_000 self.loan_amount_label.text = f'${self.loan_amount}' #--- dec loan --- if touch.location in self.dec_loan_btn.frame: self.loan_amount -= 500 self.loan_amount_label.text = f'${self.loan_amount}' if self.loan_amount < 0: self.loan_amount = 0 self.loan_amount_label.text = f'${self.loan_amount}' def touch_ended(self, touch): pass class Screen_2(Scene): def setup(self): self.bg_color = SpriteNode('plc:Brown_Block', position= (self.size/2), scale=25, parent=self) self.text_2 = LabelNode( '2nd SCREEN', ('Apple Color Emoji', 40), position= self.size/2, parent=self) self.next_screen_2 = LabelNode( '2nd button', ('Apple Color Emoji', 20), position= (self.size.w/2 * 0.2, self.size.h/2), parent=self) def touch_began(self, touch): if touch.location in self.next_screen_2.frame: self.dismiss_modal_scene() def touch_ended(self, touch): pass main = MyScene() if __name__ == '__main__': run(main, LANDSCAPE, show_fps=False)
-
I also tried just having everything inside of one scene and basically changing scenes by adding and removing nodes. It gives me the same error for some reason.
class MyScene (Scene): def setup(self): self.bankroll_amount = 0 self.text = LabelNode( 'MAIN SCREEN', ('Apple Color Emoji', 40), position= self.size/2, parent=self ) self.next_screen = LabelNode( 'Next SCREEN', ('Apple Color Emoji', 20), position= (self.size.w/2 * 0.55, self.size.h/2 * 1.33), parent=self ) self.bankroll_amount_label = LabelNode( f'{self.bankroll_amount:,}', font = ('Bodoni 72', 28), position = (self.size.w/2 * 1.79, self.size.h/2 * 1.66), color = 'gold', parent=self ) self.bg_color_1 = SpriteNode( 'plc:Grass_Block', position= (self.size/2), scale=25, ) self.text_1 = LabelNode( '1st SCREEN', ('Apple Color Emoji', 40), position = (self.size.w/2 * 0.55, self.size.h/2 * 0.99) ) self.next_screen_1 = LabelNode( '1st button', ('Apple Color Emoji', 20), position= (self.size.w/2 * 0.40, self.size.h/2 * 1.33) ) self.loan_amount = 0 self.loan_label = LabelNode( 'Loan Amount', ('DIN Condensed', 40), color= 'black', position = (self.size.w/2, self.size.h/2 * 1.10) ) self.loan_amount_label = LabelNode( f'${self.loan_amount}', ('Bodoni 72', 35), color= 'black', position = (self.size.w/2, self.size.h/2 * 0.85) ) self.take_loan = LabelNode( 'Take Loan', ('Avenir Next Condensed', 30), position = (self.size.w/2, self.size.h/2 * 0.55), color= 'black' ) self.inc_loan_btn = SpriteNode( 'emj:Red_Triangle_1', position= (self.size.w/2 * 1.33, self.size.h/2 * 1.25), scale=2 ) self.dec_loan_btn = SpriteNode( 'emj:Red_Triangle_2', position= (self.size.w/2 * 1.33, self.size.h/2 * 0.75), scale=2 ) def update(self): pass def touch_began(self, touch): if touch.location in self.next_screen.frame: self.text.remove_from_parent() self.next_screen.remove_from_parent() self.bankroll_amount_label.remove_from_parent() self.add_child(self.loan_label) self.add_child(self.loan_amount_label) self.add_child(self.take_loan) self.add_child(self.inc_loan_btn) self.add_child(self.dec_loan_btn) if touch.location in self.next_screen_1.frame: pass if touch.location in self.take_loan.frame: self.add_child(self.text) self.add_child(self.next_screen) self.add_child(self.bankroll_amount_label) self.bankroll_amount = self.loan_amount self.bankroll_amount_label.text = f'{self.bankroll_amount:,}', #--- inc loan --- if touch.location in self.inc_loan_btn.frame: self.loan_amount += 500 self.loan_amount_label.text = f'${self.loan_amount}' if self.loan_amount >= 10_000: self.loan_amount = 10_000 self.loan_amount_label.text = f'${self.loan_amount}' #--- dec loan --- if touch.location in self.dec_loan_btn.frame: self.loan_amount -= 500 self.loan_amount_label.text = f'${self.loan_amount}' if self.loan_amount < 0: self.loan_amount = 0 self.loan_amount_label.text = f'${self.loan_amount}' def touch_ended(self, touch): pass if __name__ == '__main__': run(MyScene(), LANDSCAPE, show_fps=False)
-
@resserone13 remove the comma at end of line
self.main.bankroll_amount_label.text = f'{self.main.bankroll_amount:,}',
-
I was able to figure out why I was getting the error. There was an extra comma on the end of this line. I have it working both ways now with individual scenes and with everything in one scene and you just remove notes on and off to make the scenes.
self.bankroll_amount_label.text = f'{self.bankroll_amount:,}'
-
We cross our posts 😂
-
@cvp thank you. I just figured it out. Such a little thing.
-
@cvp hahah. We did. At first I was having trouble with the multiple scenes but now I see a bit more of how I can work it both ways. I’m writing a card game to learn more coding. I’m gonna post it soon on GitHub. Hopefully in the next few days. I would sure like to hear what everyone thinks. I’m sure it will be interesting interesting. I wrote it with very few functions. Once I post it I would like to work on converting the code to more of an oop approach.
-
Thanks so much. I’ve got it working and it feels awesome.
-
@cvp said:
@resserone13 what @JonB advices is
def touch_began(self, touch): if touch.location in self.next_screen.frame: self.present_modal_scene(Screen_1()) | | | V def touch_began(self, touch): if touch.location in self.next_screen.frame: sc1 = Screen_1() sc1.main_scene = self self.present_modal_scene(sc1)
How would this work if a modal scene is presenting another modal scene on top of the main. I would like the 3rd scene (which is the 2nd modal scene on top of the main seven) to update a variable on the main scene. I’m sorry to ask but I’ve been rearranging the scenes and variables all day. I’ve also tried to do this when I first asked the question a while ago and can’t forgive it out.
-
@resserone13 said:
How would this work if a modal scene is presenting another modal scene on top of the main
I never use scene thus I'll let real specialists answer...
-
-
@resserone13 you could try, without promising it will work
try: # if current scene modal of main self.main_scene.bankroll_amount = ... except: # if current scene modal of modal of main self.main_scene.main_scene.bankroll_amount = ...
-
@cvp I’ll see if I can work this out. Thanks. I was think of some thing like.
If self.presented_scene() then. Such and such will happen but I haven’t try that too much. Main been re arranging the scenes and variables. I’ll let you know.
-
@cvp I’ve got it to work by passing the variables from screen to screen. I have the 3rd screen update the 2nd screen and then the 2nd screen updates the 1st screen.
-
@resserone13 yes, sorry, I was just busy to try but what I had proposed is not good, forget it
-
@resserone13 perhaps a global could be sufficient
-
@cvp I think I had trouble with globals once it gets into if statements and using them inside functions. I’ve noticed if you have self before everything you can use it anywhere in the class. I still have trouble with little things. I still have trouble making functions that I can use in multiple classes. I have to rewrite the function and all the scenes.
-
@resserone13 There are often several solutions to a problem even if one could be the best in a Python way, but if you are more comfortable with another one, why not, we are in free countries...
Anyway, you could post your code and perhaps @ccc or @mikael (and I'm sure, a lot of other guys) could have a look and give some professional advices, what I can't do, my Python code is rarely nice. -
@cvp Yeah you’re right. It doesn’t matter how I get it done as long as it gets done. There’s no rules. There’s just guidelines.
-
@resserone13 globals are easier to work with in scene, as long as you are careful with your naming so nothing else uses the same name, and can create the scenes before hand. if you are creating scenes in response to buttons, maybe not.
otherwise, the cleaner approach is to use attributes.
That is, within a method in your main_scene, you can do something like
self.modal_scene1 = reference_to_your_modalscene self.modal_scene1.main_scene = self
but then of course, within your modal scene, you have to refer back to your main scene through the global, or through an attribute as shiwn above, so, if you are in a modal scene method:
self.main_scene
If you need to have multiple modal scenes that refer to each other, they can all interact back through main_scene, e.g.
self.main_scene.modal_scene1
As cvp said, if you want more specific help, post your code, and/or whatever traceback you are getting.