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.
Label not updating
-
Hello, I need a little help here. I can’t figure out why my label isn’t updating. Essentially, I create a label that has a number value. That works fine. But, with a button push I bring up a modal scene and press another button. This option then dismisses the modal scene, the value that is displayed in the LabelNode is updating in value because it is written to another file, but the value that is being displayed isn’t updating to the new value. I’ll try to copy and paste the functions that I think are the most important.
First, here is the LabelNode created in the setup() for the Scene:
mad_spend_label = str(self.maddex_accounts[7]) self.Maddex_spending_amount = LabelNode(mad_spend_label, font=menu_button_font, color='black', position=(-(self.menu_bg.size.w/3), self.menu_bg.size.h/2 - 160), parent=self.menu_bg)
This is the function that is called when said button is pushed:
def run_weekly(self): self.paused = True self.run_weekly_scene = BudgetClasses.WeeklySubMenuScene("Weekly Payout", "Who gets paid?",["Both", "Maddex", "Ryker", "Back"]) self.present_modal_scene(self.run_weekly_scene) self.run_weekly_scene = None self.update_labels()
Here is a function I created trying to get it to display the correct value:
def update_labels(self): self.maddex_accounts, self.ryker_accounts = BudgetClasses.TransMethod.get_budget_values() self.Maddex_spending_amount.text = str(self.maddex_accounts[7]) self.Maddex_savings_amount.text = str(self.maddex_accounts[8]) self.Maddex_tithing_amount.text = str(self.maddex_accounts[9]) self.Ryker_spending_amount.text = str(self.ryker_accounts[7]) self.Ryker_savings_amount.text = str(self.ryker_accounts[8]) self.Ryker_tithing_amount.text = str(self.ryker_accounts[9])
Here is the function that is called from the WeeklySubMenuScene that is presented:
def weekly_both(self): #[0 kid, 1 ID, 2 date, 3 desc, 4 begin_spend, 5 begin_save, 6 begin_tithe, 7 end_spend, 8 end_save, 9 end_tithe] maddex_accounts, ryker_accounts = TransMethod.get_budget_values() new_mad_accounts = self.apply_weekly(maddex_accounts) new_ryk_accounts = self.apply_weekly(ryker_accounts) TransMethod.send_mad_trans(new_mad_accounts) TransMethod.send_ryker_trans(new_ryk_accounts) self.dismiss_modal_scene() self.paused = False
So, when that function is run it is successful because the updated values are written to a separate file, but that updated value wont display. If I close the program and then start it again then it displays the updated value that is retrieved from the separate file. I’d like for the value of that LabelNode to update! Any help would be appreciated.
-
@timjhinton It is very difficult to help you because your code has lost its indentation.
If you want to insert code in your post, please use special button
</>
-
@cvp I had the same problem, thanks
-
@cvp Ahh gotcha. I can do that. Here they are:
mad_spend_label = str(self.maddex_accounts[7]) self.Maddex_spending_amount = LabelNode(mad_spend_label, font=menu_button_font, color='black', position=(-(self.menu_bg.size.w/3), self.menu_bg.size.h/2 - 160), parent=self.menu_bg) self.account_values.append(self.Maddex_spending_amount) def run_weekly(self): self.paused = True self.run_weekly_scene = BudgetClasses.WeeklySubMenuScene("Weekly Payout", "Who gets paid?",["Both", "Maddex", "Ryker", "Back"]) self.present_modal_scene(self.run_weekly_scene) self.run_weekly_scene = None self.update_labels() def weekly_both(self): #[0 kid, 1 ID, 2 date, 3 desc, 4 begin_spend, 5 begin_save, 6 begin_tithe, 7 end_spend, 8 end_save, 9 end_tithe] maddex_accounts, ryker_accounts = TransMethod.get_budget_values() new_mad_accounts = self.apply_weekly(maddex_accounts) new_ryk_accounts = self.apply_weekly(ryker_accounts) TransMethod.send_mad_trans(new_mad_accounts) TransMethod.send_ryker_trans(new_ryk_accounts) self.dismiss_modal_scene() self.paused = False
I even tried to manually update it with this function:
def update_labels(self): self.maddex_accounts, self.ryker_accounts = BudgetClasses.TransMethod.get_budget_values() self.Maddex_spending_amount.text = str(self.maddex_accounts[7]) self.Maddex_savings_amount.text = str(self.maddex_accounts[8]) self.Maddex_tithing_amount.text = str(self.maddex_accounts[9]) self.Ryker_spending_amount.text = str(self.ryker_accounts[7]) self.Ryker_savings_amount.text = str(self.ryker_accounts[8]) self.Ryker_tithing_amount.text = str(self.ryker_accounts[9])
Does that help?
-
@cvp Well, that didn’t work how I hoped. So for the update_labels() and the other function that didn’t get quoted right there is really no indention. All of the code inside of the function definition is at the same indention.
def update_labels(self): self.maddex_accounts, self.ryker_accounts = BudgetClasses.TransMethod.get_budget_values() self.Maddex_spending_amount.text = str(self.maddex_accounts[7]) self.Maddex_savings_amount.text = str(self.maddex_accounts[8]) self.Maddex_tithing_amount.text = str(self.maddex_accounts[9]) self.Ryker_spending_amount.text = str(self.ryker_accounts[7]) self.Ryker_savings_amount.text = str(self.ryker_accounts[8]) self.Ryker_tithing_amount.text = str(self.ryker_accounts[9])
Like so. I think that clears it all up?
-
@timjhinton if you edit your post or another forum user quotes your post, we can see that the end triple back quotes stays at the end of the posted code. You have to put it at the begin of next line, by typing an enter where I've put the red arrow
So it becomes
-
@timjhinton For me, it is almost impossible to understand your problem. Without the full code, it is very difficult to help you. Perhaps somebody else could help you in a better way. Sincerely sorry and ready to help. more if you provide the entire code
-
@cvp Hmm I’m not exactly sure how to explain it differently. Simply put, I am creating a label and setting the value to a variable. When I update the value of that variable, the label is not updating. If I close out the program and open it back up then it displays the new, correct value.
I wonder if the issue is happening because I have it presenting a sub menu scene where the button is that calls the function that updates values and then I dismiss that scene. This is when I expect the label value to update.
Anyways, I’d be happy to send you the code via email or something for you to take a look?
-
@timjhinton said
Anyways, I’d be happy to send you the code via email or something for you to take a look?
Never a private mail in the forum.
Thus, if you could post the code in Github or another web site. -
@timjhinton a few key points which will probably let you understand better what is happening:
- button actions functions must return, before anything is displayed on the screen. That is because button actions are called in the main thread, and the UI, touch handling, etc all stops until your action returns.
- present_modal_scene is NON Blocking. This isn't necessarily obvious from the docs, and often when one thinks of a modal dialogue, you think of something that waits until the dialogue is closed before proceeding.
Since it returns immediately, your update label function gets called immediately, before you have pressed the button in your modal scene
The way to handle this sort of thing is via a completion handler function, which is defined in your main scene, but the modal scene is responsible for calling when it is done. So you would set my_modal_scene.completion = self.update_labels (or, a local function that does whatever other cleanup needs to happen, unpaying your scene ,etc) then in your button handling method in your modal scene, you would call self.completion().
def update_weekly(self): self.paused = True self.run_weekly_scene = BudgetClasses.WeeklySubMenuScene("Weekly Payout", "Who gets paid?",["Both", "Maddex", "Ryker", "Back"]) def completion(): self.run_weekly_scene = None self.update_labels() self.pause = False self.present_modal_scene(self.run_weekly_scene) # weekly_scene must call completion on close or button press
You could also block waiting for the scene to close by using a threading.Lock, but then you need to make sure that your button action is decorated with in_background, so that the action returns immediately (in_background schedules the action on the background thread, exiting the main thread immediately). But this pattern can lead to unexpected behavior, since the background thread is shared sometimes, and you have to be careful to only ever use ont thing at a time on it. You can create your own threading.Thread, but that is more complicated. The "completion handler callback" shown above is thread safe and easy (which is why a lot of apple frameworks use that pattern as well). You just have to handle the "cleanup" code in a the completion handler, rather than after the call to present_modal_scene, and it will be called later by the modal scene.
-
@timjhinton following @JonB advice, could you try to only change your program by preceding button action function with
@ui.in_background
@ui.in_background def run_weekly(self): self.paused = True self.run_weekly_scene = BudgetClasses.WeeklySubMenuScene("Weekly Payout", "Who gets paid?",["Both", "Maddex", "Ryker", "Back"]) self.present_modal_scene(self.run_weekly_scene) self.run_weekly_scene = None self.update_labels()