New to npyscreen, and really excited. Looking for advice on how to get the GUI into three sections

751 views
Skip to first unread message

Jeremy P

unread,
Mar 25, 2017, 2:48:14 AM3/25/17
to npyscreen
Hi, 

Im working a little command line diff app that lets you edit the final results before saving it out. I think npyscreen is definitely the way to go, it really looks elegant.

I have all of the backend logic done, and what I kind of envisioned is being able to open two files side by side on the top half of the screen, and when they are merged, the output will be on the bottom half of the screen and be editable before saving it out.  I have been concentrating on setting it up using npyscreen.NPSAppManaged and I have a menu that I plan to use to open the files, and fire off other functionality.
I figured out how to convert my lists of strings into a string and get it into the MultiLineEdit , and I can manage to get widgets onto the main form, but I was looking for a way to create a divide between the left and right side of the Form on only the top half, where the contents of file A and file B would be shown. I was able to get the SplitForm to work, but didn't see anything to split the screen vertically. Basically this is how I was approaching it.


class FormObject(npyscreen.ActionForm, npyscreen.FormWithMenus):
    def create(self):

    '''All of my widgets, Menu additions, and defs for button presses were in this class here
        But its kind of messy because im trying all sorts of stuff and have no idea what im doing
         and embarrassed to show it here :)'''


class EasyDiffApplication(npyscreen.NPSAppManaged):
    def onStart(self):
        self.addForm('MAIN', FormObject, name = 'Easy Diff')

if __name__ == '__main__':

    myApp = EasyDiffApplication()
    myApp.run()

I believe a good way to do it may be to use two identical sized boxed for the left and right side, and one larger box on the lower half perhaps, and then put my widgets in each of those boxes. I tried doing something with BasicBox, and I could get it to show up in the Main Form, but I was not able to get any widgets to show up in it. I have a feeling I am not supposed to use it like this?  I also attempted to create another class that inherits npyscreen.ActionForm and tried to add that to the main form without success. 

My question is, what is the appropriate way to get the Main Form divided visually in to three sections? Do I create separate classes of Forms with their own widgets added and somehow overlay that on the main form with positioning? Is that even possible? Or is there some other type of way to kind of containerize the three sections visually and everything is still written in the MAIN Form?

I see something similar to what I think I want to do in the Doga app https://raw.githubusercontent.com/pravj/Doga/master/docs/Doga.png , but I see they are using self.window.add(npyscreen.BoxTitle, name="Alert History", max_width=75, relx=52, rely=7), but their main Class inherits from class WindowForm(npyscreen.ActionForm): and they are not using NPSAppManaged. 

The way I have it so far, window.add does not seem to be available for me to use in my MAIN form.

Just hoping for advice on the best route to pursue,
Thanks in advance for any advice someone can give, 
Jeremy  


Nicholas Cole

unread,
Mar 25, 2017, 7:13:18 AM3/25/17
to npys...@googlegroups.com
Jeremy,

I'm so glad that you think npyscreen might be useful for what you need.

As a simplification npyscreen does not really have the concept of a
generic container widget. However, it is possible to create compound
widgets (such as the box class, and in fact all of the titled
classes), as you've seen. But as you describe your problem I would
adopt the approach used by the existing split screen Form. Place the
widgets on the screen using relx and rely in the places that you need
them, and draw a vertical line between them. If you follow the
example of that existing class, you'll see what you need to do to make
sure that everything is resized when the terminal changes size and
shape.

Does that help?

Nichlas
> --
> 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.

Jeremy P

unread,
Mar 26, 2017, 12:11:51 AM3/26/17
to npyscreen
Nicholas,

Thanks for such a fast response. That helps a lot actually. I will inherit also from Split Screen and then try to add in the vertical line.
Hopefully one day I will  figure out how to create compound classes and do something like what I see in the Doga app. 
But yes, pointing me in the right direction is what I needed, so I can work toward something that would be considered possible and sane.
Ill keep you posted,

Thanks again.

Jeremy

Jeremy P

unread,
Mar 27, 2017, 4:01:19 PM3/27/17
to npyscreen
Nicholas,

I had some time to work on it today and I had a lot of fun. I found the SplitForm class and decided to copy it and override your methods to add the vertical line.  I think perhaps I could have used super()  in a bunch of places so I didn't have to rewrite everything? I changed the variable names to differentiate between horizontal and vertical also. I thought about just getting my half way points from MAXX and MAXY,  but im not sure when or how often draw_form() gets called.  Actually, where does draw_form() even get called?  I assume after it notices a resize, but I dont see a reference to draw_form in resize()  either. 

Overall, It is working and looks great, AND doing it this way gives me the most screen real-estate which is nice. 

If I did something taboo by doing it my way, id be happy to fix it if you have any suggestions. 

Now to figure out how I want to merge the logic side of things. I like how in the Database example you give,  The forms and the instance of your database are  created in class AddressBookApplication(npyscreen.NPSAppManaged):, and then through some ninja skills you are able to reference all the classes and get them to work together, but I dont really see how you did that yet:).  So ill stick it all together in one class for now or something. 

Thanks again.


class MySplitForm(npyscreen.SplitForm):
MOVE_LINE_ON_RESIZE = True
''' Inherits and overrides methods from Nicholas Cole's npyscreen, to add a vertical line'''
"""Just the same as the Title Form, but with a horizontal line"""

def __init__(self, draw_horline_at=None, draw_vertline_at=None, *args, **keywords):
super(MySplitForm, self).__init__(*args, **keywords)
if not hasattr(self, 'draw_horline_at'):
if draw_horline_at != None:
self.draw_horline_at = draw_horline_at
else:
self.draw_horline_at = self.get_horizontal_half_way()
if draw_vertline_at != None:
self.draw_vertline_at = draw_vertline_at
else:
self.draw_vertline_at = self.get_vertical_half_way()

def draw_form(self, ):
MAXY, MAXX = self.curses_pad.getmaxyx()
super(MySplitForm, self).draw_form()
self.curses_pad.hline(self.draw_horline_at, 1, curses.ACS_HLINE, MAXX - 2)
self.curses_pad.vline(1, self.draw_vertline_at, curses.ACS_VLINE, self.draw_horline_at - 1)

def get_horizontal_half_way(self):
return self.curses_pad.getmaxyx()[0] // 2

def get_vertical_half_way(self):
return self.curses_pad.getmaxyx()[1] // 2

def resize(self):
super(MySplitForm, self).resize()
if self.MOVE_LINE_ON_RESIZE:
self.draw_horline_at = self.get_horizontal_half_way()
self.draw_vertline_at = self.get_vertical_half_way()

On Saturday, March 25, 2017 at 7:13:18 AM UTC-4, Nicholas Cole wrote:
Reply all
Reply to author
Forward
0 new messages