| Issue 277: | MTVKeyboard - add_custom_layout doesn't work | |
| 1 person starred this issue and may be notified of changes. | Back to list |
What steps will reproduce the problem?
1. Create your own KeyboardLayout.
2. Add it with add_custom_layout(Layout())
3. Start the Keyboard with MTVKeyboard(layout = 'Layout.ID')
What is the expected output?
The Keyboard with my layout.
What do you see instead?
Traceback (most recent call last):
File "start.py", line 91, in <module>
pymt.runTouchApp(baseWidget)
File "/usr/lib/python2.6/site-packages/pymt/base.py", line 352, in runTouchApp
pymt_window.mainloop()
File "/usr/lib/python2.6/site-packages/pymt/ui/window/win_pygame.py", line 124, in mainloop
evloop.idle()
File "/usr/lib/python2.6/site-packages/pymt/base.py", line 201, in idle
pymt_window.dispatch_event('on_draw')
File "/usr/lib/python2.6/site-packages/pymt/event.py", line 344, in dispatch_event
if func(*args):
File "/usr/lib/python2.6/site-packages/pymt/ui/window/__init__.py", line 355, in on_draw
w.dispatch_event('on_draw')
File "/usr/lib/python2.6/site-packages/pymt/event.py", line 344, in dispatch_event
if func(*args):
File "/usr/lib/python2.6/site-packages/pymt/ui/widgets/widget.py", line 360, in on_draw
w.dispatch_event('on_draw')
File "/usr/lib/python2.6/site-packages/pymt/event.py", line 344, in dispatch_event
if func(*args):
File "/usr/lib/python2.6/site-packages/pymt/ui/widgets/scatter.py", line 141, in on_draw
super(MTScatterWidget, self).on_draw()
File "/usr/lib/python2.6/site-packages/pymt/ui/widgets/widget.py", line 357, in on_draw
self.draw()
File "/usr/lib/python2.6/site-packages/pymt/ui/widgets/composed/vkeyboard.py", line 433, in draw
self._update()
File "/usr/lib/python2.6/site-packages/pymt/ui/widgets/composed/vkeyboard.py", line 335, in _update
layoutmode = '%s:%s' % (self.layout.ID, self.mode)
AttributeError: 'str' object has no attribute 'ID'
What version of the product are you using? On what operating system?
I use PyMT 0.4 but I saw the bug in the git too.
I use Archlinux
Please provide any additional information below.
This error came because of this line in pymt/ui/widgets/composed/vkeyboard.py
self.layout = kwargs.get('layout')
You shuffle things because you use the same variable for the object and the id for the layout.
Replace:
# read default layout in configuration
if self.layout is None:
idlayout = pymt.pymt_config.get('keyboard', 'layout')
# search layout
for layout in MTVKeyboard.available_layout:
if layout.ID == idlayout:
self.layout = layout()
break
# no layout found ?
if self.layout is None:
pymt.pymt_logger.warning('Vkeyboard: Keyboard layout <%s> not found, fallback on QWERTY' % idlayout)
self.layout = KeyboardLayoutQWERTY()
With:
layout_id = self.layout
self.layout = None
# read default layout in configuration
if layout_id == None:
layout_id = pymt.pymt_config.get('keyboard', 'layout')
# search layout
for layout in MTVKeyboard.available_layout:
if layout.ID == layout_id:
self.layout = layout
break
# no layout found ?
if self.layout == None:
pymt.pymt_logger.warning('Vkeyboard: Keyboard layout <%s> not found, fallback on QWERTY' % layout_id)
self.layout = KeyboardLayoutQWERTY()
And you will see that it works.
Jul 4, 2010
Project Member
#1
dennd...@gmail.com
Owner:
dennda85
Jul 4, 2010
I copied one of the standard layouts and changed only the header information.
Here is it:
class KeyboardLayoutQWERTZ(KeyboardLayout):
'''Implementation of QWERTZ Layout'''
ID = 'qwertz'
TITLE = 'Qwertz'
DESCRIPTION = 'A classical German Keyboard'
# Need to be comment out because I don't defined kbdlayout_default_font
#FONT_FILENAME = kbdlayout_default_font
NORMAL_1 = [
('~', '~', None, 1), ('!', '!', None, 1), ('@', '@', None, 1),
('#', '#', None, 1), ('$', '$', None, 1), ('%', '%', None, 1),
('^', '^', None, 1), ('&', '&', None, 1), ('*', '*', None, 1),
('(', '(', None, 1), (')', ')', None, 1), ('_', '_', None, 1),
('+', '+', None, 1), (u'\u232b', None, 'backspace', 2),
]
NORMAL_2 = [
(u'\u21B9', chr(0x09), None, 1.5), ('q', 'q', None, 1), ('w', 'w', None, 1),
('e', 'e', None, 1), ('r', 'r', None, 1), ('t', 't', None, 1),
('y', 'y', None, 1), ('u', 'u', None, 1), ('i', 'i', None, 1),
('o', 'o', None, 1), ('p', 'p', None, 1), ('{', '{', None, 1),
('}', '}', None, 1), ('|', '|', None, 1.5)
]
NORMAL_3 = [
(u'\u21ea', None, 'capslock', 1.8), ('a', 'a', None, 1), ('s', 's', None, 1),
('d', 'd', None, 1), ('f', 'f', None, 1), ('g', 'g', None, 1),
('h', 'h', None, 1), ('j', 'j', None, 1), ('k', 'k', None, 1),
('l', 'l', None, 1), (':', ':', None, 1), ('"', '"', None, 1),
(u'\u23ce', None, 'enter', 2.2),
]
NORMAL_4 = [
(u'\u21e7', None, 'shift_L', 2.5), ('z', 'z', None, 1), ('x', 'x', None, 1),
('c', 'c', None, 1), ('v', 'v', None, 1), ('b', 'b', None, 1),
('n', 'n', None, 1), ('m', 'm', None, 1), ('<', '<', None, 1),
('>', '>', None, 1), ('?', '?', None, 1), (u'\u21e7', None, 'shift_R', 2.5),
]
NORMAL_5 = [
('', ' ', None, 12), (u'\u2b12', None, 'layout', 1.5), (u'\u2a2f', None, 'escape', 1.5),
]
SHIFT_1 = [
('`', '`', None, 1), ('1', '1', None, 1), ('2', '2', None, 1),
('3', '3', None, 1), ('4', '4', None, 1), ('5', '5', None, 1),
('6', '6', None, 1), ('7', '7', None, 1), ('8', '8', None, 1),
('9', '9', None, 1), ('0', '0', None, 1), ('+', '+', None, 1),
('=', '=', None, 1), (u'\u232b', None, 'backspace', 2),
]
SHIFT_2 = [
(u'\u21B9', chr(0x09), None, 1.5), ('Q', 'Q', None, 1), ('W', 'W', None, 1),
('E', 'E', None, 1), ('R', 'R', None, 1), ('T', 'T', None, 1),
('Y', 'Y', None, 1), ('U', 'U', None, 1), ('I', 'I', None, 1),
('O', 'O', None, 1), ('P', 'P', None, 1), ('[', '[', None, 1),
(']', ']', None, 1), ('?', '?', None, 1.5)
]
SHIFT_3 = [
(u'\u21ea', None, 'capslock', 1.8), ('A', 'A', None, 1), ('S', 'S', None, 1),
('D', 'D', None, 1), ('F', 'F', None, 1), ('G', 'G', None, 1),
('H', 'H', None, 1), ('J', 'J', None, 1), ('K', 'K', None, 1),
('L', 'L', None, 1), (':', ':', None, 1), ('"', '"', None, 1),
(u'\u23ce', None, 'enter', 2.2),
]
SHIFT_4 = [
(u'\u21e7', None, 'shift_L', 2.5), ('Z', 'Z', None, 1), ('X', 'X', None, 1),
('C', 'C', None, 1), ('V', 'V', None, 1), ('B', 'B', None, 1),
('N', 'N', None, 1), ('M', 'M', None, 1), (',', ',', None, 1),
('.', '.', None, 1), ('/', '/', None, 1), (u'\u21e7', None, 'shift_R', 2.5),
]
SHIFT_5 = [
('', ' ', None, 12), (u'\u2b12', None, 'layout', 1.5), (u'\u2a2f', None, 'escape', 1.5),
]
Jul 4, 2010
Sorry, I forgot to ask you for the code that you were using to add your own layout. Can you paste it as well please?
Jul 4, 2010
Here is the whole code I used:
#!/usr/bin/env python
from pymt import *
class BaseWidget(MTWidget):
def __init__(self):
MTWidget.__init__(self)
class KeyboardLayoutQWERTZ(KeyboardLayout):
'''Implementation of QWERTZ Layout'''
ID = 'qwertz'
TITLE = 'Qwertz'
DESCRIPTION = 'A classical German Keyboard'
#FONT_FILENAME = kbdlayout_default_font
NORMAL_1 = [
('~', '~', None, 1), ('!', '!', None, 1), ('@', '@', None, 1),
('#', '#', None, 1), ('$', '$', None, 1), ('%', '%', None, 1),
('^', '^', None, 1), ('&', '&', None, 1), ('*', '*', None, 1),
('(', '(', None, 1), (')', ')', None, 1), ('_', '_', None, 1),
('+', '+', None, 1), (u'\u232b', None, 'backspace', 2),
]
NORMAL_2 = [
(u'\u21B9', chr(0x09), None, 1.5), ('q', 'q', None, 1), ('w', 'w', None, 1),
('e', 'e', None, 1), ('r', 'r', None, 1), ('t', 't', None, 1),
('y', 'y', None, 1), ('u', 'u', None, 1), ('i', 'i', None, 1),
('o', 'o', None, 1), ('p', 'p', None, 1), ('{', '{', None, 1),
('}', '}', None, 1), ('|', '|', None, 1.5)
]
NORMAL_3 = [
(u'\u21ea', None, 'capslock', 1.8), ('a', 'a', None, 1), ('s', 's', None, 1),
('d', 'd', None, 1), ('f', 'f', None, 1), ('g', 'g', None, 1),
('h', 'h', None, 1), ('j', 'j', None, 1), ('k', 'k', None, 1),
('l', 'l', None, 1), (':', ':', None, 1), ('"', '"', None, 1),
(u'\u23ce', None, 'enter', 2.2),
]
NORMAL_4 = [
(u'\u21e7', None, 'shift_L', 2.5), ('z', 'z', None, 1), ('x', 'x', None, 1),
('c', 'c', None, 1), ('v', 'v', None, 1), ('b', 'b', None, 1),
('n', 'n', None, 1), ('m', 'm', None, 1), ('<', '<', None, 1),
('>', '>', None, 1), ('?', '?', None, 1), (u'\u21e7', None, 'shift_R', 2.5),
]
NORMAL_5 = [
('', ' ', None, 12), (u'\u2b12', None, 'layout', 1.5), (u'\u2a2f', None, 'escape', 1.5),
]
SHIFT_1 = [
('`', '`', None, 1), ('1', '1', None, 1), ('2', '2', None, 1),
('3', '3', None, 1), ('4', '4', None, 1), ('5', '5', None, 1),
('6', '6', None, 1), ('7', '7', None, 1), ('8', '8', None, 1),
('9', '9', None, 1), ('0', '0', None, 1), ('+', '+', None, 1),
('=', '=', None, 1), (u'\u232b', None, 'backspace', 2),
]
SHIFT_2 = [
(u'\u21B9', chr(0x09), None, 1.5), ('Q', 'Q', None, 1), ('W', 'W', None, 1),
('E', 'E', None, 1), ('R', 'R', None, 1), ('T', 'T', None, 1),
('Y', 'Y', None, 1), ('U', 'U', None, 1), ('I', 'I', None, 1),
('O', 'O', None, 1), ('P', 'P', None, 1), ('[', '[', None, 1),
(']', ']', None, 1), ('?', '?', None, 1.5)
]
SHIFT_3 = [
(u'\u21ea', None, 'capslock', 1.8), ('A', 'A', None, 1), ('S', 'S', None, 1),
('D', 'D', None, 1), ('F', 'F', None, 1), ('G', 'G', None, 1),
('H', 'H', None, 1), ('J', 'J', None, 1), ('K', 'K', None, 1),
('L', 'L', None, 1), (':', ':', None, 1), ('"', '"', None, 1),
(u'\u23ce', None, 'enter', 2.2),
]
SHIFT_4 = [
(u'\u21e7', None, 'shift_L', 2.5), ('Z', 'Z', None, 1), ('X', 'X', None, 1),
('C', 'C', None, 1), ('V', 'V', None, 1), ('B', 'B', None, 1),
('N', 'N', None, 1), ('M', 'M', None, 1), (',', ',', None, 1),
('.', '.', None, 1), ('/', '/', None, 1), (u'\u21e7', None, 'shift_R', 2.5),
]
SHIFT_5 = [
('', ' ', None, 12), (u'\u2b12', None, 'layout', 1.5), (u'\u2a2f', None, 'escape', 1.5),
]
if __name__ == '__main__':
main_window = getWindow()
main_widget = BaseWidget()
MTVKeyboard.add_custom_layout(KeyboardLayoutQWERTZ())
keyboard = MTVKeyboard(layout = 'qwertz')
main_widget.add_widget(MTScatterWidget())
main_widget.add_widget(keyboard)
runTouchApp(main_widget)
I have detected an other bug when you use add_custom_layout.
Try this code and then fix the bug with the code I gave you.
Now you custom layout works but then try to change the layout to QWERTY.
This works fine too.
But when you want to change back to QWERTZ you get the following message:
Traceback (most recent call last):
File "test.py", line 89, in <module>
runTouchApp(main_widget)
File "/usr/lib/python2.6/site-packages/pymt/base.py", line 352, in runTouchApp
pymt_window.mainloop()
File "/usr/lib/python2.6/site-packages/pymt/ui/window/win_pygame.py", line 124, in mainloop
evloop.idle()
File "/usr/lib/python2.6/site-packages/pymt/base.py", line 196, in idle
self.dispatch_input()
File "/usr/lib/python2.6/site-packages/pymt/base.py", line 181, in dispatch_input
self.post_dispatch_input(type=type, touch=touch)
File "/usr/lib/python2.6/site-packages/pymt/base.py", line 151, in post_dispatch_input
wid.dispatch_event('on_touch_up', touch)
File "/usr/lib/python2.6/site-packages/pymt/event.py", line 349, in dispatch_event
event_type, args, getattr(self, event_type))
File "/usr/lib/python2.6/site-packages/pymt/event.py", line 344, in dispatch_event
if func(*args):
File "/usr/lib/python2.6/site-packages/pymt/ui/widgets/composed/kineticlist.py", line 425, in on_touch_up
child.dispatch_event('on_touch_down', touch)
File "/usr/lib/python2.6/site-packages/pymt/event.py", line 349, in dispatch_event
event_type, args, getattr(self, event_type))
File "/usr/lib/python2.6/site-packages/pymt/event.py", line 344, in dispatch_event
if func(*args):
File "/usr/lib/python2.6/site-packages/pymt/ui/widgets/button.py", line 153, in on_touch_down
self.dispatch_event('on_press', touch)
File "/usr/lib/python2.6/site-packages/pymt/event.py", line 337, in dispatch_event
self._raise_dispatch_exception(event_type, args, handler)
File "/usr/lib/python2.6/site-packages/pymt/event.py", line 334, in dispatch_event
if handler(*args):
File "/usr/lib/python2.6/site-packages/pymt/utils.py", line 32, in call_fn
return fn(*(cargs + fargs), **d)
File "/usr/lib/python2.6/site-packages/pymt/ui/widgets/composed/vkeyboard.py", line 432, in on_layout_change
self.layout = layout()
TypeError: 'KeyboardLayoutQWERTZ' object is not callable
Jul 4, 2010
OK, there is no bug. :-) You're using the API incorrectly. a) add_custom_layout expects a class object, not an object of that class. I.e., don't call add_custom_layout(KeyboardLayoutQWERTZ()), but add_custom_layout(KeyboardLayoutQWERTZ). Then you can just create a MTVKeyboard (even without the layout= parameter) and choose the qwertz layout from the list when you click the button on the bottom left. b) If you want to give the keyboard the right layout from the start, don't pass an ID but the actual keyboardlayout object. I.e.: k = MTVKeyboard(layout=KeyboardLayoutQWERTZ()) instead of: k = MTVKeyboard(layout='qwertz'). That both works for me. (You are missing a SIZE attribute in your layout. I think you can just copy that one line from the QWERTY layout.) That should help. I'm marking this issue as invalid since I don't think it's a bug. If you disagree, feel free to post again. Thanks for taking the time to report this issue, nevertheless!
Status:
Invalid
Jul 4, 2010
OK, I became a little bit confused because of the config file were it says layout = qwerty. Thank you for these informations and sorry that I waste your time. (You are missing a SIZE attribute in your layout. I think you can just copy that one line from the QWERTY layout.) There is no SIZE attribute in the QWERTY layout - I think that's because I don't use the git version. |