Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
wxPython状态栏中的moviepy进度栏_Python_Python 3.x_Wxpython_Moviepy - Fatal编程技术网

wxPython状态栏中的moviepy进度栏

wxPython状态栏中的moviepy进度栏,python,python-3.x,wxpython,moviepy,Python,Python 3.x,Wxpython,Moviepy,在Windows10上的Python3.x上运行 我正在编写一个脚本,帮助将.tiff图像序列自动编译成视频。我正在使用wxPython构建GUI。首先,我创建window类并为窗口设置一个全局变量 global main_window main_window = self 然后,我有一个函数,用于写入状态栏,并将值打印到控制台(有时我还添加代码,从发送到此函数的文本中写入日志文件) 这是我编写的moviePy函数,用于将图像序列转换为ta视频 def video_from_sequence(

在Windows10上的Python3.x上运行

我正在编写一个脚本,帮助将.tiff图像序列自动编译成视频。我正在使用wxPython构建GUI。首先,我创建window类并为窗口设置一个全局变量

global main_window
main_window = self
然后,我有一个函数,用于写入状态栏,并将值打印到控制台(有时我还添加代码,从发送到此函数的文本中写入日志文件)

这是我编写的moviePy函数,用于将图像序列转换为ta视频

def video_from_sequence(image_sequence, video, fps):
    img = []
    update_status_bar(main_window, 'Getting Image Directory')
    path = os.path.dirname(os.path.realpath(image_sequence))
    print(path)
    update_status_bar(main_window, 'Getting List of Image Files')
    for root, dirs, files in os.walk(path):
        for file in files:
            if file.endswith('.tiff'):
                img.append(file)
    os.chdir(path)
    update_status_bar(main_window, 'Creating Video From Image Sequence')
    clip = ImageSequenceClip(img, fps=fps)
    update_status_bar(main_window, clip.write_videofile(video, fps=fps))
print to console(打印到控制台)确实显示了进度,但是状态栏中没有填充流程的当前进度。因为我希望最终以.pyw的形式运行,其中状态栏显示进度,所以让进度栏显示在状态栏中对我来说很重要,但是我很难找到这样做的方法

更新(2020年1月6日):

我成功地使用了两个函数来启动和停止进度条,并创建了带有两个面板(而不是一个)的状态栏

状态栏的MainWindow类中的我的代码已更改为:

self.statusbar = self.CreateStatusBar(2)
self.progress_bar = wx.Gauge(self.statusbar, -1, size=(280,25), style=wx.GA_PROGRESS)
self.progress_bar_active = False
self.Show()
self.progress_bar.SetRange(50)
self.progress_bar.SetValue(0)
我的启动动画的功能:

def start_busy_statusbar(window):
    window.count = 0
    window.proc = subprocess.Popen(['ping', '127.0.0.1', '-i', '0.2'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    while True:
        wx.Yield()
        try:
            list_data = window.proc.stdout.readline()
            wx.Yield()
        except:
            break
        if len(list_data) == 0:
            break
        window.progress_bar.Pulse()
        wx.Yield()
        window.count += 1
def stop_busy_statusbar(window):
    window.progress_bar.Destroy()
    window.progress_bar = wx.Gauge(window.statusbar, -1, size=(280, 25), style=wx.GA_PROGRESS)
以及我停止动画的功能:

def start_busy_statusbar(window):
    window.count = 0
    window.proc = subprocess.Popen(['ping', '127.0.0.1', '-i', '0.2'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    while True:
        wx.Yield()
        try:
            list_data = window.proc.stdout.readline()
            wx.Yield()
        except:
            break
        if len(list_data) == 0:
            break
        window.progress_bar.Pulse()
        wx.Yield()
        window.count += 1
def stop_busy_statusbar(window):
    window.progress_bar.Destroy()
    window.progress_bar = wx.Gauge(window.statusbar, -1, size=(280, 25), style=wx.GA_PROGRESS)
这确实感觉有点粗糙,但确实有效

因此,我的convert()函数调用video_from_sequence()函数如下所示:

    def convert(self, event):
        start_busy_statusbar(main_window)
        image_sequence = str(self.text_image_sequence_dir.GetValue())
        original_video = str(self.text_original_video_dir.GetValue())
        if image_sequence.endswith('.tiff') and original_video.endswith('.mkv'):
            try:
                new_video = str(original_video)[:-4] + '_1080p.mkv'
                temp_video = str(original_video)[:-4] + '_temp.mkv'
                print(image_sequence)
                print(original_video)
                print(new_video)
                fps = get_frame_rate(original_video)
                print(fps)
                video_from_sequence(image_sequence, temp_video, fps)

            except FileNotFoundError as e:
                e = str(e).replace('Errno 2] ', '')
                e = e.replace('directory:', 'directory:\n')
                warning(e)
            update_status_bar(self, 'Finished')
        else:
            warning('You must enter valid paths for both a tiff sequence and original video.')
        stop_busy_statusbar(main_window)
我现在遇到的是,窗口在处理图像序列时会锁定。有人建议我使用一个单独的线程或利用wx.Yield。我不太清楚如何执行这些事情。我尝试过CallAfter(function(vars)),但似乎不起作用


我复制了一些代码片段来演示它在wxPython中的工作原理,但我并不真正理解它是如何工作的,也无法在我的脚本中使用它。

这里是一个在状态栏中实现进度栏的非常古老的示例。
它应该给你足够的时间和你一起工作

import wx
import subprocess
class MainFrame(wx.Frame):

    def __init__(self):
        wx.Frame.__init__(self, None, title='Statusbar progress')
        panel = wx.Panel(self)
        self.start_btn = wx.Button(panel, label='Start')
        self.start_btn.Bind(wx.EVT_BUTTON, self.OnStart)
        self.stop_btn = wx.Button(panel, label='Stop')
        self.stop_btn.Bind(wx.EVT_BUTTON, self.OnStop)
        self.Bind(wx.EVT_CLOSE, self.OnExit)
        self.text = wx.TextCtrl(panel, -1, 'Type text here')
        btn_sizer = wx.BoxSizer(wx.HORIZONTAL)
        btn_sizer.Add(self.start_btn)
        btn_sizer.Add(self.stop_btn)
        btn_sizer.Add(self.text)
        panel.SetSizer(btn_sizer)
        self.statusbar = self.CreateStatusBar(3)
        self.text1 = wx.StaticText(self.statusbar,-1,("Static text"))
        self.text2 = wx.StaticText(self.statusbar,-1,("Count Text"))
        self.progress_bar = wx.Gauge(self.statusbar, -1, style=wx.GA_HORIZONTAL|wx.GA_SMOOTH)
        sizer = wx.BoxSizer(wx.HORIZONTAL)
        sizer.Add(self.text1, 0, wx.ALL, 5)
        sizer.Add(self.text2, 1, wx.ALL, 5)
        sizer.Add(self.progress_bar, 2, wx.ALL, 5)
        self.statusbar.SetSizer(sizer)
        self.Show()
        self.progress_bar.SetRange(50)
        self.progress_bar.SetValue(0)

    def OnStart(self,event):
        self.start_btn.Enable(False)
        self.text1.SetLabelText("Started")
        self.count = 0
        self.proc = subprocess.Popen(['ping','127.0.0.1','-i','0.2'],stdin=subprocess.PIPE, stdout=subprocess.PIPE,stderr=subprocess.PIPE)
        while True:
            try:
                list_data = self.proc.stdout.readline()
            except:
                break
            if len(list_data) == 0:
                break
            self.progress_bar.Pulse()
            self.count+=1
            self.text2.SetLabelText("Count "+str(self.count))
            wx.GetApp().Yield()

    def OnStop(self,event):
        self.start_btn.Enable(True)
        self.text1.SetLabelText("Stopped")
        try:
            self.proc.kill()
        except:
            pass

    def OnExit(self,event):
        try:
            self.proc.kill()
        except:
            pass
        self.Destroy()

if __name__ == '__main__':
    app = wx.App()
    frame = MainFrame()
    app.MainLoop()

谢谢你。我不知道如何在启动进程和进程结束之间的函数期间调用它。我是否将
def\uuuu init\uuuu(self)
添加到当前窗口?或者可能只是将该类的函数添加到我当前为窗口创建的类中?好的,我已经成功启动了progressbar动画,但是我无法停止它。
.proc.kill()
实际上似乎并没有关闭状态栏。我还注意到,当我开始一个较长的过程(在本例中是将帧编译成视频)时,进度条会冻结。如果看不到您的代码,几乎不可能进行评论。但是,
proc.kill
只是终止一个子进程,因此您的等效程序将停止图像转换。当您处理
长时间运行的任务时,整个gui将发生冻结。您可以在适当的时候使用
wx.Yield()
,或者如果您正在对progressbar执行线程,则可以定期使用
wx.Yield
,并为线程创建
stop
方法。我发现我可以使用
window.progress\u bar.Destroy()
window.progress\u bar=wx.Gauge(window.statusbar,-.1,size=(280,25),style=wx.GA_PROGRESS)
以停止动画。我不确定
wx.Yield()
wx.Yield
的合适位置。不过我会继续玩,如果可以的话,我很想避免冰冻。或者我只是需要学习如何在另一个线程中运行它。我已经更新了页面以包含更多要评估的代码。