python - Gtk.ProgressBar 在 Python 中不起作用

标签 python progress-bar gtk3 pygobject

我尝试在PythonGtk3中使用进度条,但它没有更新。我已阅读this这个论坛中的文档和一些问题(主要是针对 pygtk),我真的不明白!

我编写的代码仅用于测试目的。当您单击按钮时,它会递归读取目录的内容。我的目的是在阅读所有这些文件时使用进度条。

这是整个代码:

import os
from gi.repository import Gtk

class MyWindow(Gtk.Window):
    """Progress Bar"""

    def __init__(self):
        Gtk.Window.__init__(self, title='Progress Bar')
        self.set_default_size(300, 75)
        self.set_position(Gtk.WindowPosition.CENTER)
        self.set_border_width(10)

        # read dir contents
        mydir = 'Documents'
        home_path = os.environ.get('HOME')
        dir_path = os.path.join(home_path, mydir)
        self.dir_files_list(dir_path)

        # create a grid
        self.grid = Gtk.Grid(column_homogeneous=True, row_homogeneous=True,
                             column_spacing=10, row_spacing=10)
        self.add(self.grid)

        # create a progress bar
        self.progressbar = Gtk.ProgressBar()
        self.grid.add(self.progressbar)

        # create a button
        self.button = Gtk.Button(stock=Gtk.STOCK_APPLY)
        self.button.connect('clicked', self.on_button_pressed)
        self.grid.attach(self.button, 0, 1, 1, 1)

    # function to read the dir contents
    def dir_files_list(self, dir_path):
        self.dir_list = []
        for root, dirs, files in os.walk(dir_path):
            for fn in files:
                f = os.path.join(root, fn)
                self.dir_list.append(f)

    # function to update the progressbar
    def on_button_pressed(self, widget):
        self.progressbar.set_fraction(0.0)
        frac = 1.0 / len(self.dir_list)
        for f in self.dir_list:
            new_val = self.progressbar.get_fraction() + frac
            print new_val, f
            self.progressbar.set_fraction(new_val)
        return True

def main():
    """Show the window"""
    win = MyWindow()
    win.connect('delete-event', Gtk.main_quit)
    win.show_all()
    Gtk.main()
    return 0

if __name__ == '__main__':
    main()

感谢更有经验的程序员的任何帮助!

最佳答案

问题是您在创建窗口时正在处理整个目录。甚至在您显示它之前(在 self.dir_files_list(dir_path) 行中)。在我看来,您想在按下“应用”按钮后调用它。

至少有两种可能的解决方案:使用线程或使用迭代器。对于您的特定用例,我认为迭代器就足够了,除了更简单和更Pythonic之外。仅当您真正需要它们时,我才会推荐它们。

您可以一次处理每个目录中的每个文件,而不是预先遍历整个目录并稍后处理它们。

在您的示例中,我会将方法dir_files_list(重命名为walk)和on_button_pressed更改为:

from gc import collect
from gi.repository import Gtk, GObject

我们现在还需要导入 GObject 以使用 idle_add,只要没有更高优先级的事件待处理,它就会调用回调。此外,一旦任务完成,我们需要删除回调以不再调用它(为此我们需要 source_remove)。

我将您的方法dir_files_list重命名为walk,因为它在语义上看起来更接近迭代器。当我们遍历每个目录和文件时,我们会暂时“返回”(使用yield)。请记住,yield True 表示有待处理的项目。 yield False 意味着我们停止迭代。

所以,方法是:

def walk(self, dir_path):
    self.dir_list = []
    for root, dirs, files in os.walk(dir_path):
        i = 0.0
        self.set_title(os.path.dirname(root))

        for fn in files:
            i = i + 1.0
            f = os.path.join(root, fn)
            self.dir_list.append(f)

            self.progressbar.set_fraction(i / len(files))

            collect()
            yield True

       yield True

    GObject.source_remove(self.id)
    yield False

现在,我们在这里更新进度条。在这个特定部分中,我正在更新每个目录内的进度条。也就是说,它将在每个子目录中重新启动,并且进度条将在每个子目录中重新启动。要了解正在访问哪个目录,请使用当前目录设置窗口标题。这里需要理解的重要部分是yield。您可以根据自己的喜好进行调整。

一旦我们遍历了整个目录,我们必须返回yield False,但在此之前我们删除回调(GObject.source_remove(self.id))。

我认为 self.dir_list 在这里不再有用,但您可能有不同的想法。

您可能想知道 walk 何时以及如何被调用?按下按钮时可以设置:

def on_button_pressed(self, button, *args):
    homedir = os.path.expanduser('~')
    rootdir = os.path.join(homedir, 'Documents')

    self.task = self.walk(rootdir)
    self.id = GObject.idle_add(self.task.next)

self.task 是一个迭代器,它具有从 self.task 检索下一项的方法 next(),即只要没有挂起的事件(使用idle_add)就会被调用。我们获取 id 以便在完成后删除回调。

您必须从 __init__ 方法中删除行 self.dir_files_list(dir_path)

还有一件事:我手动调用了垃圾收集器 (gc.collect()),因为它在处理大型目录时可能很有用(取决于您对它们执行的操作)。

关于python - Gtk.ProgressBar 在 Python 中不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15914687/

相关文章:

c - 用于 GTK 开发的 VS Code C/C++ 配置

python - 使用 iterrows() 时如何通过索引访问列

python - 如何从/etc/oratab 文件中提取字符串?

android - 进度条阴影仅在填充部分

c++ - 应用程序QT崩溃(带进度条的ftp下载)

Gtk "subtle"进度条

python - 设置 URL gif 背景但不使用 Python 2 上的新框架

python生成器对象混淆

matlab - 如何在 MATLAB 模态中制作等待栏

Python 3 和 GTK3 : crossplatform tray icon