Text Encoding Between Python File, Maya Script Editor, and Maya UI (Python 2.7, Maya 2015, Windows 7) - python-2.7

I've got a python file that I'm loading as a script into the maya script editor. The python file is currently encoded as UTF-8.
I have the need to use the ↑ and ↓ characters (or any other arrow substitutes within Unicode, such as ➘ or ➚, I just want to convey up and down). I'm using the characters as the label of a button. Here's the script:
import Maya.cmds as cmds
def initInterface():
cmds.window("mywin")
cmds.rowColumnLayout("my_rcl", nc=1)
cmds.button(label=u'\↑')
cmds.button(label=u'\↓')
cmds.showWindow("mywin")
initInterface()
The script is saved as myPythonScript.py and is then loaded into the Maya script editor using the load script button.
On execution, I get a UI window and buttons as expected, but the labels for the buttons are now "?" (question marks). I can't seem to get Maya to display the arrows.
To solve this, I've tried a couple of in-code things. Here are a few of my attempts:
# Attempt 1
upArrow = u'\↑'
upArrowEncoded = upArrow.encode("utf-8")
cmds.button(label=upArrowEncoded)
# Result: "?"
# Attempt 2
upArrow = u'\U+2B06'
cmds.button(label=upArrow)
# Result: "?B06"
# Attempt 3
upArrow = u'\U+2B06'
upArrowEncoded = upArrow.encode("utf-8")
cmds.button(label=upArrowEncoded)
# Result: "?"
To be honest (and is likely to be apparent from my code snippets) I've never experimented with text encoding and know next to nothing about it. I'm not sure if I need to change the encoding of my .py file, or encode the string with UTF-16 or something. This is way outside of my area of expertise and I'm having a hard time finding resources to help me understand text and string encoding.
I did check out this:
Unicode Within Maya
And this:
Convert a Unicode String to a String in Python Containing Extra Symbols
But I wasn't able to understand a lot of what I read, and I'm not sure if they relate to this issue or not.
I'm the type of person who doesn't enjoy using code I don't understand (how do people even document that?), so I'm here to ask for links to learning resources and for general advice on the subject, moreso than for a code snippet that does what I want. If it turns out this is not possible, I can use image buttons instead. But they are less efficient and time consuming to produce for each special character I may use.
Thank you for reading through this, and thank you in advance to anyone who can point me in the right direction here. Cheers!

As far as I can tell, the native MayaUi uses/has access to the Code Page 1252 Windows Latin 1 (ANSI) character set (at least on Windows...) as mentioned here, and after some noodling these *all appear to work as advertised.
I'd be curious to see an answer that explained how to change that and access what OP is looking for, but as an alternative to anyone that really truly wants more special characters, may I suggest learning PySide / Qt for building your UI.
Caveats
A lot more boilerplate and setup when it comes to making 'something simple'
Several mayaControls do not have direct Qt implementations (gradientControlNoAttr being a recent discovery, and case in point)
Example is written under the assumption that user has installed and uses Qt.py
Lets dive right in:
import maya.cmds as cmds
import maya.OpenMayaUI as omui
from Qt import QtCore, QtGui
from Qt.QtWidgets import *
from shiboken import wrapInstance
def maya_main_window():
main_window_ptr = omui.MQtUtil.mainWindow()
return wrapInstance(long(main_window_ptr), QWidget)
class TestUi(QDialog):
def __init__(self, parent=maya_main_window()):
super(TestUi, self).__init__(parent)
self.setAttribute(QtCore.Qt.WA_DeleteOnClose)
def create(self):
self.setWindowTitle("TestUi : Unicode")
self.setWindowFlags(QtCore.Qt.Tool)
self.create_controls()
self.create_layout()
self.create_connections()
def create_controls(self):
"""
Create the widgets for the dialog.
"""
# using "Python source code" unicode values
# ie: https://www.fileformat.info/info/unicode/char/2191/index.htm
self.up_button = QPushButton(u'\u2191')
self.down_button = QPushButton(u'\u2193')
self.left_button = QPushButton(u'\u2190')
self.right_button = QPushButton(u'\u2192')
def create_layout(self):
"""
Create the layouts & add widgets
"""
main_layout = QVBoxLayout()
main_layout.setContentsMargins(6, 6, 6, 6)
main_layout.addWidget(self.up_button)
main_layout.addWidget(self.down_button)
main_layout.addWidget(self.left_button)
main_layout.addWidget(self.right_button)
main_layout.addStretch()
self.setLayout(main_layout)
def create_connections(self):
"""
Create the signal/slot connections
"""
self.up_button.clicked.connect(self.on_button_pressed)
self.down_button.clicked.connect(self.on_button_pressed)
self.left_button.clicked.connect(self.on_button_pressed)
self.right_button.clicked.connect(self.on_button_pressed)
def on_button_pressed(self):
print "Button Pressed"
def LaunchUI():
if __name__ == "__main__":
# Development workaround for PySide winEvent error (Maya 2014)
# Make sure the UI is deleted before recreating
try:
test_ui.deleteLater()
test_ui.close()
except:
pass
# Create minimal UI object
test_ui = TestUi()
# Delete the UI if errors occur to avoid causing winEvent
# and event errors (in Maya 2014)
try:
test_ui.create()
test_ui.show()
except:
test_ui.deleteLater()
traceback.print_exc()
LaunchUI()
There's an awful lot to unpack there for not a terribly huge payoff, but the relevant piece of information is living under "create_controls".

Related

Unable to save persistence file using wxPython PersistenceManager

I'm developing a GUI application using wxpython that has roughly 110 user-chosen parameters. Since I would like for users to be able to save these options to a project file, I decided to use the PersistenceManager module that's included with wxPython.
The persistence works great as long as I don't try to specify the filename in which to save the settings, i.e., I use the default value (C:\users\username\AppData\programName\Persistence_Options), and just have the program save the settings when it exits.
What I'm trying to do is allow the user to choose a file to save the settings (since they might have multiple projects with different options). But, when I use the SetPersistenceFile method with the user-specified filename, no file gets saved, and no error message is returned, even though it's definitely executing those lines of code, which are given below. (The OnSave function is a method of the main window of the program.)
def OnSave(self, e):
self.dirname = os.getcwd()
if self.ProjectFile == '':
dlg = wx.FileDialog(self, "Save project file", self.dirname, "", "Project configuration file (.prj)|*.prj", wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT)
if dlg.ShowModal() == wx.ID_CANCEL:
return
else:
self.ProjectFile = os.path.join(dlg.GetDirectory(), dlg.GetFilename())
#print self.ProjectFile
if self.ProjectFile != '':
print "Made it to here (Save)..."
#self.Register(self) # Also tried calling Register in __init__
self._persistMgr = PM.PersistenceManager.Get()
print self.ProjectFile # Gives correct filename
self._persistMgr.SetPersistenceFile(self.ProjectFile)
self._persistMgr.Save(self)
print "Finished saving."
I've tried using a local PersistenceManager object, rather than having it as a class member, and this made no difference. Interestingly enough, if I declare the self.__persistMgr object in the window's __init__ function and use the SetPersistenceFile method with a hard-coded filename there, it writes the file, however this is not helpful since the user needs to specify that at runtime.
Does anyone know why the file isn't saving and how I can fix this?
Not sure why your code is giving you grief, the following works on Linux, although that may be of no consolation to you.
It is cobbled together from a number of sources, not having come across the PersistenceManager myself.
#!/usr/bin/python
import wx , os
import wx.lib.agw.persist as PM
class persist(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__(self, parent, -1, "A window that maintains size and position after restart")
self.Bind(wx.EVT_CLOSE, self.OnClose)
# Very important step!!
if self.GetName() == "frame":
self.SetName("My Persist Frame") # Do not use the default name!!
dirname = os.getcwd()
dlg = wx.FileDialog(self, "Project file", dirname, "", "Project configuration file (.prj)|*.prj|All files (*.*)|*.*", wx.FD_SAVE)
if dlg.ShowModal() == wx.ID_CANCEL:
_configFile = os.path.join(os.getcwd(), "persist-saved.prj") # getname()
else:
_configFile = os.path.join(dlg.GetDirectory(), dlg.GetFilename())
print _configFile
self._persistMgr = PM.PersistenceManager.Get()
self._persistMgr.SetPersistenceFile(_configFile)
self._persistMgr.RegisterAndRestoreAll(self)
self._persistMgr.Save(self)
def OnClose(self, event):
self._persistMgr.SaveAndUnregister()
event.Skip()
if __name__ == '__main__':
my_app = wx.App()
p = persist(None)
p.Show()
my_app.MainLoop()
Result in my .prj file:
[Persistence_Options]
[Persistence_Options/Window]
[Persistence_Options/Window/My\ Persist\ Frame]
x=('int', '9')
y=('int', '134')
w=('int', '319')
h=('int', '78')
Maximized=('bool', 'False')
Iconized=('bool', 'False')
Note the setting of the name this would be true of whatever it is that you are saving for persistence.
Edit: With regard to your comment
I think that you might be hoping for more than the PersistenceManager can cope with currently.
wxWidgets has built-in support for a (constantly growing) number of controls. Currently the following classes are supported:
wxTopLevelWindow (and hence wxFrame and wxDialog)
wxBookCtrlBase (i.e. wxNotebook, wxListbook, wxToolbook and wxChoicebook)
wxTreebook
To automatically save and restore the properties of the windows of classes listed above you need to:
Set a unique name for the window using wxWindow::SetName(): this step is important as the name is used in the configuration file and so must be unique among all windows of the same class.
Call wxPersistenceManager::Register() at any moment after creating the window and then wxPersistenceManager::Restore() when the settings may be restored (which can't be always done immediately, e.g. often the window needs to be populated first). If settings can be restored immediately after the window creation, as is often the case for wxTopLevelWindow, for example, then wxPersistenceManager::RegisterAndRestore() can be used to do both at once.
If you do not want the settings for the window to be saved (for example the changes to the dialog size are usually not saved if the dialog was cancelled), you need to call wxPersistenceManager::Unregister() manually. Otherwise the settings will be automatically saved when the control itself is destroyed.
Source: http://www.ccp4.ac.uk/dist/checkout/wxPython-src-3.0.2.0/docs/doxygen/out/html/overview_persistence.html
Of course I could be hopelessly wrong, as I have already admitted, I haven't used it before or really investigated it properly.

Closing Tkinter GUI from another function A and passes Tkinter variable to function A

This question is about programming in Python 2.7.x
I wanted to code a programme where there are two functions exist: one of those is a method to get input from the user, and the other one is to show the input. Both are supposed to be done in GUI. Let's call the first function as GET TEXT function, and the second as SHOW TEXT function; my strategy is to open a GUI, show a text box, and put a button to go to SHOW TEXT function. Then, the first line of the SHOW TEXT function is to close the window opened by the GET TEXT function, get the value of the input text, and print it in another GUI.
So, I tried doing this,
from Tkinter import *
import tkMessageBox
def texttobeenteredhere():
application = Tk()
textbox = Text(application)
textbox.pack()
submitbutton = Button(application, text="OK", command=showinputtext)
submitbutton.pack()
application.mainloop()
def showinputtext():
application.quit()
thetext = textbox.get()
print "You typed", thetext
texttobeenteredhere()
I got errors that I could not comprehend, but I hope you get my idea even though my explanation could be really bad. Please suggest a solution to my problem, where the GET TEXT function and SHOW TEXT function have to exist separately in the code.
EDIT:
Thanks Josselin for introducing the syntax class in python. What I actually wanted to say was, I want the programme to open a window to get input from the user, and then close the window, and finally open another window to show the input text. I am honestly new to this, but through my prior knowledge and guessing, I tried to modify the code to meet my expectation.
import Tkinter as tk
global passtext
class application(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.textbox = tk.Text(self)
self.textbox.pack()
self.submitbutton = tk.Button(self, text="OK", command=self.showinputtext)
self.submitbutton.pack()
self.mainloop()
def showinputtext(self):
self.thetext = self.textbox.get("1.0", "end-1c")
print "You typed:", self.thetext
self.destroy()
class showtext(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.setthetext = tk.StringVar()
self.setthetext.set(passtext)
self.showthetext = tk.Label(self, textvariable=self.setthetext)
self.showthetext.pack()
self.submitbutton = tk.Button(self, text="OK", command=self.destroy)
self.submitbutton.pack()
self.mainloop()
# Launch the GUI
app = application()
# Access the entered text after closing the GUI
passtext = app.thetext
text = showtext()
My English can sometimes be not understandable, but this question is answered. Thank you very much.
There are 2 main problems in your code:
First, in your showinputtext function, you want to access elements of your GUI, but they are not defined within the scope of the function.
Second, when reading the content of a tk.Text widget, the .get() method takes 2 arguments (see this link).
To fix the first problem, the best is to define your application as a class, with an inner function taking the class instance self as input argument, such that application widgets can be called within the function.
Code:
import Tkinter as tk
class application(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.textbox = tk.Text(self)
self.textbox.pack()
self.submitbutton = tk.Button(self, text="OK", command=self.showinputtext)
self.submitbutton.pack()
self.mainloop()
def showinputtext(self):
self.thetext = self.textbox.get("1.0", "end-1c")
print "You typed:", self.thetext
self.destroy()
# Launch the GUI
app = application()
# Access the entered text after closing the GUI
print "you entered:", app.thetext

Python tk(): No window appears when using in scripts (console works)

I have the following problem with this easy script:
from Tkinter import *
root = Tk()
while 1:
pass
I think, after the 2nd line everyone would expect a Tkinter window would appear. But it does not!
If I put this line into the Python console (without the endless-while-loop), it works.
[I wanted to add an image here, but as I'm new I'm to allowed to :-(]
But running the script (double-clicking on the *.py file in the Windows Explorer) results only in an empty Python console!
Background:
Actually I want to use Snack for Python. This is based on Tkinter. That means I have to create an Tk() instance first. Everything works fine in the Python console. But I want to write a bigger program with at least one Python script thus I cannot type the whole program into the console everytime :-)
I have installed Python 2.7 and Tcl/Tk 8.5 (remember: it works in the console)
EDIT: So here's my solution:
First, I create a class CSoundPlayer:
from Tkinter import*
import tkSnack
class CSoundPlayer:
def __init__(self, callbackFunction):
self.__activated = False
self.__callbackFunction = callbackFunction
self.__sounds = []
self.__numberOfSounds = 0
self.__root = Tk()
self.__root.title("SoundPlayer")
tkSnack.initializeSnack(self.__root)
def __mainFunction(self):
self.__callbackFunction()
self.__root.after(1, self.__mainFunction)
pass
def activate(self):
self.__activated = True
self.__root.after(1, self.__mainFunction)
self.__root.mainloop()
def loadFile(self, fileName):
if self.__activated:
self.__sounds.append(tkSnack.Sound(load=fileName))
self.__numberOfSounds += 1
# return the index of the new sound
return self.__numberOfSounds - 1
else:
return -1
def play(self, soundIndex):
if self.__activated:
self.__sounds[soundIndex].play()
else:
return -1
Then, the application itself must be implemented in a class thus the main() is defined when handed over to the CSoundPlayer() constructor:
class CApplication:
def __init__(self):
self.__programCounter = -1
self.__SoundPlayer = CSoundPlayer(self.main)
self.__SoundPlayer.activate()
def main(self):
self.__programCounter += 1
if self.__programCounter == 0:
self.__sound1 = self.__SoundPlayer.loadFile("../mysong.mp3")
self.__SoundPlayer.play(self.__sound1)
# here the cyclic code starts:
print self.__programCounter
CApplication()
As you can see, the mainloop() is called not in the constructor but in the activate() method. This is because the CApplication won't ever get the reference to CSoundPlayer object because that stucks in the mainloop.
The code of the class CApplication itself does a lot of overhead. The actual "application code" is placed inside the CApplication.main() - code which shall be executed only once is controlled by means of the program counter.
Now I put it to the next level and place a polling process of the MIDI Device in the CApplication.main(). Thus I will use MIDI commands as trigger for playing sound files. I hope the performance is sufficient for appropriate latency.
Have you any suggestions for optimization?
You must start the event loop. Without the event loop, tkinter has no way to actually draw the window. Remove the while loop and replace it with mainloop:
from Tkinter import *
root = Tk()
root.mainloop()
If you need to do polling (as mentioned in the comments to the question), write a function that polls, and have that function run every periodically with after:
def poll():
<do the polling here>
# in 100ms, call the poll function again
root.after(100, poll)
The reason you don't need mainloop in the console depends on what you mean by "the console". In IDLE, and perhaps some other interactive interpreters, tkinter has a special mode when running interactively that doesn't require you call mainloop. In essence, the mainloop is the console input loop.

weird django translations behaviour

I have weird problem with django translations that i need help figuring out. Problem is that instead of getting translated string every time i seem to get randomly either translated string or default string.
I have created a class for putting "action" buttons on several pages. Many of those buttons are reusable so why should i put
blabla
into several templates when i can create simple toolbar and use
toolbar.add(tool)
in view and then just use templatetag for rendering all the tools.... anyway.
This is example of one tool:
class NewUserGroupButton(MyTool):
tool_id = 'new-user-group'
button_label = ugettext(u'Create new user group')
tool_href = 'new/'
js = ()
def render(self):
s = '<a id="%(tool_id)s" href="%(tool_href)s" class="button blue">%(button_label)s</a>'
return s % {'tool_id': self.tool_id, 'tool_href': self.tool_href, 'button_label':self.button_label}
The tools are rendered like this:
class ToolbarTools:
def __init__(self):
self.tools = []
def add(self, tool):
self.tools.append(tool)
def render(self):
# Organize tools by weight
self.tools.sort(key=lambda x: x.weight)
# Render tools
output = '<ul id="toolbar" class="clearfix">'
for tool in self.tools:
output += '<li id="%s">' % ('tool-'+ tool.tool_id)
output += tool.render() if tool.renderable else ''
output += '</li>'
output += '</ul>'
# Reset tools container
self.tools = []
return mark_safe(output)
im using ugettext to translate the string. using (u)gettext=lambda s:s or ugettext_lazy gives me either no translations or proxy object corresponding to function choices.
And like i said - while rest of the page is in correct language the toolbar buttons seem to be randomly either translated or not. The faulty behaviour remains consistent if i move between different pages with different "tools" or even refresh the same page several times.
Could someone please help me to figure out what is causing this problem and how to fix it?
Problem solved.
The issue itself (random translating) was perhaps caused by using ugettext. But at the same time i should have used ugettext_lazy instead.
And thus the problem really came from ugettext_lazy returning proxy object not translated string... and that is caused by this:
[Quote]
Working with lazy translation objects
The result of a ugettext_lazy() call can be used wherever you would use a unicode string (an object with type unicode) in Python. If you try to use it where a bytestring (a str object) is expected, things will not work as expected, since a ugettext_lazy() object doesn't know how to convert itself to a bytestring. You can't use a unicode string inside a bytestring, either, so this is consistent with normal Python behavior. For example:
This is fine: putting a unicode proxy into a unicode string.
u"Hello %s" % ugettext_lazy("people")
This will not work, since you cannot insert a unicode object
into a bytestring (nor can you insert our unicode proxy there)
"Hello %s" % ugettext_lazy("people")
[/Quote]
taken from here:
https://docs.djangoproject.com/en/dev/topics/i18n/translation/#working-with-lazy-translation-objects
Alan
I had the same issue just now. The problem was caused by incorrect Middleware order - I set LocaleMiddleware after CommonMiddleware. After I placed it between SessionMiddleware and CommonMiddleware, it seems to work correctly.
See more here: https://lokalise.com/blog/advanced-django-internationalization/
I know, the problem was solved a long ago, but it can be helpful for someone.

How can i add bengali font in a django web application

I want to create a quiz web application using django where the quiz question will be in Bengali. How can i generate the bengali font in my desired site.
Please if anyone tell me .. i will be grateful to him
Django is not involved in font rendering on the browser. Embedding a particular font via CSS is still problematical until today. You may find answers at How to embed fonts in HTML?.
In Django, you specify only the character codes. You may have to use unicode escape sequences in strings, unless you can enter Bengali characters directly. Bengali characters reside in the unicode range U+0981 to U+09FA. I assume that your target audience will have glyphs installed for those characters, so there may be no need to provide an embedded font at all.
You can use the following script to display a list of the defined Bengali unicode characters.
import sys
import unicodedata as ucd
try:
chr = unichr
except NameError:
# Python 3
unicode = str
def filter_bengali():
for i in range(256, sys.maxunicode + 1):
try:
name = ucd.name(chr(i))
if 'BENGALI' in name:
print(unicode('U+{0:04X} {1:<60} {2}').format(i, name, chr(i)))
except ValueError:
pass
if __name__ == '__main__':
filter_bengali()