[Urwid] Selectable ListBox Items

James Mills prologic at shortcircuit.net.au
Sat Jun 23 11:04:30 EDT 2007


Hello all,

Wondering if someone can help me improve this UI i'm
building with urwid:

<code>
#!/usr/bin/env python

from select import select
from traceback import format_exc

import urwid
from urwid.raw_display import Screen

MAIN_TITLE = "-test: 0.0.1"
KEYS = "q:Quit  s:Scan  i:Info  m:Monitor  ?:Help"

def setNetwork(net):
	pass

class MainWindow(Screen):

	def __init__(self):
		Screen.__init__(self)

		self.register_palette((
			("title", "dark red", "default"),
			("keys", "dark red", "default"),
			("message", "light cyan", "default"),
			("input", "light gray", "default"),
			))

		self.mode = ""
		self.pos = 0
		self.input = ""
		self.nets = []

		self.items = []
		self.listbox = urwid.ListBox(self.items)

		self.title = urwid.Text(MAIN_TITLE)
		self.header = urwid.AttrWrap(self.title, "title")

		self.keys = urwid.AttrWrap(urwid.Text(KEYS), "keys")
		self.user = urwid.AttrWrap(urwid.Text("", ), "message")
		self.footer = urwid.Pile([self.keys, self.user])

		self.top = urwid.Frame(self.listbox, self.header,
				self.footer)
	
	def displayInfo(self):
		while len(self.items) > 0:
			self.items.pop()

		self.items.append(urwid.Text("Some data"))
		self.items.append(urwid.Text("Some more data"))

	def doScan(self):
		while len(self.items) > 0:
			self.items.pop()

		self.items.append(urwid.Text("Some data"))
		self.items.append(urwid.Text("Some more data"))

		self.user.set_text("Connect to: ")

	def process(self):
		size = self.get_cols_rows()

		if self.mode == "monitor":
			self.displayInfo()

		if not select(
				self.get_input_descriptors(),
				[], [], 0.1)[0] == []:

			timeout, keys, raw = self.get_input_nonblocking()

			for k in keys:
	
				if k == "window resize":
					size = self.get_cols_rows()
					continue
				elif k in "0123456789":
					self.input += k
				elif k == "enter":
					self.mode = ""
					self.user.set_text("")

					try:
						i = int(self.input)
						if i >= 0 and i < len(self.nets):
							setNetwork(self.nets[i])
						else:
							self.user.set_text("ERROR: Invalid selection")
					except ValueError:
						self.user.set_text("ERROR: Invalid input")

				elif k == "s":
					self.mode = "select"
					self.doScan()
				elif k == "i":
					self.mode = ""
					self.displayInfo()
				elif k == "m":
					self.mode = "monitor"
				elif k  == "q":
					raise SystemExit, 0
				else:
					self.user.set_text("Key: %s" % k)

				self.top.keypress(size, k)

		self.update_screen(size)

	def update_screen(self, size):
		canvas = self.top.render(size, focus=True)
		self.draw_screen(size, canvas)
	
def main():

	window = MainWindow()

	window.start()

	while True:
		try:
			window.process()
		except KeyboardInterrupt:
			window.stop()
			break
		except SystemExit:
			window.stop()
			break
		except Exception, e:
			window.stop()
			print format_exc()
			break

if __name__ == "__main__":
	main()
</code>

Basically when you press "s" a scan will result (just dummy
code for now) and you should be able to highlight the
desired item with up/down and select it by pressing enter.

The only way I can think of doing this is with a lot of
messy ugly code - I'm sure there is a more elegant solution.

Much appreicated,

cheers
James

-- 
--
-"Problems are Solved by Method"
-
- James Mills <prologic at shortcircuit.net.au>
- HomePage: http://shortcircuit.net.au/~prologic/
- IRC: irc://shortcircuit.net.au#se

Please avoid sending me Word or PowerPoint attachments.
See http://www.gnu.org/philosophy/no-word-attachments.html




More information about the Urwid mailing list