Updating widgets with dynamic data?

3,462 views
Skip to first unread message

Mrmessage Writer

unread,
Sep 30, 2013, 5:13:12 AM9/30/13
to npys...@googlegroups.com
I am running through all the examples, and looking through the documentations.
What I am interested in is using a form, to reflect a device's settings which are communicated via serial port.  I would do this using textfields and sliders. 
It seems that npyscreen is really meant for only editing of widgets data, from the user, and not really allowing for data to be updated externally.

If I'm wrong, does anyone have a good example of this?

Nicholas Cole

unread,
Oct 1, 2013, 4:09:59 AM10/1/13
to npys...@googlegroups.com
You can certainly use npyscreen in that way - it is one of the reason
you can set widgets to be not editable by the user.

Do you intend the user to be able to interact with any of the widgets,
or not at all?

Are you going to have one thread for the user interface and one for
the communication with the serial port?

The easiest way to achieve what you want might be to override the
while_waiting() method of a Form to update the widgets with the values
that you want to update, for example.

Have a look at the EXAMPLE-waiting.py file.

If you give me a better idea of what you want to achieve, I can be of more help.

Andy Vaught

unread,
Oct 9, 2013, 1:27:22 PM10/9/13
to npys...@googlegroups.com

The easiest way to achieve what you want might be to override the
while_waiting() method of a Form to update the widgets with the values
that you want to update, for example.

Have a look at the EXAMPLE-waiting.py file.


That's what I did.  Update the .value member, then call the display() method ...

Andy


Riku Lindblad

unread,
Feb 11, 2014, 9:20:07 AM2/11/14
to npys...@googlegroups.com

Do you intend the user to be able to interact with any of the widgets,
or not at all?

Are you going to have one thread for the user interface and one for
the communication with the serial port?

The easiest way to achieve what you want might be to override the
while_waiting() method of a Form to update the widgets with the values
that you want to update, for example.

Have a look at the EXAMPLE-waiting.py file.

If you give me a better idea of what you want to achieve, I can be of more help.

I'm having a similar issue. I want to display information retrieved from different locations on a non-editable form(s). Everything works perfectly on the first run, values are filled from the database and APIs as expected, but I can't get the values to update without quitting and restarting the program.

I can override the while_waiting() method and it is run on the correct interval (tested by adding npyscreen.notify_wait on the method) . BUT nothing on the forms is updated, everything stays as is.

What method(s) am I supposed to call in the while_waiting() method to force it to basically run the create() method again in order to update the form values?

Nicholas Cole

unread,
Feb 11, 2014, 9:55:39 AM2/11/14
to npys...@googlegroups.com
You can either call the .display() method of each widget you want to
update or you can call the .display() method of the containing form to
update all of its widgets at once.

Best wishes,

N.

Riku Lindblad

unread,
Feb 11, 2014, 12:20:55 PM2/11/14
to npys...@googlegroups.com

You can either call the .display() method of each widget you want to
update or you can call the .display() method of the containing form to
update all of its widgets at once.

Best wishes,

N.

This is a minimal example of what I attempted: https://gist.github.com/lepinkainen/8939453

Am I doing something wrong here?

The notify_wait call goes through every 5 seconds as it should and the notification is displayed. But the date stays exactly the same, as if datetime.now() is never called again after the first time.

Nicholas Cole

unread,
Feb 12, 2014, 10:40:45 AM2/12/14
to npys...@googlegroups.com
You're quite right. It is never called again. Datatime.now() just
returns a value that is passed as the value when the widget is
created. If you wanted it to update you would have to do this:

import npyscreen
from datetime import datetime

class DateForm(npyscreen.Form):
def while_waiting(self):
npyscreen.notify_wait("Update")
self.date_widget.value = datetime.now()
self.display()

def create(self):
self.date_widget = self.add(npyscreen.FixedText,
value=datetime.now(), editable=False)

class DateApp(npyscreen.NPSAppManaged):

keypress_timeout_default = 50

def onStart(self):
self.addForm("MAIN", DateForm, name="Time")

if __name__ == '__main__':
app = DateApp()
app.run()

Riku Lindblad

unread,
Feb 13, 2014, 8:52:32 AM2/13/14
to npys...@googlegroups.com
You're quite right.  It is never called again.  Datatime.now() just
returns a value that is passed as the value when the widget is
created.  If you wanted it to update you would have to do this:


That worked, thank you. I can now dynamically update TitleFixedText fields like I wanted.

Now I'm having an issue with GridColTitles. Is it possible to adjust its height value dynamically during while_waiting?

In need the GridColTitles element to increase in size (height) based on the amount of data I add to it during the while_waiting event. 

Also I'd like to adjust the column widths individually (in my case one column is substantially larger than the other two that display just numbers), but this seems to  be impossible as all the columns need to be of equal width?

Nicholas Cole

unread,
Feb 15, 2014, 9:11:45 AM2/15/14
to npys...@googlegroups.com
On Thu, Feb 13, 2014 at 1:52 PM, Riku Lindblad <riku.l...@gmail.com> wrote:
>> You're quite right. It is never called again. Datatime.now() just
>> returns a value that is passed as the value when the widget is
>> created. If you wanted it to update you would have to do this:
>>
>
> That worked, thank you. I can now dynamically update TitleFixedText fields
> like I wanted.

Great.


> Now I'm having an issue with GridColTitles. Is it possible to adjust its
> height value dynamically during while_waiting?
>
> In need the GridColTitles element to increase in size (height) based on the
> amount of data I add to it during the while_waiting event.

I'm not quite sure when you need to actually change the size of the
grid widget. What is wrong with the default behaviour?

> Also I'd like to adjust the column widths individually (in my case one
> column is substantially larger than the other two that display just
> numbers), but this seems to be impossible as all the columns need to be of
> equal width?

Yes, the current grid widget assumes columns of equal width. What do
you think the API should look like for variable width columns? If
there is enough demand, I'll see what I can do.

N.

Riku Lindblad

unread,
Feb 15, 2014, 10:27:15 AM2/15/14
to npys...@googlegroups.com
> Now I'm having an issue with GridColTitles. Is it possible to adjust its
> height value dynamically during while_waiting?
>
> In need the GridColTitles element to increase in size (height) based on the
> amount of data I add to it during the while_waiting event.

I'm not quite sure when you need to actually change the size of the
grid widget.  What is wrong with the default behaviour?

I'm building a tool that has no user input in its basic state, it just displays data it fetches from the internet and a few databases updating the screen as necessary.

In this program I have multiple grids on one page, each can contain anything from 0-30 rows (even more in extreme cases).

This is why I'd want to adjust the space the grids take up on each page. I need to completely hide the table when there is nothing to display for that particular grid and also adjust the size based on the content so it's not using any more space than it needs to.

 
> Also I'd like to adjust the column widths individually (in my case one
> column is substantially larger than the other two that display just
> numbers), but this seems to  be impossible as all the columns need to be of
> equal width?

Yes, the current grid widget assumes columns of equal width.  What do
you think the API should look like for variable width columns? If
there is enough demand, I'll see what I can do.


In my case I have a two-column gridcol, the first column is the item name the second the amount. On a 60 column wide table a 30/30 split is a bit silly when the amount is five numbers maximum and many item names get cut short because of the lack of space.

It'd be enough to have column_width take in a list of ints and use it for column widths, throw an exception if the list is of different size than the one given to col_titles.

If you want to get fancy, columns could be set as a list of (title, width) tuples and calculate the grid width from the sum of all column widths automatically.

Even fancier would be to have some of the widths specified and calculate the rest automatically; in my case I'd specify the narrower column(s) statically and give all the rest to the name column.

-R

Nicholas Cole

unread,
Feb 15, 2014, 10:34:21 AM2/15/14
to npys...@googlegroups.com
On Sat, Feb 15, 2014 at 3:27 PM, Riku Lindblad <riku.l...@gmail.com> wrote:
>> > Now I'm having an issue with GridColTitles. Is it possible to adjust its
>> > height value dynamically during while_waiting?
>> >
>> > In need the GridColTitles element to increase in size (height) based on
>> > the
>> > amount of data I add to it during the while_waiting event.
>>
>> I'm not quite sure when you need to actually change the size of the
>> grid widget. What is wrong with the default behaviour?
>
>
> I'm building a tool that has no user input in its basic state, it just
> displays data it fetches from the internet and a few databases updating the
> screen as necessary.
>
> In this program I have multiple grids on one page, each can contain anything
> from 0-30 rows (even more in extreme cases).
>
> This is why I'd want to adjust the space the grids take up on each page. I
> need to completely hide the table when there is nothing to display for that
> particular grid and also adjust the size based on the content so it's not
> using any more space than it needs to.

OK. I'm trying to think of a way I can make that work for you. You
can already hide particular widgets by setting the .hidden attribute
to True. But that doesn't help you with the bigger issue.

Resizing is a tricker problem. Especially since you could very easily
run out of space for your widgets doing this kind of dynamic layout.
It adds a huge level of complexity to the system. I'll give it some
thought.

How often are you doing the updates? If they are relatively
infrequent, you might find that you can achieve what you want by
dynamically creating a new Form completely every time you do the
search. I can see that that might not be ideal.

N.

Riku Lindblad

unread,
Feb 15, 2014, 12:02:00 PM2/15/14
to npys...@googlegroups.com
 
How often are you doing the updates?  If they are relatively
infrequent, you might find that you can achieve what you want by
dynamically creating a new Form completely every time you do the
search.  I can see that that might not be ideal.

I run the while_waiting loop every 10 seconds, but the actual background data updates only every 5-10 minutes. The only thing that I update in every while_waiting loop are counters that show the age/eta of items based on a static datetime received from the backend, but they don't require the grids to be resized, just the values need to change.

Clearing the screen and creating a whole new Form every time the data actually needs to be updated would be perfectly fine in my case. Even a slight flicker on update isn't a major issue.

My previous solution is a script with a bunch of formatted print-commands running under watch(1) every 10 minutes, so everything I'm doing with npyscreen is a big upgrade :)

-R

Nicholas Cole

unread,
Feb 15, 2014, 4:25:53 PM2/15/14
to npys...@googlegroups.com
Ok. I've got resizing widgets 90% working. The problem is making sure I don't make existing applications crash. That will take a few more days of testing.

If you are just doing a display (no user interaction), I would make a new form each time in your case.

If you want an interactive display, give me a few more days to get this working.  

Aaron Statham

unread,
Jan 4, 2016, 7:14:40 AM1/4/16
to npyscreen
Hi Nicholas - did you end up incorporating resizing widgets into npyscreen? Can you point me at an example of how to... say change the height of a MultiLineAction from 5 to 10 lines?
Thanks!

Nicholas Cole

unread,
Jan 4, 2016, 9:23:44 AM1/4/16
to npys...@googlegroups.com
Yes, they've been part of it for a while. I don't have time to write
an example today, but I'll try to get to it tomorrow.

N.
> --
> You received this message because you are subscribed to the Google Groups
> "npyscreen" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to npyscreen+...@googlegroups.com.
> To post to this group, send email to npys...@googlegroups.com.
> Visit this group at https://groups.google.com/group/npyscreen.
> For more options, visit https://groups.google.com/d/optout.
Reply all
Reply to author
Forward
0 new messages