⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tutorial.html

📁 Urwid is a Python library for making text console applications. It has many features including fluid
💻 HTML
📖 第 1 页 / 共 4 页
字号:
<a href="reference.html#Columns">Columns</a>widgets may be used to arrange either flow widgets or box widgetshorizontally into columns. Columns widgets will manage selectable widgetsby keeping track of which column is in focus and it can handle moving thefocus between columns when the user presses the LEFT and RIGHT keys.Columns widgets also work well when used within a ListBox.<br><br>Columns widgets are selectable only if the column in focus is selectable.If a focus column is not specified the first selectable widget will bechosen as the focus column. The <a href="reference.html#Columns-set_focus">set_focus</a>method may be used to select the focus column.<br clear="left"><br><h3><a name="grid">4.3. GridFlow Arrangement</a><span class="back">[<a href="#top">back to top</a>]</span></h3>The <a href="reference.html#GridFlow">GridFlow</a>widget is a flow widget designed for use with<a href="reference.html#Button">Button</a>,<a href="reference.html#CheckBox">CheckBox</a> and<a href="reference.html#RadioButton">RadioButton</a> widgets.It renders all the widgets it contains the same width and it arranges themfrom left to right and top to bottom.<br><br>The GridFlow widget uses Pile, Columns, Padding and Divider widgets to builda display widget that will handle the keyboard input and rendering. When theGridFlow widget is resized it regenerates the display widget to accommodatethe new space.<br clear="left"><br><h3><a name="overlay">4.4. Overlay Widgets</a><span class="back">[<a href="#top">back to top</a>]</span></h3>The <a href="reference.html#Overlay">Overlay</a> widget is a box widget thatcontains two other box widgets.  The bottom widget is rendered the full sizeof the Overlay widget and the top widget is placed on top, obscuring an areaof the bottom widget. This widget can be used to create effects such asoverlapping "windows" or pop-up menus.<br><br>The Overlay widget always treats the top widget as the one in focus. Allkeyboard input will be passed to the top widget. <br><br>If you want to use a flowflow widget for the top widget, first wrap the flow widget with a<a href="reference.html#Filler">Filler</a> widget.<br clear="left"><br><h2>5. Creating Custom Widgets</h2><h3><a name="wmod">5.1. Modifying Existing Widgets</a><span class="back">[<a href="#top">back to top</a>]</span></h3>The easiest way to create a custom widget is to modify an existing widget.This can be done by either subclassing the original widget or by wrapping it.Subclassing is appropriate when you need to interact at a very low levelwith the original widget, such as if you are creating a custom edit widgetwith different behavior than the usual Edit widgets.  If you are creatinga custom widget that doesn't need tight coupling with the original widget,such as a widget that displays customer address information, then wrappingis more appropriate.<br><br>The <a href="reference.html#WidgetWrap">WidgetWrap</a> class simplifieswrapping existing widgets.  You can create a custom widget simply by creating a subclass of WidgetWrap and passing a widget into WidgetWrap's constructor. <br><br>This is an example of a custom widget that uses WidgetWrap:<pre class="code">class QuestionnaireItem( urwid.WidgetWrap ):	def __init__(self):		self.options = []		unsure = urwid.RadioButton( self.options, &quot;Unsure&quot; )		yes = urwid.RadioButton( self.options, &quot;Yes&quot; )		no = urwid.RadioButton( self.options, &quot;No&quot; )		display_widget = urwid.GridFlow( [unsure, yes, no],			15, 3, 1, 'left' )		urwid.WidgetWrap.__init__(self, display_widget)	def get_state(self):		for o in self.options:			if o.get_state() is True:				return o.get_label()</pre>The above code creates a group of RadioButtons and provides a method toquery the state of the buttons.<br><br>Wrapped widgets may also override the standard widget methods. These methodsare described in following sections.<br clear="left"><br><h3><a name="wanat">5.2. Anatomy of a Widget</a><span class="back">[<a href="#top">back to top</a>]</span></h3>Any object that follows the <a href="reference.html#Widget_interface_definition">Widget interface definition</a>may be used as a widget.  Box widgets must implement <a href="reference.html#Widget_interface_definition-selectable">selectable</a>and <a href="reference.html#Widget_interface_definition-render">render</a>methods, and flow widgets must implement selectable, render and <a href="reference.html#Widget_interface_definition-rows">rows</a>methods.<pre class="code">class Pudding( urwid.FlowWidget ):	def selectable( self ):		return False	def rows( self, (maxcol,), focus=False ):		return 1	def render( self, (maxcol,), focus=False ):		num_pudding = maxcol / len(&quot;Pudding&quot;)		return urwid.TextCanvas([&quot;Pudding&quot;*num_pudding])class BoxPudding( urwid.BoxWidget ):	def selectable( self ):		return False	def render( self, (maxcol, maxrow), focus=False ):		num_pudding = maxcol / len(&quot;Pudding&quot;)		return urwid.TextCanvas(			[&quot;Pudding&quot;*num_pudding] * maxrow)</pre>The above code implements two widget classes. Pudding is a flow widget and BoxPudding is a box widget. Pudding will render as much "Pudding" as willfit in a single row, and BoxPudding will render as much "Pudding" as willfit into the entire area given.<br><br>It is not strictly necessary to inherit from<a href="reference.html#FlowWidget">BoxWidget</a> or <a href="reference.html#FlowWidget">FlowWidget</a>, but doing so does addsome documentation to your code.  <br><br>Note that the rows and render methods' focus parameter must have a defaultvalue of False.  Also note that for flow widgets the number of rows returned by the rows method must match the number of rows rendered by the rendermethod.<br><br>In most cases it is easier to let other widgets handle the rendering and row calculations for you:<pre class="code">class NewPudding( urwid.FlowWidget ):	def selectable( self ):		return False	def rows( self, (maxcol,), focus=False ):		w = self.display_widget( (maxcol,), focus )		return w.rows( (maxcol,), focus )	def render( self, (maxcol,), focus=False ):		w = self.display_widget( (maxcol,), focus )		return w.render( (maxcol,), focus )	def display_widget( self, (maxcol,), focus ):		num_pudding = maxcol / len(&quot;Pudding&quot;)		return urwid.Text( &quot;Pudding&quot;*num_pudding )</pre>The NewPudding class behaves the same way as the Pudding class above, but inNewPudding you can change the way the widget appears by modifying only thedisplay_widget method, whereas in the Pudding class you may have to modify boththe render and rows methods.<br><br>To improve the efficiency of your Urwid application you should be carefulof how long your rows methods take to execute.  The rows methods may be calledmany times as part of input handling and rendering operations.  If you areusing a display widget that is time consuming to create you should considercaching it to reduce its impact on performance.<br><br>It is possible to create a widget that will behave as either a flow widgetor box widget depending on what is required:<pre class="code">class MultiPudding( urwid.Widget ):	def selectable( self ):		return False	def rows( self, (maxcol,), focus=False ):		return 1	def render( self, size, focus=False ):		if len(size) == 1:			(maxcol,) = size			maxrow = 1		else:			(maxcol, maxrow) = size		num_pudding = maxcol / len(&quot;Pudding&quot;)		return urwid.TextCanvas(			[&quot;Pudding&quot;*num_pudding] * maxrow )</pre>MultiPudding will work in place of either Pudding or BoxPudding above. Thenumber of elements in the size tuple determines whether the containing widgetis expecting a flow widget or a box widget.<br clear="left"><br><h3><a name="wsel">5.3. Creating Selectable Widgets</a><span class="back">[<a href="#top">back to top</a>]</span></h3>Selectable widgets such as Edit and Button widgets allow the user tointeract with the application.  A widget is selectable if its selectablemethod returns True.  Selectable widgets must implement the<a href="reference.html#Widget_interface_definition-keypress">keypress</a>method to handle keyboard input.<pre class="code">class SelectablePudding( urwid.FlowWidget ):	def __init__( self ):		self.pudding = &quot;pudding&quot;	def selectable( self ):		return True	def rows( self, (maxcol,), focus=False ):		return 1	def render( self, (maxcol,), focus=False ):		num_pudding = maxcol / len(self.pudding)		pudding = self.pudding		if focus:			pudding = pudding.upper()		return urwid.TextCanvas( [pudding*num_pudding] )	def keypress( self, (maxcol,), key ):		if len(key)&gt;1:			return key		if key.lower() in self.pudding:			# remove letter from pudding			n = self.pudding.index(key.lower())			self.pudding = self.pudding[:n]+self.pudding[n+1:]			if not self.pudding:				self.pudding = &quot;pudding&quot;		else:			return key</pre>The SelectablePudding widget will display its contents in uppercase when itis in focus, and it allows the user to "eat" the pudding by pressing each ofthe letters P, U, D, D, I, N and G on the keyboard.  When the user has "eaten"all the pudding the widget will reset to its initial state.<br><br>Note that keys that are unhandled in the keypress method are returned so thatanother widget may be able to handle them.  This is a good convention to followunless you have a very good reason not to.  In this case the UP and DOWN keysare returned so that if this widget is in a ListBox the ListBox will behave asthe user expects and change the focus or scroll the ListBox.<br clear="left"><br><h3><a name="wcur">5.4. Widgets Displaying the Cursor</a><span class="back">[<a href="#top">back to top</a>]</span></h3>Widgets that display the cursor must implement the<a href="reference.html#Widget_interface_definition-get_cursor_coords">get_cursor_coords</a> method. Similar to the rows method for flow widgets, this method lets otherwidgets make layout decisions without rendering the entire widget.  TheListBox widget in particular uses get_cursor_coords to make sure that thecursor is visible within its focus widget.<pre class="code">class CursorPudding( urwid.FlowWidget ):	def __init__( self ):		self.cursor_col = 0	def selectable( self ):		return True	def rows( self, (maxcol,), focus=False ):		return 1	def render( self, (maxcol,), focus=False ):		num_pudding = maxcol / len(&quot;Pudding&quot;)		cursor = None		if focus:			cursor = self.get_cursor_coords((maxcol,))		return urwid.TextCanvas(			[&quot;Pudding&quot;*num_pudding], [], cursor )	def get_cursor_coords( self, (maxcol,) ):		col = min(self.cursor_col, maxcol-1)		return col, 0	def keypress( self, (maxcol,), key ):		if key == 'left':			col = self.cursor_col -1		elif key == 'right':			col = self.cursor_col +1		else:			return key		self.cursor_x = max(0, min( maxcol-1, col ))</pre>CursorPudding will let the user move the cursor through the widget by pressing LEFT and RIGHT. The cursor must only be added to the canvas whenthe widget is in focus. The get_cursor_coords method must always returnthe same cursor coordinates that render does.<br><br>A widget displaying a cursor may choose to implement<a href="reference.html#Widget_interface_definition-get_pref_col">get_pref_col</a>.This method returns the preferred column for the cursor, and is called whenthe focus is moving up or down off this widget.<br><br>Another optional method is <a href="reference.html#Widget_interface_definition-move_cursor_to_coords">move_cursor_to_coords</a>.This method allows other widgets to try to position the cursor within thiswidget. The ListBox widget uses move_cursor_to_coords when changing focus andwhen the user pressed PAGE UP or PAGE DOWN. This method must return True onsuccess and False on failure. If the cursor may be placed at any positionwithin the row specified (not only at the exact column specified) then thismethod must move the cursor to that position and return True.<pre class="code">	def get_pref_col( self, (maxcol,) ):		return self.cursor_x	def move_cursor_to_coords( self, (maxcol,), col, row ):		assert row == 0		self.cursor_x = col		return True</pre><br clear="left"><br></body></html>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -