Not able to output datetime to text view in Ui.
Phuket2 last edited by
@meleyz, I think the below should help. No need to make 2 instances of the arrow object. Also the formatting can be applied in different parts of your code, depending what makes sense for you. In your case, really you dont need the function oTime. As you did in your code you can call the method in place.
Also your calls to timecard.append(oTime) should be timecard.append(oTime()). You are calling a function, so you need to add the ().
But the timecard.append could look like
timecard.append(arrow.now().format('MMMM DD,YYYY, h:m:s a') or using a _fmt1 for example based on a variable
import arrow _fmt1 = 'MMMM DD,YYYY, h:m:s a' _fmt2 = 'MMMM DD, YYYY, HH:mm:ss A' def oTime(fmt=None): # if no fmt param supplied, return the str version of the arrow # oject, otherwise return the formatted version return arrow.now().format(fmt) if fmt else str(arrow.now()) ''' while oTime(self): return (a) else: return (b) ''' print(oTime()) print(oTime(_fmt1)) print(oTime(_fmt2))
A more complete example
import ui import arrow class MyClass(ui.View): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.lb = None self.sw = None self.fmts = ['MMMM DD,YYYY, h:m:s a', 'MMMM DD, YYYY, HH:mm:ss A'] self.make_view() self.update() self.update_interval = 1 def make_view(self): # create label lb = ui.Label(width=self.width, height=32, alignment=ui.ALIGN_CENTER) self.lb = lb self.add_subview(self.lb) # create switch sw = ui.Switch(action=self.update) sw.y = lb.frame.max_y + 10 sw.x = 10 self.sw = sw self.add_subview(sw) def update(self, sender=None): ''' int(self.sw.value) coerce False/True to 0 or 1 ''' self.lb.text = str(arrow.now().format(self.fmts[int(self.sw.value)])) if __name__ == '__main__': f = (0, 0, 300, 400) v = MyClass(frame=f, bg_color='white') v.present(style='sheet')
meleyz last edited by
Can you see any obvious reason why the switch isn’t working? I believe I have everything written right (as much as I can see anyways) and the function name is in the ui switch, yet nothing happens when I tap the switch. It only returns
b_fmt2and I can’t figure out why. I’m sure it’s something I should’ve seen by now but anyways, here is my current code.
import ui import arrow import appex # import the proper modules needed to run script timecard =  a_fmt1 = 'MMMM DD,YYYY, h:m:s a' b_fmt2 = 'MMMM DD, YYYY, HH:mm:ss A' def switch_1(fmt): while fmt: return arrow.now().format(a_fmt1) else: return arrow.now().format(b_fmt2) def clock(sender): v['textview1'].text = v['textview1'].text + 'Time ' + sender.title + ': ' + str(switch_1('')) + '\n' v = ui.load_view() v.present('sheet') # load the UI
JonB last edited by
Can you explain what you think the purpose of
If that is your switch method, fmt is the sender, not a fmt, and will always return True in a while statement. You used that pattern before, you may want to review how while works too...
Phuket2 last edited by Phuket2
@meleyz , I have some hesitation about what I am posting below. Not sure it will help or confuse you.
Because the view is not complex, this would be a lot more easily done in a Custom ui class as I did above. But you keep using the while clause. Not sure why, maybe you think that your values will get continuously updated? They wont. You could stay in a while loop in there, but normally you would not want to.
But you can see in the Custom ui.View, it has a update method. The frequency it gets called depends on the update_interval attr
import ui import arrow import appex # import the proper modules needed to run script timecard =  a_fmt1 = 'MMMM DD,YYYY, h:m:s a' b_fmt2 = 'MMMM DD, YYYY, HH:mm:ss A' def create_view(**kwargs): ''' Create a view as I dont have the pyui file ''' v = ui.View(frame=(0, 0, 0, 220), **kwargs) lb = ui.Label(name='textview1', frame=(0,0,0,v.height), flex='W', alignment = ui.ALIGN_CENTER) sw = ui.Switch(name='switch_1', action=switch_1) v.add_subview(lb) v.add_subview(sw) sw.y = lb.frame.max_y + 10 sw.x = 10 # note here v is the main view, its superview property will be None return v # the action for the switch def switch_1(sender): sv = sender.superview if sender.value: sv['textview1'].text = arrow.now().format(a_fmt1) else: sv['textview1'].text = arrow.now().format(b_fmt2) # while is a loop construct. Also, you will not get a return value. # when action method is called you need to do some assigmentsin this case. # what maybe troubling you is getting a refence to your label object in # this method. ui.Views have a property called superview. Is the object the # view has been added to (it could be None). So we can get the sender # superview and access your other views as above as each ui.View also has a # list of all its subviews. ''' while fmt: return arrow.now().format(a_fmt1) else: return arrow.now().format(b_fmt2) ''' ''' def clock(sender): v['textview1'].text = v['textview1'].text + 'Time ' + sender.title + ': ' + str(switch_1('')) + '\n' ''' #v = ui.load_view() - Create the view instead a do not have the pyui file f = (0, 0, 320, 260) v = create_view(bg_color = 'white') # call the switch action, but in this case we need the switch object also switch_1(v['switch_1']) v.present('sheet') # load the UI
meleyz last edited by
Thank you both for explaining. It has become clear that I misunderstood some of the documentation and have since spent time rereading those documents. I have the code working the way I need it to now however, I have one last question. I was getting the error
‘’str’ object has no attribute ‘superview’’until I deleted and re added the switch in the ui designer. Was that just a random bug or does that happen frequently with the ui designer? Thanks again for all the help.
JonB last edited by
That error means that you sent a string to your callback, rather than a view.
I'd bet when you were calling
It is usually helpful to look at, and paste the full traceback, to see where errors occured.
If the ui debugger pops up, you can actually look at the variables at each level of scope, and see where the problem happened, and can walk up the call chain to see where things were called. Pressing Print Traceback prints a full traceback, which is what you should always include whenever you are asking for help on the forum.
Learning to debug is a important skill, since it means you will be able to diagnose most problems without the delay of forum posting back and forth. (Thats why i was trying to ask leasing questions, rather than post a solution). If I can offer a few suggestions for effective debugging:
First, find out what line threw the exception. That's key, since if you don't know where the error is, how can you fix it. Printing the traceback will tell you this, and the sequence of function calls that got you to that point.
Next, make sure you understand what the error is telling you. AttributeErrors mean you tried to access an attribute that doesn't exist. Usually that means the object you have is not the one you expected -- for instance, when switch_1 is called with a string, instead of as ui.Switch.
Often the pythonista debugger will then let you walk up and down the stack, and examine variables in simple structures. Expand the window, then click on variables tto examine variable values. The switch to the stack view, and you can swicth to the callers scope, and look at variables in that scope, etc. The pythonista debugger is somewhat limited (cannot evaluate arbitrary expressions), but is easy to use and for every one of your problems here would have provided good insight.
As a crude, but easy and effective debugging technique, add print statements at key places in the code before your error. For instance, if you had print(fmt) in your old code, you would have noticed that you were being sent a ui.Switch, and not a boolean or string. If you are getting an AttributeError on
print(somevariable), print(type(somevariable)), and print(dir(somevariable))can help you understand what you are dealing with.
Eventually, you will want to learn how to use
pdb.pm()for debugging problems after the fact, or
pdb.settrace()for setting breakpoints. This is a slightly more advanced topic, but only sort of -- when I was learning python, after the basics, one of the first things i taught myself was the debugger!