Category Archive : python相关

wxpython 的pub/sub发布订阅,夸窗口传递信息

我们经常会用到两个窗口之间互相传递信息,或者把一个窗口里,文本框输入的值,传递到另外一个frame的另外一个文本框里,
这个时候,我们可以使用wxpython的pub/sub方法。
test.py


class Main(wx.App):
          def __init__(self):
                  #mainFrame 是用wxglade画的一个frame导出来的python文件
                   self.frame1 = mainFrame.MyFrame(None, wx.ID_ANY, "")
                   self.frame1.Show()
                   self.children=test2.children()
                  #定义一个name1属性,值来自于窗口上的文本框控件
                   self.name1 = self.frame1.text_ctrl_1
                  #  离开焦点,就把fram1的文本框里的值传入children的另外一个文本框内
                  self.name1 .Bind(wx.EVT_COMMAND_KILL_FOCUS, self.save)
                  #发布一个叫in_sync的主题,触发sync函数
                   pub.subscribe(self.sync, "in_sync")
          def sync(self, msg):
                  #给children的text_ctrl_2字段设置值
                  self.children.frame.text_ctrl_2.SetValue(msg)
          def save(self,evt):
                    value=self.name1.GetValue()
                    #调用一下in_sync方法,如果in_sync方法在别的class里,
                    #也是可以调用pub.sendMessage成功的
                    self.children.in_sync(value)

test2.py

class children(wx.App):
           def __init__(self):
                  #mainFrame 是用wxglade画的一个frame导出来的python文件
                   self.frame = mainFrame.MyFrame(None, wx.ID_ANY, "")
                   self.frame.Show()
           def in_sync(text):
                 #订阅"in_sync"主题
                 wx.CallAfter(pub.sendMessage, "in_sync", msg=text)

wxpython 根据item的名字找到tree_ctrl对应的节点

业务场景,需要在一个tree_ctrl中找到一个节点,并且给该节点添加子节点

def get_item_by_label(self, tree, search_text, root_item):
    item, cookie = tree.GetFirstChild(root_item)
    while item.IsOk():
        text = tree.GetItemText(item)
        if text.lower() == search_text.lower():
            return item
        if tree.ItemHasChildren(item):
            match = self.get_item_by_label(tree, search_text, item)
            if match.IsOk():
                return match
        item, cookie = tree.GetNextChild(root_item, cookie)
    return wx.TreeItemId()
result = get_item_by_label(tree, '已有节点', tree.GetRootItem())
if result.IsOk():
    print('We have a match!')
    new_item = tree.AppendItem(result , "新节点")

wxpython一个event,多个handler,先绑定的后执行

Q:为什么会有一次event,多次handler的需求呢?
A:因为wxpython 目前有一个BUG,在一个event函数中,无法使用两次Dialog.showModal方法。当第一个Dialog消失后,第二个dialog再弹出,会造成系统卡死。所以必须把两个dialog.showModal放入两个event中。
绑定规则:先绑定的后执行
给按钮sync_button 绑定三个事件,第一次执行的在下,第二次执行的在上,如下:
给按钮绑定事件

        self.sync_button.Bind(wx.EVT_BUTTON, self.sync_three_event)
        self.sync_button.Bind(wx.EVT_BUTTON, self.sync_two_event)
        self.sync_button.Bind(wx.EVT_BUTTON, self.sync_one_event)

编写事件的event

    def sync_one_event(self, event):
        print("第一次触发事件" )
        event.Skip()
    def sync_two_event(self, event):
        print("第二次触发事件" )
        event.Skip()
    def sync_three_event(self, event):
        print("第三次触发事件" )
        event.Skip()

最后触发的结果是:

第一次触发事件
第二次触发事件
第三次触发事件

实现wxpython的拖拽上传功能

实现wxpython的拖拽上传功能
1.从FileDropTarget继承

···
class MyFileDropTarget(wx.FileDropTarget):
def init(self):
wx.FileDropTarget.init(self)
def OnDropFiles(self, x, y, filepath):
# file=os.path.basename(filepath[0])
#各种文件操作之类的
return False ···

2.给panel绑定拖拽功能

    filedrop = MyFileDropTarget()
    self.frame.panel_2.SetDropTarget(filedrop)

3.注意事项:
一次只能拖拽一个文件上去,如果一次拖拽A,B,C三个文件。最后filepath只能获取到A文件,B,C丢失

python2.7-wxpython4.0.1-pyinstaller打包的正确用法

hi 各位看官,本文是截止2018年7月4日,基于python2.7开发wxpython时的打包正确用法。(2018年11月16日,发现pyinstall 3.4版本解决了这个问题了)
坑1:
wxpython的最新版本为4.0.3 但是因为4.0.3引入了新的pubsub 4.0 不兼容python2.7。所以如果用python2.7的同学必须降级到wxpython 4.0.1版本
坑2:
打包方面,我们可以用pyinstaller打包。但是pip上,pyinstaller最新的版本是3.3.1 版本,此版本上有bug https://github.com/pyinstaller/pyinstaller/issues/2215
但是后期,pyinstall的作者修复了此bug在dev版本上,所以我们只有去github上 安装最新的dev版本才能打包成功
踩坑表现:

Traceback (most recent call last):
  File "<string>", line 41, in <module>
  File "<string>", line 36, in walk_packages
  File "<string>", line 20, in walk_packages
  File "d:program filespythonpython27libsite-packageswx-3.0-mswwxlibpubsubcorearg1__init__.py", line 16, in <module>
    raise RuntimeError(msg)
RuntimeError: Should not import this directly, used by pubsub.core if applicable

出现pubsub报错,因为wxpython 2.8.0之前的版本用的是corearg1 所以为了能顺利打包,我们要进行如下操作:
填坑方法:
1.pip装wxpython 4.0.1版本

pip install wxpython==4.0.1

2.pip装dev版本pyinstaller

 pip install git+https://github.com/pyinstaller/pyinstaller

3.重新打包主入口main.py

pyinstaller -D main.py

wxpython之tree_ctrl图标与点击事件


如何用wxpython展示一个如图所示的的树呢?
wxpython的treectrl功能可以实现。
1.首先我们可以用wxglade画前端frame界面,添加一个TreeCtrl ,或者多个TreeCtrl,添加root.每一个tree只能有一个root

self.tree_ctrl_1 = wx.TreeCtrl(self.panel_1, wx.ID_ANY)
my_defect_root =self.my_tree.AddRoot("My Defect")

2.然后给设置图片list 用来给根节点和树节点放不一样的图片

self.image_list = wx.ImageList(16, 16)
self.case_icon =self.image_list.Add(wx.Image("resource/image/icon/bookmark.png",
                                              wx.BITMAP_TYPE_PNG).Scale(16, 16).ConvertToBitmap())
self.folder_icon =self.image_list.Add(wx.Image("resource/image/icon/document.png",
                                                wx.BITMAP_TYPE_PNG).Scale(16, 16).ConvertToBitmap())

3.然后给树设置imagelist

self.project_tree.SetImageList(self.image_list)

#注意千万不能用AssignImageList ,这样写虽然运行没问题,但是关闭窗口时会导致crash,一定要用SetImageList
4.给每一个节点设置图片和文字

status_node =self.my_tree.AppendItem(my_defect_root, “open”)
self.my_tree.SetItemImage(status_node, self.folder_icon, wx.TreeItemIcon_Normal)

5.给节点绑定双击事件

self.my_tree.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self.show_defect_info)
def show_defect_info(self, event):
    item = event.GetItem()
    self.my_tree.Expand(item)
    print(self.my_tree.GetItemText(item))

苏ICP备18047533号-1