【问题标题】:Widget changing hangs the main window in GTK+小部件更改挂起 GTK+ 中的主窗口
【发布时间】:2014-11-07 08:46:20
【问题描述】:

我正在使用 GTK+ 在 Vala 中编写程序。它有一个函数可以创建一个包含大量 EventBox 对象的 ListBox。有一个问题:有一个下载图像的功能,它需要很多时间,所以除非所有下载完成,否则主窗口不会显示。这不是我想要的,我希望出现主窗口,然后下载并显示图像。所以我将图像加载分离到单独的功能,但除非所有下载完成,否则主窗口仍然不显示。我做错了什么?

这是我正在使用的功能:

foreach (MediaInfo post in feedPosts)  
     feedList.prepend(post);

foreach (PostBox box in feedList.boxes)
     box.loadImage();

("feedList" 是继承自 Gtk.ListBox 的类,"boxes" 是包含所有 PostBox (继承自 Gtk.EventBox) 对象的列表)

这是 feedList.prepend 函数:

public void append(MediaInfo post)
{
    Gtk.Separator separator = new Gtk.Separator (Gtk.Orientation.HORIZONTAL);
    base.prepend(separator);
    PostBox box = new PostBox(post);
    base.prepend(box);
    boxes.append(box);      
}

这是 PostBox 类的构造函数和 loadImage 函数:

public PostBox(MediaInfo post)
{
    box = new Gtk.Box(Gtk.Orientation.VERTICAL, 0);
    this.add(box);

    this.post = post;

    userToolbar = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 0);

    userNameLabel = new Gtk.Label("@" + post.postedUser.username);
    this.userNameLabel.set_markup(
            "<span underline='none' font_weight='bold' size='large'>" +
            post.postedUser.username + "</span>"
            );


    userToolbar.add(userNameLabel);
    box.pack_start(userToolbar, false, true);   

    image = new Gtk.Image();
    box.add(image); 

    box.add(new Gtk.Label(post.title));
    box.add(new Gtk.Label( post.likesCount.to_string() + " likes."));
    print("finished.\n");

    return;
}   

public void loadImage()
{
    var imageFileName = PhotoStream.App.CACHE_URL + getFileName(post.image.url);
    downloadFile(post.image.url, imageFileName);

    Pixbuf imagePixbuf = new Pixbuf.from_file(imageFileName);   
    imagePixbuf = imagePixbuf.scale_simple(IMAGE_SIZE, IMAGE_SIZE, Gdk.InterpType.BILINEAR);


    image.set_from_pixbuf(imagePixbuf);             
}

【问题讨论】:

    标签: gtk vala


    【解决方案1】:

    您已经用另一种方法编写了下载操作,但是这些操作仍然是同步的,即它们阻塞线程。你永远不想在 GUI 线程中做计算或其他昂贵的事情,因为这会使 GUI 无响应。

    您应该异步开始下载,并在下载完成时触发回调方法。例如,在回调中,您可以将图像占位符更改为实际图像。

    【讨论】:

    • 我认为从 PostBox 构造函数到分离函数的移动图像下载代码可以做到这一点,但显然这不是我想要的工作方式。
    • 你能告诉我应该如何处理吗?因为我不明白如何正确地做到这一点。
    • 你应该看看这些:wiki.gnome.org/Projects/Vala/AsyncSamples,这里也有一个关于它的部分:wiki.gnome.org/Projects/Vala/Tutorial#Asynchronous_Methods
    • 我尝试用这种方式重写第二个“foreach”语句:pastebin.com/9bzgBrKm,但结果是一样的。
    • 您应该定义一个 async 方法来从 URL 下载图像。使用 URL 参数调用其begin,并定义回调。我明天可以写一个更复杂的例子,但现在不行。
    【解决方案2】:

    我用多线程替换了我所有的 async 方法,现在它按照我希望的方式工作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多