I ran the following python code
import wx
class myframe(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, -1, title="Hello")
self.InitUI()
def InitUI(self):
menubar = wx.MenuBar()
fileMenu = wx.Menu()
qmi = wx.MenuItem(fileMenu, 100, '&Quit\tCtrl+Q')
qmi.SetBitmap(wx.Image(
'quit.png', wx.BITMAP_TYPE_ANY).ConvertToBitmap())
fileMenu.AppendItem(qmi)
self.Bind(wx.EVT_MENU, self.OnQuit, id=100)
menubar.Append(fileMenu, '&File')
self.SetMenuBar(menubar)
self.SetSize((250, 200))
self.SetTitle('Icons and shortcuts')
self.Centre()
self.Show(True)
def OnQuit(self, e):
self.Close()
def main():
ex = wx.App()
myframe()
ex.MainLoop()
if __name__ == '__main__':
main()
The above code is throwing the message
qmi.SetBitmap(wx.Image('quit.png', wx.BITMAP_TYPE_ANY).ConvertToBitmap())
File "C:\Python27\lib\site-packages\wx-3.0-msw\wx\_core.py", line 2882, in __init__
_core_.Image_swiginit(self,_core_.new_Image(*args, **kwargs))
PyAssertionError: C++ assertion "strcmp(setlocale(LC_ALL, NULL), "C") == 0" failed at ..\..\src\common\intl.cpp(1449) in wxLocale::GetInfo(): You probably called setlocale() directly instead of using wxLocale and now there is a mismatch between C/C++ and Windows locale.
Things are going to break, please only change locale by creating wxLocale objects to avoid this!
I am new to python and completely unable to solve this.
Is there anyway to find the solution to this.
I am using python 2.7.10 and wxpython 3.0.2.0 in a windows machine.
I had a similar issue that only occurred following a cxFreeze with wxPhoenix. I worried that the solution above could cause issues on a machine that wasn't wx.LANGUAGE_ENGLISH, so instead, I recorded the locale before any imports (which I suspected were changing the locale):
import wx
locale = wx.Locale.GetSystemLanguage()
And then reset it after my imports and after creating the app:
app = wx.App(redirect=False)
app.locale = wx.Locale(locale)
This worked for me.
The solution is to modify the locale and it is working.
Modified the code as here:
def main():
ex = wx.App()
ex.locale = wx.Locale(wx.LANGUAGE_ENGLISH)
myframe()
ex.MainLoop()
Locale is conflicting with system locale. So modified it in the code for this program.
This was fixed if you included some wx.App code:
def InitLocale(self):
import sys
if sys.platform.startswith("win") and sys.version_info > (3, 8):
import locale
locale.setlocale(locale.LC_ALL, "C")
Also, it was fixed correctly in wx4.2 which was just released. If you hit this bug, it was never you. wx and python were disagreeing about the locale. It hits intermittently and only for some non-English locale. 4.2 fixes, or the above code snipple to get rid of the local for post py3.8.
Related
My wxPython GUI either quits with a Segmentation Fault or fails to quit at all using the standard options. The only successful quit option (no errors) is wx.Exit, which I understand is not a great practice. I've traced the issues down to a few factors, but I'm scratching my head as to why they are having this effect.
Using the wxPython inspector (wx.lib.inspection.InspectionTool()), I've been able to determine that a FigureFrameWxAgg is being created when I run certain pylab functions (pylab.xticks() is the function that creates it here, but I haven't tracked down every single function that has this effect). I don't know what this window is for. It's invisible and doesn't appear to do anything. However, this window totally messes up the shutdown of my GUI. If I use self.Destroy, Python doesn't shut down fully. If I use sys.exit, I get a Segmentation fault. I need to catch the wx.EVT_CLOSE so that I can prompt the user to save his/her work.
Here is the code for a simplified version of the GUI:
import matplotlib
matplotlib.use('WXAgg')
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigCanvas
import wx
import wx.grid
import wx.lib.scrolledpanel
import wx.lib.inspection
import sys
import pylab
class my_frame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, -1, 'Many Rows')
self.InitUI()
def InitUI(self):
self.panel = wx.Window(self, size=(200, 200))
hbox_all= wx.BoxSizer(wx.HORIZONTAL)
self.create_menubar()
self.fig1 = pylab.Figure((5, 5), dpi=100)
self.canvas1 = FigCanvas(self.panel, -1, self.fig1)
self.fig1.text(0.01,0.98,"Arai plot",{'family':'Arial', 'fontsize':10, 'style':'normal','va':'center', 'ha':'left' })
self.araiplot = self.fig1.add_axes([0.1,0.1,0.8,0.8])
self.araiplot.clear()
self.araiplot.plot(range(5),range(5),lw=0.75,clip_on=False)
xt = pylab.xticks()
grid = wx.grid.Grid(self.panel)
grid.ClearGrid()
grid.CreateGrid(100, 100)
grid.AutoSize()
hbox_all.AddSpacer(self.canvas1)
hbox_all.AddSpacer(20)
hbox_all.AddSpacer(grid)
hbox_all.AddSpacer(20)
self.panel.SetSizer(hbox_all)
hbox_all.Fit(self)
self.Centre()
self.Show()
def create_menubar(self):
"""
Create menu bar
"""
self.menubar = wx.MenuBar()
menu_file = wx.Menu()
menu_file.AppendSeparator()
m_exit = menu_file.Append(wx.ID_EXIT, "Quit", "Quit application")
self.Bind(wx.EVT_CLOSE, self.on_menu_exit)
self.menubar.Append(menu_file, "&File")
self.SetMenuBar(self.menubar)
def on_menu_exit(self, event):
self.Destroy() # this doesn't quit Python fully, unless I comment out 'matplotlib.use('WXAgg')'
#for w in wx.GetTopLevelWindows():
# if w.Title == 'Figure 1':
# w.Destroy() # if I pre-destroy the FigureFrameWxAgg window, I get a PyDeadObjectError when I run self.Destroy
# self.Destroy() #
# wx.Exit() # forces the program to exit, with no clean up. works, but not an ideal solution
#sys.exit() # program closes, but with segmentation error
#self.Close() # creates infinite recursion error, because we have a binding to wx.EVT_CLOSE
if __name__ == '__main__':
app = wx.PySimpleApp(redirect=False)
app.frame = my_frame()
if '-i' in sys.argv:
wx.lib.inspection.InspectionTool().Show()
app.MainLoop()
To add one more level of complexity, the Segmentation Fault with sys.exit() only happens with my brew installed Python. Sys.exit() works fine with Canopy Python.
My questions are: how can I fix this error? And, is using wx.Exit() really so bad?
There are several issues with your example:
Do not use pylab in GUI applications, because is brings its own mainloop (which will not quit when the wxPython mainloop quits). You had to kill pylab.
# both not required
# matplotlib.use('WXAgg')
# import pylab
# use instead
from matplotlib.figure import Figure
...
def __init__(# ...
...
self.fig1 = Figure((5, 5), dpi=100)
Your menu item "Close" does not work (at least not on Windows). wx.ID_EXIT is meant for buttons in dialogs. Do not ask me which predefined IDs are meant for menus.
ID_QUIT = wx.NewId()
menu_file.Append(ID_QUIT , "Quit", "Quit application")
#
self.Bind(wx.EVT_MENU, self.on_quit, id=ID_QUIT)
def on_quit(self, evt):
self.Close()
In this case it is not necessary to bind to wx.EVT_CLOSE. If you want to do something on the close event, you have to skip it. When you skip it, wxPython will deal with it on its own.
self.Bind(wx.EVT_CLOSE, self.on_close)
...
def on_close(self, evt):
# you can veto the close here or perform cleanup
evt.Skip()
If you change your code accordingly, wxPython will close everything properly.
I agree with the answer from #nepix32 on not using pylab but use the OOP approach of Matplotlib. However, in my case, I still need the matplotlib.use('WX') for the application to show.
I have the same problem of wxpython GUI application not terminated properly if a Matplotlib figure is displayed even if I'm not using pylab or pyplot.
My workaround is to pass the app object to the wx.Frame class and call app.Exit at EVT_CLOSE.
class my_frame(wx.Frame):
def __init__(self, app=None):
...
self.InitUI()
self.Bind(wx.EVT_CLOSE, lambda evt: app.Exit())
...
if __name__ == '__main__':
...
app.frame = my_frame(app)
...
I am up for anyone who can suggest cleaner solution. To be honest, I'm still new to wxpython.
I was working through the third video in this tutorial series in my effort to learn WxPython. I typed the code as in the video but an error is still returned. I am guessing this has something to do with the WxPython or Python version used. He is using Python 2.4, I am using 2.7.5 and I don't know what WxPython version he is using but I am using 3.0.0.
This is the code:
import wx
class MainWindow(wx.Frame):
def __init__(self,parent,id,title):
wx.Frame.__init__(self,parent,wx.ID_ANY,title,size = (400,200), style = wx.DEFAULT_FRAME_STYLE | wx.NO_FULL_REPAINT_ON_RESIZE
self.control = wx.TextCtrl(self,1,style = wx.TE_MULTILINE)
self.Show(True)
app = wx.PySimpleApp()
frame = MainWindow(None,-1,"Small Editor")
app.MainLoop()
Invalid syntax is returned for self.control but I don't know why.
Any help is appreciated,
Fluffy
It looks like you're missing the final enclosing parenthesis on the line directly above.
Generally speaking, syntax errors are typically due to misspellings, missing characters, or other such mistakes, and can either be found on the line indicated by the stacktrace or the line directly above.
Once the parenthesis is added, the below code runs for me:
import wx
class MainWindow(wx.Frame):
def __init__(self,parent,id,title):
wx.Frame.__init__(self,parent,wx.ID_ANY,title,size = (400,200), style = wx.DEFAULT_FRAME_STYLE | wx.NO_FULL_REPAINT_ON_RESIZE)
self.control = wx.TextCtrl(self,1,style = wx.TE_MULTILINE)
self.Show(True)
app = wx.PySimpleApp()
frame = MainWindow(None,-1,"Small Editor")
app.MainLoop()
I was trying to get fullscreen support for a wxPython app using the code in the answer from this stackoverflow question wxPython MacOS X Lion full screen mode
My Error
Traceback (most recent call last):
File "test_mac_fullscreen.py", line 36, in <module>
frame = Frame()
File "test_mac_fullscreen.py", line 29, in __init__
SetFullScreenCapable(self)
File "test_mac_fullscreen.py", line 16, in SetFullScreenCapable
window = frameobj.window()
AttributeError: 'NSHIObject' object has no attribute 'window'
My Code (just copied and pasted into one file from the above link)
# from https://stackoverflow.com/questions/12328143/getting-pyobjc-object-from-integer-id
import ctypes, objc
_objc = ctypes.PyDLL(objc._objc.__file__)
# PyObject *PyObjCObject_New(id objc_object, int flags, int retain)
_objc.PyObjCObject_New.restype = ctypes.py_object
_objc.PyObjCObject_New.argtypes = [ctypes.c_void_p, ctypes.c_int, ctypes.c_int]
def objc_object(id):
return _objc.PyObjCObject_New(id, 0, 1)
def SetFullScreenCapable(frame):
frameobj = objc_object(frame.GetHandle())
NSWindowCollectionBehaviorFullScreenPrimary = 1<<7
window = frameobj.window()
newBehavior = window.collectionBehavior() | NSWindowCollectionBehaviorFullScreenPrimary
window.setCollectionBehavior_(newBehavior)
import wxversion
wxversion.select('2-osx_cocoa') # require Cocoa version of wxWidgets
import wx
class Frame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None)
self.Bind(wx.EVT_CLOSE, self.OnClose)
wx.Button(self, label="Hello!") # test button to demonstrate full-screen resizing
SetFullScreenCapable(self)
def OnClose(self, event):
print "Closing"
exit()
if __name__ == "__main__":
app = wx.App(False)
frame = Frame()
frame.Show()
app.MainLoop()
print "running app loop"
While this is rather late, recently looking at this it suddenly clicked.
If you notice in the error it states a class NSHIObject (HI I am guessing stands for Human Interface) this has to do with the backend that wxPython uses, the archaic Carbon (as in this case) or the updated Cocoa. In earlier versions only Carbon was available but with 2.9.5 (IIRC) Cocoa is available (and I believe it has sense moved to 3.0 with Cocoa or Carbon ). Simply reinstall with a cocoa version and it works.
For the following simple wxPython snippets:
import sys
import wx
class MyApp(wx.App):
def OnInit(self):
self.frame = wx.Frame(None, title="Simple wxPython App")
self.frame.Show()
self.SetTopWindow(self.frame)
return True
def main(argv=sys.argv[:]):
app = MyApp()
app.MainLoop()
return 0
if __name__ == '__main__':
sys.exit(main())
I always got the warning message "R0904: 12:MyApp: Too many public methods" from Pylint. How can I prevent that?
# pylint: disable=R0904
Stick that at the top of the offending class.
On older versions of Pylint, you have to use
# pylint: disable-msg=R0904
Unfortunately, if you ever upgrade to a more recent version you'll have to write a sed script to replace all instances of # pylint: disable-msg with # pylint: disable.
I've been using Tix to create a comboBox and it causes an intermittent crash if the entry box is left empty.
I'm new to Python and very new to GUI programming so I've been using example to teach myself stuff.
When using the following example code, you should be able to enter a value into the entry box or select form the dropdown menu, however if you leave the entry field empty and press go it will cause the python to crash.
import Tix
import tkMessageBox
class App(object):
def __init__(self, window):
window.winfo_toplevel().wm_title("test")
self.window = window
self.combo = Tix.ComboBox(window)
self.combo.insert(Tix.END, 'thing1')
self.combo.insert(Tix.END, 'thing2')
self.combo.entry['state'] = "normal"
self.combo['editable'] = True
self.combo.pack()
button = Tix.Button(window)
button['text'] = "Go"
button['command'] = self.go
button.pack()
def go(self):
tkMessageBox.showinfo('info', self.combo['selection'])
if __name__ == '__main__':
root = Tix.Tk()
App(root)
root.mainloop()
=========================
CRASH DETAILS :
Problem signature:
Problem Event Name: APPCRASH
Application Name: python2.7.exe
Application Version: 0.0.0.0
Application Timestamp: 4cfbf049
Fault Module Name: ntdll.dll
Fault Module Version: 6.1.7600.16385
Fault Module Timestamp: 4a5bdb3b
Exception Code: c0000005
Exception Offset: 0002e23e
OS Version: 6.1.7600.2.0.0.256.48
Locale ID: 2057
Additional Information 1: 0a9e
Additional Information 2: 0a9e372d3b4ad19135b953a78882e789
Additional Information 3: 0a9e
Additional Information 4: 0a9e372d3b4ad19135b953a78882e789
So
A] is it something the example is doing wrong ?
B] is there a better way?
C] Should I be using Tix at all ?
I've noticed that some people seem to shy away from Tix and only use Tkinter. is there a reason for this? Should I not be using Tix ?
++++++++++++++++++++++++++++
Ok so I managed to monkeypatch this by adding value =' ' so the return string is not empty and then lstrip() the value when I need it.
self.combo = Tix.ComboBox(window, value =' ')
...
tkMessageBox.showinfo('info', self.combo['selection'].lstrip())
Very ugly but stops me from crashing for now; until someone wiser can give me a better answer.
If the user deletes the space and then presses 'go' it will of cause crash again!
I am not Tix expert, but this should fix the problem:
tkMessageBox.showinfo('info', self.combo.entry.get())
In between the lines, I would recommend using wxPython for learning GUI programming. It was great for me as a learning environment.
import wx
class MainWin(wx.Frame):
def __init__(self, *args, **kwargs):
wx.Frame.__init__(self, *args, **kwargs)
self.combo = wx.ComboBox(self, choices=["Thing 1", "Thing 2"])
self.button = wx.Button(self, label="Go")
self.button.Bind(wx.EVT_BUTTON, self.OnButton)
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.sizer.Add(self.combo, 0, wx.EXPAND)
self.sizer.Add(self.button, 0, wx.EXPAND)
self.SetSizerAndFit(self.sizer)
self.Show()
def OnButton(self, e):
wx.MessageBox(self.combo.GetValue())
app = wx.App(False)
main_win = MainWin(None)
app.MainLoop()