urwid in use

Code-Stücke können hier veröffentlicht werden.
Antworten
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

Dienstag 14. März 2006, 14:56

Modelnine hat mich auf urwid gestossen, einer Library zum Erstellen von Konsolen-UIs. Damit laesst es sich wirklich prima arbeiten. :) Was mir allerdings noch fehlt, sind Rahmen aus duennen Linien. Mmh. :roll:

Ich habe eine Klasse zusammengebastelt, die ein Dialogfenster (Text + Eingabefeld (optional) + Buttons) ueber ein anderes Widget zeichnet.

Code: Alles auswählen

class Dialog(urwid.WidgetWrap):
    """
    Creates a BoxWidget that displays a message, an edit field (optionally)
    and some buttons on top of another BoxWidget.

    Attributes:

    b_pressed -- Contains the label of the last button pressed or None if no
                 button has been pressed.
    edit_text -- After a button is pressed, this contains the text the user
                 has entered in the edit field
    """
    
    b_pressed = None;
    edit_text = None;

    _blank = urwid.Text("");
    _edit_widget = None;

    def __init__(self, msg, buttons, attr, height, width, body, edit=None,
                 edit_text=""):
        """
        msg -- content of the message widget, one of:
                   plain string -- string is displayed
                   (attr, markup2) -- markup2 is given attribute attr
                   [markupA, markupB, ... ] -- list items joined together
        buttons -- a list of strings with the button labels
        attr -- a tuple (background, button, active_button) of attributes
        height -- height of the message widget
        width -- width of the message widget
        body -- widget displayed beneath the message widget
        edit -- If \"Text\" or \"Int\", a corresponding edit widget will be
                displayed under the message, Otherwise, the edit widget will be
                omitted.
        edit_text -- default value to be edited
        """

        #Text widget containing the message:
        msg_widget = urwid.Padding(urwid.Text(msg), 'center', width - 4);

        #GridFlow widget containing all the buttons:
        button_widgets = [];

        for button in buttons:
            button_widgets.append(urwid.AttrWrap(
                urwid.Button(button, self._action), attr[1], attr[2]));

        button_grid = urwid.GridFlow(button_widgets, 12, 2, 1, 'center');

        #Combine message widget, button widget and (possibly) edit widget:
        if edit == "Text": #with text edit
            self._edit_widget = urwid.Edit("", edit_text);
            edit_pad = urwid.Padding(urwid.AttrWrap(
                self._edit_widget, attr[1], attr[2]), 'center', width - 4);
            widget_list = [msg_widget, self._blank, edit_pad, self._blank,
                           button_grid];
                        
        elif edit == "Int": #with integer edit
            self._edit_widget = urwid.IntEdit("", edit_text);
            edit_pad = urwid.Padding(urwid.AttrWrap(
                self._edit_widget, attr[1], attr[2]), 'center', width - 4);
            widget_list = [msg_widget, self._blank, edit_pad, self._blank,
                           button_grid];
            
        else: #plain message without edit widget:
            widget_list = [msg_widget, self._blank, button_grid];

            
        combined = urwid.AttrWrap(urwid.Filler(urwid.Pile(widget_list, 2)),
                                  attr[0]);

        #Place the dialog widget on top of body:
        overlay = urwid.Overlay(combined, body, 'center', width,
                                'middle', height);
       
        urwid.WidgetWrap.__init__(self, overlay);


    def _action(self, button):
        """
        Function called when a button is pressed.
        Should not be called manually.
        """
        
        self.b_pressed = button.get_label();
        if self._edit_widget:
            self.edit_text = self._edit_widget.get_edit_text();
Anwenden tut man's zum Beispiel so:

Code: Alles auswählen

display = urwid.Filler(...);
dim = ...;

input_dialog = Dialog("Input something:", ["OK", "Cancel"],
	      ('menu', 'bg', 'bgff'), 7, 30, display,
	      "Text", "Hello World!");

while True:
	ui.draw_screen(dim, input_dialog.render(dim, True));
	keys = ui.get_input();
	if "window resize" in keys:
	    dim = ui.get_cols_rows();
	for k in keys:
	    input_dialog.keypress(dim, k);

	if input_dialog.b_pressed == "OK":
	    text = input_dialog.edit_text;
	    break;

	if input_dialog.b_pressed == "Cancel":
	    break;
Vielleicht hat ja jemand Verwendung dafuer.

P.S.: Ich weiss, die Semikolons... Hey, ich sollte mir en Skript schreiben, das Dateien mit Semikolons umwandelt in solche ohne Semikolons. Oder noch besser, eine Emacs-Funktion... :D

Edit: Fehler im Docstring beseitigt
modelnine
User
Beiträge: 670
Registriert: Sonntag 15. Januar 2006, 18:42
Wohnort: Celle
Kontaktdaten:

Mittwoch 15. März 2006, 00:18

Nur, damit ich hier keine Lorbeeren einheimse die mir nicht zustehen: jemand anderes hat mich auf urwid aufmerksam gemacht; ich habs nur weitergegeben. ;-)

Und benutz es mittlerweilen auch selbst. :-)
--- Heiko.
Antworten