问题
code below creates a layout and displays some text in the layout. Next the layout is displayed on the console screen using raw display module from urwid library. (More info on my complete project can be gleaned from questions at widget advice for a console project and urwid for a console project. My skype help request being here.) However running the code fails as an AttributeError is raised as described below. On looking at source code for urwid at /usr/lib64/python2.7/site-packages/urwid I see that both main_loop.py and curses_display.py have a draw_screen function with different arguments : main_loop.py -> def draw_screen(self):
curses_display.py > def draw_screen(self, (cols, rows), r ):
Do I have to specify which one to use by something like import draw_screen from specificFile command ? Or is there anything fundamentally wrong I am looking at the canvas concept ? I can also see that the frame class (class Frame(BoxWidget): ) in the file /usr/lib64/python2.7/site-packages/urwid/container.py has a render function (def render(self, size, focus=False):)
Error on running code is :
Traceback (most recent call last):
File "./yamlUrwidUIPhase6.py", line 104, in <module>
main()
File "./yamlUrwidUIPhase6.py", line 98, in main
form.main()
File "./yamlUrwidUIPhase6.py", line 51, in main
self.loop.run()
File "/usr/lib64/python2.7/site-packages/urwid/main_loop.py", line 274, in run
self.screen.run_wrapper(self._run)
File "/usr/lib64/python2.7/site-packages/urwid/raw_display.py", line 237, in run_wrapper
return fn()
File "/usr/lib64/python2.7/site-packages/urwid/main_loop.py", line 285, in _run
self.draw_screen()
File "/usr/lib64/python2.7/site-packages/urwid/main_loop.py", line 508, in draw_screen
canvas = self._topmost_widget.render(self.screen_size, focus=True)
AttributeError: 'NoneType' object has no attribute 'render'
The code :
import sys
sys.path.append('./lib')
import os
from pprint import pprint
import random
import urwid
ui=urwid.raw_display.Screen()
class FormDisplay(object):
def __init__(self):
global ui
self.ui = ui
self.palette = self.ui.register_palette([
('Field', 'dark green, bold', 'black'), # information fields, Search: etc.
('Info', 'dark green', 'black'), # information in fields
('Bg', 'black', 'black'), # screen background
('InfoFooterText', 'white', 'dark blue'), # footer text
('InfoFooterHotkey', 'dark cyan, bold', 'dark blue'), # hotkeys in footer text
('InfoFooter', 'black', 'dark blue'), # footer background
('InfoHeaderText', 'white, bold', 'dark blue'), # header text
('InfoHeader', 'black', 'dark blue'), # header background
('BigText', RandomColor(), 'black'), # main menu banner text
('GeneralInfo', 'brown', 'black'), # main menu text
('LastModifiedField', 'dark cyan, bold', 'black'), # Last modified:
('LastModifiedDate', 'dark cyan', 'black'), # info in Last modified:
('PopupMessageText', 'black', 'dark cyan'), # popup message text
('PopupMessageBg', 'black', 'dark cyan'), # popup message background
('SearchBoxHeaderText', 'light gray, bold', 'dark cyan'), # field names in the search box
('SearchBoxHeaderBg', 'black', 'dark cyan'), # field name background in the search box
('OnFocusBg', 'white', 'dark magenta') # background when a widget is focused
])
urwid.set_encoding('utf8')
def main(self):
global ui
#self.view = ui.run_wrapper(formLayout)
self.ui.start()
self.view = formLayout()
self.loop = urwid.MainLoop(self.view, self.palette, unhandled_input=self.unhandled_input)
self.loop.run()
def unhandled_input(self, key):
if key == 'f8':
quit()
return
def formLayout():
global ui
text1 = urwid.Text("Urwid 3DS Application program - F8 exits.")
text2 = urwid.Text("One mission accomplished")
textH = urwid.Text("topmost Pile text")
cols = urwid.Columns([text1,text2])
pile = urwid.Pile([textH,cols])
fill = urwid.Filler(pile)
textT = urwid.Text("Display")
textSH = urwid.Text("Pile text in Frame")
textF = urwid.Text("Good progress !")
frame = urwid.Frame(fill,header=urwid.Pile([textT,textSH]),footer=textF)
dim = ui.get_cols_rows()
#ui is treated as global handle for all functions, either belonging
#to any class or standalone functions such as formLayout
#need to check if screen has been started
if not ui._started:
print("Screen has not been started, so no use of rendering.Thus return :-( ")
return
ui.draw_screen(dim, frame.render(dim, True))
return
def RandomColor():
'''Pick a random color for the main menu text'''
listOfColors = ['dark red', 'dark green', 'brown', 'dark blue',
'dark magenta', 'dark cyan', 'light gray',
'dark gray', 'light red', 'light green', 'yellow',
'light blue', 'light magenta', 'light cyan', 'default']
color = listOfColors[random.randint(0, 14)]
return color
def main():
form = FormDisplay()
form.main()
########################################
##### MAIN ENTRY POINT
########################################
if __name__ == '__main__':
main()
I don't want to change the function formLayout as I intend to add more to this basic code framework, where in another function will be added that repeatedly calls formLayout to keep updating the screen based on reading values from a yml file. I already have a separate code that deals with reading the yaml file and extracting ordered dictionaries out it. After figuring out how to get basic urwid console working, I can move on to integrating both to create my final application.
回答1:
The Attribute Error was removed by adding following lines in the code as shown at this question.
line 1 :
self.loop.widget = self.view
in main
of class FormDisplay
line 2 :
doing a return Frame
instead of return
in the function formLayout()
line 3 :
added lines to handle key presses in unhandled_input
function
来源:https://stackoverflow.com/questions/17908588/attributeerror-while-trying-to-create-a-console-screen-using-urwid