第一次接触到wxpython,在网上找到一个简单的界面显示代码,复制到spyder3编辑中进行运行出现错误,(“module 'wx' has no attributte 'App'”),但在python3.6的IDLE编辑器上运行没有错误。具体程序如下:
import wx
app = wx.App()
frame = wx.Frame(None,title="my GUI")
frame.Show(1)
app.MainLoop()
于是在网上找到一些解决方法:
1)wx.py 文件名与插件wx 重名了;【命名py脚本时,不要与python预留字,模块名等相同;删除该库的.pyc文件(因为py脚本每次运行时均会生成.pyc文件;在已经生成.pyc文件的情况下,若代码不更新,运行时依旧会走pyc,所以要删除.pyc文件),重新运行代码;或者找一个可以运行代码的环境,拷贝替换当前机器的.pyc文件即可
解决:
把wx.py 改成 editor.py 执行成功弹出一个文本框,如附件截图:
D:\ProgramFiles64\Anaconda36\Lib\site-packages\IPython\terminal\pt_inputhooks\wx.py文件修改为editor.py,再执行。】
2)有的说是版本问题;
我按方法1修改了之后,还是没有成功,后来我将spyder重启,并且所有设置恢复默认之后,再执行又没有错误,具体原因在哪里我还是没有搞清楚。
下面我们来实现简单界面设计:
最小的wxpython程序,叫它hello world程序吧。功能就是产生一个窗口,就像是我们VC中新建的一个单文档的MFC类似,不过没有菜单什么的,只有一个框架窗口。其实严格来说,wxpython不叫这个为窗口,而是“frame”。实现代码有如下几种:
一>import wx
app = wx.PySimpleApp()
frame = wx.Frame(None, -1, "Hello World")
frame.Show()
app.MainLoop()
二>import wx
app = wx.App()
frame = wx.Frame(None, -1, "Hello World")
frame.Show()
app.MainLoop()
三>import wx
class MyApp(wx.App):
def OnInit(self):
frame=wx.Frame(parent=None,title='Hello wxpython')
frame.Show()
return True
app=MyApp()
app.MainLoop()
【下面部分转载博主:http://blog.sina.com.cn/s/blog_4b5039210100eykc.html】
可以看到,frame上面什么都没有。但所谓麻雀虽小,五脏俱全,从这个最小的程序我们就能看出一个wxpython程序都包含哪些东西:
1 导入wxpython库,或者里面的方法( import wx)
2 创建一个应用类的子类(继承于wxpython中的App类,class MyApp(wx.App):)
3 定义应用子类初始化方法(OnInit())
4 创建应用类的实例
5 进入应用类的消息循环 MainLoop
我们主要看一下,应用类的OnInit函数,在这个初始化方法中,我们生成了一个wx.frame对象的一个实例,因为这个程序比较简单,所以这个过程放到了OnInit方法中,一般情况下,我们都是定义一个继承于wx..Frame的子类(类似于MyApp一样),这个我们在以后会经常看到。
还有一点,我们在App类初始化没有调用__init__()这个方法,这意味着我们这个子类创建的过程中,按照类的继承性,这个方法会被自动调用。当然我们可以重新定义这个方法,但是一定要在子类中调用一下基类的__init__()方法。例如:
class App(wx.App):
def __init__(self):
wx.App.__init__(self)
#Do something here.....
最后创建应用类实例和进入消息循环和Tkinter差不多,就不说了。
上面例子只是为了说明wxpython的基本用法,但是那个代码其实扩展性很差,那么,作为一般wxpython程序应该怎么写呢?我们看下面的代码
#!/usr/bin/env Python
“”” hello.py is a starting point for a wxpython program”””
import wx
class Frame(wx.Frame):
pass
class App(wx.App):
def OnInit(self):
self.frame=Frame(parent=None,title='Hello wxpython')
self.frame.Show()
self.SetTopWindow(self.frame)
return True
if __name__=='__main__':
app=App()
app.MainLoop()
第一行是注释行,在windows中不是必须的,但是在linux中需要有,它告诉操作系统python解释器在什么地方,有了这个以后,我们就可以在linux命令行里直接输入文件名运行了。虽然windows中这个不是必须的,但是为了兼容性跨平台,这个一般还是要有的。
第二行的三引号所夹内容就不说了。
下面第一个类是继承于wx..Frame的frame类。这里我们什么没做,其实在这里我们可以做很多事,比如创建一些组件(按钮,文本框等待),这样把frame单独拿出来,为了使程序更清晰可读。
第二个类是继承于wx..App的App类。和第一个程序类似,只不过这里的frame换成了调用Frame,实例化得对象。
self.SetTopWindow(self.frame),这个其实是把self.frame作为了主frame,因为一个程序中可能会有多个frame。通过这个可以设置哪个frame是最顶层的主frame。
最后的if语句就是这个程序的入口。
下面,我们把上面的例子稍微扩充一点。
#!/usr/bin/env python
""" Hello,wxPython program."""
import wx #import the wxPackage
class Frame(wx.Frame):
"""Frame class that display an image."""
def __init__(self,image,parent=None,id=-1,
pos=wx.DefaultPosition,
title='Hello wxPython'):
temp=image.ConvertToBitmap() #Displaying the image
size=temp.GetWidth(),temp.GetHeight()
wx.Frame.__init__(self,parent,id,title,pos,size)
self.bmp=wx.StaticBitmap(parent=self,bitmap=temp)
class App(wx.App):
"""Application class."""
def OnInit(self):
image=wx.Image('wxpython.jpg',wx.BITMAP_TYPE_JPEG)
self.frame=Frame(image)
self.frame.Show()
self.SetTopWindow(self.frame)
return True
def main():
app=App()
app.MainLoop()
if __name__=='__main__':
main()
实现是在frame上显示一张照片。结果为: