【问题标题】:Py2app prevents wxpython opening second wx.FramePy2app 阻止 wxpython 打开第二个 wx.Frame
【发布时间】:2014-05-20 15:13:23
【问题描述】:

我有一个处理 Quicktime 文件的 python 脚本,虽然这个过程可能需要很长时间才能执行和完成,但我打开了第二个窗口(它打开并保持在其他所有内容之上,说“请稍候”,BusyWindow类),然后在完成后关闭。这一切在 python 脚本形式中都可以正常工作,但是当创建一个 Py2app 时,它捆绑了包括 wxpython 在内的所有内容,第二个窗口无法打开。如果我再次运行它仍然打开,第二个窗口现在打开。我已经看到另一个关于这个问题的帖子,但没有修复,请问有人有什么建议吗?

import wx
import os
import os.path
import inspect
import csv
import subprocess
import sys
import shutil
import re
import urllib2
import threading
from subprocess import Popen, PIPE

class ScrolledWindow(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title, size=(510, 370), style=wx.DEFAULT_FRAME_STYLE & ~ (wx.RESIZE_BORDER | 
                                                wx.RESIZE_BOX | 
                                                wx.MAXIMIZE_BOX))

        self.tabbed = wx.Notebook(self, -1, style=(wx.NB_TOP))

        run_params = {}
        run_params["dropList1"] = ['HD 1920x1080', 'PAL 4x3', 'PAL 16x9', 'NTSC 4x3', 'NTSC 16x9']
        run_params["dropList2"] = ['Progressive', 'Interlaced']
        run_params["running"] = False
        run_params["1stRun"] = True

        self.CreateStatusBar()
        menuBar = wx.MenuBar()
        menu = wx.Menu()
        self.SetMenuBar(menuBar)
        panel = wx.Panel(self, -1)

        self.Centre()
        self.Show()

        self.filePrep = PrepFile(self.tabbed, run_params)

        self.tabbed.AddPage(self.filePrep, "File Prep")

class PrepFile(wx.Panel):
    def __init__(self, parent, run_params):
        wx.Panel.__init__(self, parent)

        self.run_params = run_params
        self.fieldChoice = 'Progressive'
        self.formatOption = 'HD 1920x1080'

        outputOption = '''Format'''
        wx.StaticText(self, -1, outputOption, (33, 22), style=wx.ALIGN_CENTRE)


        self.choice1 = wx.Choice(self, pos=(35, 40), choices=self.run_params["dropList1"])
        self.choice1.SetSelection(0)
        self.choice1.SetFocus()
        self.choice1.Bind(wx.EVT_CHOICE, self.selectOption)

        fieldSetText = '''Fields'''
        wx.StaticText(self, -1, fieldSetText, (33, 82), style=wx.ALIGN_CENTRE)

        self.choice2 = wx.Choice(self, pos=(35, 100), choices=self.run_params["dropList2"])
        self.choice2.SetSelection(0)
        self.choice2.SetFocus()
        self.choice2.Bind(wx.EVT_CHOICE, self.fieldSet)

        self.buttonClose = wx.Button(self, -1, "Quit", pos=(195, 250))
        self.buttonClose.Bind(wx.EVT_BUTTON, self.OnClose)

        greyBox = wx.StaticBox(self, -1, '', pos=(20, 15), size=(235, 130))

        outputtxt3 = '''Drag and Drop Quicktimes'''
        wx.StaticText(self, -1, outputtxt3, pos=(35, 170), style=wx.ALIGN_CENTRE)

        self.drop_target = MyFileDropTarget(self)
        self.SetDropTarget(self.drop_target)
        self.tc_files = wx.TextCtrl(self, wx.ID_ANY, pos=(38, 190), size=(200, 25))
        self.buttonSubmit = wx.Button(self, -1, "Submit", pos=(250,190))
        self.buttonSubmit.Bind(wx.EVT_BUTTON, self.submit)

    def EvtRadioBox(self, event):
        self.mode = (event.GetString())

    def selectOption(self, e):
        self.formatOption = self.choice1.GetStringSelection()

    def fieldSet(self, e):
        self.fieldChoice = self.choice2.GetStringSelection()

    def setSubmissionDrop(self, dropFiles):
        """Called by the FileDropTarget when files are dropped"""
        self.tc_files.SetValue(','.join(dropFiles))
        self.selectedFiles = dropFiles
        print self.selectedFiles

    def submit(self, edit):
        self.run_params["running"] = True
        busy = BusyWindow(None, self.run_params)
        for item in self.selectedFiles:
            if os.path.isdir(item):
                print "It is a folder!"
                for root, dirs, files in os.walk(item):
                    for file1 in files:
                        if file1.endswith(".mov"):
                            currentFile = os.path.join(root, file1)
                            self.jesFile(currentFile)
            else:
                if item.endswith(".mov"):
                    self.jesFile(item)
        busy.Close()

    def OnClose(self, e):
        CloseApp()

    def jesFile(self, currentFile):
        if self.fieldChoice == "Interlaced":
            if self.formatOption == 'HD 1920x1080':
                self.preset = 'HD 1080i'
            elif self.formatOption == 'PAL 4x3':
                self.preset = 'PAL 4x3i'
            elif self.formatOption == 'PAL 16x9':
                self.preset = 'PAL 16x9i'
            elif self.formatOption == 'NTSC 4x3':
                self.preset = 'NTSC 4x3i'
            elif self.formatOption == 'NTSC 16x9':
                self.preset = 'NTSC 16x9i'
        else:
            if self.formatOption == 'HD 1920x1080':
                self.preset = 'HD 1080p'
            elif self.formatOption == 'PAL 4x3':
                self.preset = 'PAL 4x3p'
            elif self.formatOption == 'PAL 16x9':
                self.preset = 'PAL 16x9p'
            elif self.formatOption == 'NTSC 4x3':
                self.preset = 'NTSC 4x3p'
            elif self.formatOption == 'NTSC 16x9':
                self.preset = 'NTSC 16x9p'

        # Apply JES settings
        jesCommand = './JES/JES\ Extensifier.app/Contents/MacOS/JES\ Extensifier   -p   ' + '"' + self.preset + '"' + '   ' + '"' + currentFile + '"'
        print jesCommand
        self.process1 = Popen(jesCommand, shell=True, stdin=PIPE)
        self.assignAudio(currentFile)

class MyFileDropTarget(wx.FileDropTarget):
    """"""
    def __init__(self, window):
        wx.FileDropTarget.__init__(self)
        self.window = window

    def OnDropFiles(self, x, y, filenames):
        self.window.setSubmissionDrop(filenames)

class CloseApp(wx.Frame):
    def __init__(e):
        sys.exit(0)

class BusyWindow(wx.Frame):
    def __init__(self, parent, run_params):
        self.run_params = run_params
        wx.Frame.__init__(self, parent, -1, '', size=(350,80), style=wx.STAY_ON_TOP | wx.DEFAULT_FRAME_STYLE)
        wx.StaticText(self, -1, "                    Processing files. Please wait. \n                     DON'T TOUCH ANYTHING!")
        self.Centre()
        self.Show()

app = wx.App()
ScrolledWindow(None, -1, 'iTunes Quicktime File Prep')
app.MainLoop()

【问题讨论】:

  • 确认一下,在您的程序第一次运行时,辅助窗口显示,但在程序的后续运行中显示
  • 您确定 for 循环中没有导致它几乎立即转到busy.Close() 的问题吗?或者可能引发了一些异常,因此它退出并且从不调用Close()(在这种情况下似乎有效。)无论哪种方式,您都应该阅读有关在不阻塞GUI的情况下处理长时间运行任务的更好方法。 wiki.wxpython.org/LongRunningTaskswiki.wxpython.org/Non-Blocking_Guiwiki.wxpython.org/CallAfter
  • 我绝对确定循环或异常没有问题,因为它在 IDLE 中运行完美。

标签: python wxpython py2app


【解决方案1】:

今晚我为这个问题苦苦挣扎了好一阵子。似乎有效的方法是将 py2app 中的 argv_emulation 选项设置为 False

启用后,argv_emulation 会捕获某些 AppleEvents,这些事件会被转换为字符串并填充到 sys.argv 中。当与使用 GUI 工具包的应用程序一起使用时,我怀疑这会吞噬 wxPython 期望接收的一些 AppleEvents。

【讨论】:

  • 这解决了我的问题:当我点击图标时,我的 wxPython GUI 不会弹出。我必须双击该图标,然后 再次单击它或单击 Dock 中的图标。现在它第一次正常工作。谢谢!
猜你喜欢
  • 2015-08-07
  • 2010-11-12
  • 1970-01-01
  • 2015-07-19
  • 2021-06-25
  • 2017-01-18
  • 2018-05-21
  • 1970-01-01
  • 2023-04-03
相关资源
最近更新 更多