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.
Should UI actions run in the background by default?
Gerzer last edited by
How about implementing a warning outputted to the console when a UI action is executed on the main thread, explaining how to fix the problem, kind of like the warning you get when a UI element can’t find its assigned action? The warning would presumably not be an error, as that would break a lot of existing code not using
My biggest "ask" is being able to call ui.input_alert in an action. Maybe I'm doing it wrong, but I've had to resort to building my own custom view to get input during an action.
omz last edited by
Does this work for you?
import ui import console @ui.in_background def action(sender): s = console.input_alert('Test') sender.title = s v = ui.Button() v.title = 'Tap me' v.action = action v.frame = (0, 0, 200, 200) v.present('sheet')
Yes, but I mispoke. I meant to be able to do that as part of a "did_select" method of a tableview, not an action. Still doable?
omz last edited by
This should work, if I understood you correctly:
import ui import console class MyDataSource (ui.ListDataSource): @ui.in_background def tableview_did_select(self, tv, section, row): s = console.input_alert('Test') self.items[row] = s tv = ui.TableView() tv.frame = (0, 0, 400, 400) lds = MyDataSource(['foo', 'bar', 'baz']) tv.data_source = lds tv.delegate = lds tv.present('sheet')
I need to rework some things as I thought from the docs that you could only inherit from ui.View. I inherit from
objectand a mixin class. Under those circumstances, the ui loop freezes and it only displays the input alert when the view is closed (with the upper left hand corner X). I presume I can override some of the default delegate and data_source UI.ListDataSource methods without doing any real damage?
It does work. But only with the parent class as ui.ListDataSource. Then you need to remember to call the parent class's
__init__method to initialize some ui stuff as in:
class Capos(ui.ListDataSource,viewTools): # viewTools is a "mixin" class. def __init__(self,items): super(Capos,self).__init__(items) . . etc .
Thanks, will simplify my interface. Got to finish current major update first.
JonB last edited by
There are some actions, usually involving changing some ui state, where I seem to recall
in_backgroundcauses unexpected results. I can't think of a specific example... While it is true that
in_backgrounddoes help avoid many ui crashes I share the concern that we will now have to learn the proper threadsafe practices.
mteep last edited by
Like JonB, I have also experienced problems modifying UI state from an
@in_backgroundaction. Similarly from any other threads, such as in
ui.delayed functions or in callbacks from the
cbmodule in the 1.6 beta. I think it happened when trying to append text to a
TextView. But this is somewhat expected, since the underlying UIKit, like many other GUI toolkits, requires that most of its methods are called from the UI thread. So I believe something like the
@in_foregrounddecorator dgelessus suggested is really needed already with the current model. (Unless I have misunderstood something.)
I would try this first, coupled with another decorator to use dispatch queues since, as you hinted,
@in_backgroundfunctions seems to be blocked by
View.wait_modal(). Then, we could experiment with your idea without breaking anything.
But I suspect that using a serial queue (or a single thread) to process all actions would just cause it to block further actions from say a dialog. A better approach might be to do like AppKit and presumably UIKit, and run the event loop within the dialog presenting function, if called from the UI thread. Similar with
View.wait_modal(). Or wouldn't that work?
kollivier last edited by
As someone who's been programming for over 15 years, I've found that I agree with the Zen of Python here that usually explicit is better than implicit. Also, in my experience, when faced with an issue like this, the best overall results are gained by trying to help the programmer to understand exactly what the code is doing rather than hide those details away. I know it's common that beginner programmers want to avoid getting caught up in the gory details, but when they eventually do hit problems that knowledge really helps them find the cause and fix it.
Is running in the background important for most actions, or just a few special (but common) scenarios, like triggering a dialog? I've coded in a few different GUI toolkits, and usually event handlers are run on the main thread. Modal dialogs blocking the app is, in other toolkits, expected behavior, as often in those cases you need a response from the user before the app can continue. If you don't want that behavior there is usually a separate option for showing dialogs non-blocking, where you send in a dialog finished callback function or a delegate.