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.
Related
My python application stops responding whenever I do anything "wx" a few times...whether that be clicking buttons, menus, inside the text area, etc.
This seems to be a problem with my use of windows hooks elsewhere in the program. When the two are used together, things go bad.
While the example below might not make much sense outside the context of the real application, it is what I came up with as a minimal example. I took everything out I could in order to try to diagnose the problem with minimal extra complexities.
It really seems like the second windows message pump called from the worker thread is the factor that makes it happen. If I comment that out, the app doesn't hang...or do anything useful...Hooks requires a pump, and I can't put it on my UI thread or it will the hooks will timeout, which led me to this POC in the first place...
If you run this and click the mouse a dozen times or so, you will notice the text blocks get garbled and then the app just hangs. Does anyone have any insight as to why?
I am using
python 2.7.16 32 bit
pyHook 1.5.1
wxPython 3.0.2.0 32bit for python 2.7
(update) I've also tried with the same results
python 2.7.16 32 bit
pyHook 1.5.1
wxPython 4.0.6 32 bit for python 2.7
We use these in the real application, because the my higher ups want to continue to support Windows XP (A whole different conversation)
main.py
import wx
from twisted.internet import wxreactor
from windows_hooks import WindowsHooksWrapper
from main_window import MainWindow
def main():
hook_wrapper = WindowsHooksWrapper()
hook_wrapper.start()
app = wx.App(False)
frame = MainWindow(None, 'Hooks Testing', hook_wrapper)
from twisted.internet import reactor
reactor.registerWxApp(app)
reactor.run()
hook_wrapper.stop()
if __name__ == "__main__":
wxreactor.install()
main()
windows_hooks.py
import pyHook
import threading
import pythoncom
class WindowsHooksWrapper(object):
def __init__(self):
self.hook_manager = None
self.started = False
self.thread = threading.Thread(target=self.thread_proc)
self.window_to_publish_to = None
print "HookWrapper created on Id {}".format(threading.current_thread().ident)
def __del__(self):
self.stop()
def start(self):
if self.started:
self.stop()
self.started = True
self.thread.start()
def stop(self):
if not self.started:
return
self.started = False
self.thread.join()
def on_mouse_event(self, event):
"""
Called back from pyHooks library on a mouse event
:param event: event passed from pyHooks
:return: True if we are to pass the event on to other hooks and the process it was intended
for. False to consume the event.
"""
if self.window_to_publish_to:
from twisted.internet import reactor
reactor.callFromThread(self.window_to_publish_to.print_to_text_box, event)
return True
def thread_proc(self):
print "Thread started with Id {}".format(threading.current_thread().ident)
# Evidently, the hook must be registered on the same thread with the windows msg pump or
# it will not work and no indication of error is seen
# Also note that for exception safety, when the hook manager goes out of scope, the
# documentation says that it unregisters all outstanding hooks
self.hook_manager = pyHook.HookManager()
self.hook_manager.MouseAll = self.on_mouse_event
self.hook_manager.HookMouse()
while self.started:
pythoncom.PumpMessages()
print "Thread exiting..."
self.hook_manager.UnhookMouse()
self.hook_manager = None
main_window.py
import threading
import wx
class MainWindow(wx.Frame):
def __init__(self, parent, title, hook_manager):
wx.Frame.__init__(self, parent, title=title, size=(800, 600))
self.hook_manager = hook_manager
self.CreateStatusBar()
menu_file = wx.Menu()
menu_item_exit = menu_file.Append(wx.ID_EXIT, "E&xit", " Terminate the program")
menu_help = wx.Menu()
menu_item_about = menu_help.Append(wx.ID_ABOUT, "&About", " Information about this program")
menu_bar = wx.MenuBar()
menu_bar.Append(menu_file, "&File")
menu_bar.Append(menu_help, "&Help")
self.SetMenuBar(menu_bar)
self.panel = MainPanel(self, hook_manager)
self.Bind(wx.EVT_MENU, self.on_about, menu_item_about)
self.Bind(wx.EVT_MENU, self.on_exit, menu_item_exit)
self.Show(True)
def on_about(self, e):
dlg = wx.MessageDialog(self, "A window to test Windows Hooks", "About Test Windows Hooks",
wx.OK)
dlg.ShowModal()
dlg.Destroy()
def on_exit(self, e):
self.Close(True)
class MainPanel(wx.Panel):
def __init__(self, parent, hook_manager):
self.hook_manager = hook_manager
hook_manager.window_to_publish_to = self
self.consuming = False
wx.Panel.__init__(self, parent)
self.textbox = wx.TextCtrl(self, style=wx.TE_MULTILINE | wx.TE_READONLY)
self.horizontal = wx.BoxSizer()
self.horizontal.Add(self.textbox, proportion=1, flag=wx.EXPAND)
self.sizer_vertical = wx.BoxSizer(wx.VERTICAL)
self.sizer_vertical.Add(self.horizontal, proportion=1, flag=wx.EXPAND)
self.SetSizerAndFit(self.sizer_vertical)
self.called_back_count = 0
def print_to_text_box(self, event):
self.called_back_count += 1
print "Printing message {} on Thread with Id {}".format(self.called_back_count,
threading.current_thread().ident)
self.textbox.AppendText('MessageName: {}\n'.format(event.MessageName))
self.textbox.AppendText('Message: {}\n'.format(event.Message))
self.textbox.AppendText('Time: {}\n'.format(event.Time))
self.textbox.AppendText('Window: {}\n'.format(event.Window))
self.textbox.AppendText('WindowName: {}\n'.format(event.WindowName))
self.textbox.AppendText('Position: {}\n'.format(event.Position))
self.textbox.AppendText('Wheel: {}\n'.format(event.Wheel))
self.textbox.AppendText('Injected: {}\n'.format(event.Injected))
self.textbox.AppendText('---\n')
I've also tried a version without Twisted and used wxPostEvent with a custom event instead, but we were suspecting that might be the problem, so I changed it to use twisted and it's still no good.
I'll post an edited listing with that in a bit.
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.
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.
I wrote global shortcut example for hide and show my windows with key like 'F12', I used python-xlib and some script named 'pyxhook' everything works fine except when i want to hide() and show() window few times my proccess turning a zombie, but same code working with hiding and showing just button.
#!/usr/bin/python
# -*- coding: utf-8; -*-
from gi.repository import Gtk, GObject
from pyxhook import HookManager
GObject.threads_init()
class Win(Gtk.Window):
def __init__(self):
super(Win, self).__init__()
self.connect('destroy', Gtk.main_quit)
self.button = Gtk.Button()
self.add(self.button)
self.resize(200,150)
self.show_all()
def handle_global_keypress(self, event):
if event.Key == 'F12':
if self.get_visible():
self.hide()
else:
self.show()
### this part works fine with button
#if self.button.get_visible():
# self.button.hide()
#else:
# self.button.show()
def main():
app = Win()
hm = HookManager()
hm.HookKeyboard()
hm.KeyDown = app.handle_global_keypress
hm.start()
Gtk.main()
hm.cancel()
if __name__ == "__main__":
main()
edit: i solved my problem using Keybinder library instead of coding pure python keybinder.
http://kaizer.se/wiki/keybinder/
I'm unable to answer your specific question but I might suggest another option. Guake console implements this very same behavior but using dbus:
http://guake.org/
In the dbusiface.py file you can find:
import dbus
import dbus.service
import dbus.glib
import gtk
import guake.common
dbus.glib.threads_init()
DBUS_PATH = '/org/guake/RemoteControl'
DBUS_NAME = 'org.guake.RemoteControl'
class DbusManager(dbus.service.Object):
def __init__(self, guakeinstance):
self.guake = guakeinstance
self.bus = dbus.SessionBus()
bus_name = dbus.service.BusName(DBUS_NAME, bus=self.bus)
super(DbusManager, self).__init__(bus_name, DBUS_PATH)
#dbus.service.method(DBUS_NAME)
def show_hide(self):
self.guake.show_hide()
Among others methods. This is worth to explore. Please also note that Guake is developed using PyGtk and not PyGObject, but anyway you can get some ideas.
I've made a gui in glade that I want to put in a python program. I was adapting the instructions from a tutorial I found online to load in my glade file (http://www.pygtk.org/articles/pygtk-glade-gui/Creating_a_GUI_using_PyGTK_and_Glade.htm). When I had problems I tried something basic (one button) calling it the same thing as in that tutorial, and copy pasting their code, and it still didn't work. I also took a look at (http://www.linuxjournal.com/article/6586?page=0,2), which has a function being called slightly differently ("self.wTree=gtk.glade.XML (gladefile,windowname)" instead of without windowname), and implemented an equivalent with mine and that didn't fix it. I definitely have pygtk working, I made something without using glade before and it worked fine. The error I'm getting is:
/usr/share/themes/NOX/gtk-2.0/gtkrc:233: Murrine configuration option "gradients"
is no longer supported and will be ignored.
(helloWorld.py:9804): libglade-WARNING **: Expected <glade-interface>. Got
<interface>.
(helloWorld.py:9804): libglade-WARNING **: did not finish in PARSER_FINISH state
Traceback (most recent call last):
File "helloWorld.py", line 31, in <module>
hwg = HellowWorldGTK()
File "helloWorld.py", line 22, in __init__
self.wTree = gtk.glade.XML(self.gladefile)
RuntimeError: could not create GladeXML object
I'm running xubuntu 11.04. The Murrine configuration thing comes up when any gtk application opens, but I included it in case it is relevant. Here's the code I took from the tutorial (but isn't working)
#!/usr/bin/env python
import sys
try:
import pygtk
pygtk.require("2.0")
except:
pass
try:
import gtk
import gtk.glade
except:
sys.exit(1)
class HellowWorldGTK:
"""This is an Hello World GTK application"""
def __init__(self):
#Set the Glade file
self.gladefile = "PyHelloWorld.glade"
self.wTree = gtk.glade.XML(self.gladefile)
#Get the Main Window, and connect the "destroy" event
self.window = self.wTree.get_widget("MainWindow")
self.window.show()
if (self.window):
self.window.connect("destroy", gtk.main_quit)
if __name__ == "__main__":
hwg = HellowWorldGTK()
gtk.main()
Try with this code:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import pygtk
pygtk.require("2.0")
import gtk
import gtk.glade
class HellowWorldGTK:
def __init__(self):
self.gladefile = "helloworld.glade"
self.glade = gtk.Builder()
self.glade.add_from_file(self.gladefile)
self.glade.connect_signals(self)
self.glade.get_object("MainWindow").show_all()
def on_MainWindow_delete_event(self, widget, event):
gtk.main_quit()
if __name__ == "__main__":
try:
a = HellowWorldGTK()
gtk.main()
except KeyboardInterrupt:
pass
Remember:
In Glade, Edit the "Preferences" of the file to "GTKBuilder" (not "libglade")
Your PyHelloWorld.glade is incorrect. Make sure you created it with the correct Glade application, there are Glade2 and Glade3 applications that can be installed and used. If you downloaded the file make sure it is correct. The error message says it all:
Expected <glade-interface>. Got <interface>
So the XML file has the interface tag, but PyGTK library expects glade-interface tag.
Since I always end up having problems with this, here is a Python 2.7 code that I use for one or the other:
for Libglade:
# needs libglade (not for gtk-builder)
import pygtk
pygtk.require("2.0")
import gtk
import gtk.glade
gladefile = "test-libglade.glade"
wTree = gtk.glade.XML(gladefile)
window = wTree.get_widget("MainWindow")
if (window):
window.connect("destroy", gtk.main_quit)
window.show_all() # must have!
gtk.main()
For GtkBuilder:
# needs gtk-builder (not for libglade)
import pygtk
pygtk.require("2.0")
import gtk
gladefile = "test-gtkbuilder.glade"
wTree = gtk.Builder()
wTree.add_from_file(gladefile)
window = wTree.get_object("MainWindow")
if (window):
window.connect("destroy", gtk.main_quit)
window.show_all() # must have!
gtk.main()
In Glade, you can just add a Window, call it MainWindow, and save two versions with the respective filenames as above for each format; and these snippets should work with them respeactively.
Hope this helps someone,
Cheers!
This works perfectly.
#!/usr/bin/python
import pygtk
pygtk.require("2.0")
import gtk
import gtk.glade
class SubinsWindow:
def __init__(self):
self.gladefile = "game.glade"
self.glade = gtk.Builder()
self.glade.add_from_file(self.gladefile)
self.glade.connect_signals(self)
self.win=self.glade.get_object("window1") # Window Name in GLADE
self.win.show_all()
if __name__ == "__main__":
a = SubinsWindow()
gtk.main()
If you are using GTK+3 in python, see builder.
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
class Handler:
def onDestroy(self, *args):
Gtk.main_quit()
def onButtonPressed(self, button):
print("Hello World!")
builder = Gtk.Builder()
builder.add_from_file("builder_example.glade")
builder.connect_signals(Handler())
window = builder.get_object("window1")
window.show_all()
Gtk.main()