小部件更改将挂起GTK中的主窗口+

小部件更改将挂起GTK中的主窗口+,gtk,vala,Gtk,Vala,我正在用GTK+用Vala编写一个程序。它有一个函数,用于创建包含许多EventBox对象的ListBox。有一个问题:有一个函数可以下载图像,而且需要花费很多时间,因此除非所有下载都完成,否则主窗口不会显示。这不是我想要的,我希望主窗口出现,然后图像下载和显示。所以我将图像加载分离为单独的函数,但除非所有下载完成,否则主窗口仍然不会显示。我做错了什么 下面是我正在使用的函数: foreach (MediaInfo post in feedPosts) feedList.prepe

我正在用GTK+用Vala编写一个程序。它有一个函数,用于创建包含许多EventBox对象的ListBox。有一个问题:有一个函数可以下载图像,而且需要花费很多时间,因此除非所有下载都完成,否则主窗口不会显示。这不是我想要的,我希望主窗口出现,然后图像下载和显示。所以我将图像加载分离为单独的函数,但除非所有下载完成,否则主窗口仍然不会显示。我做错了什么

下面是我正在使用的函数:

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

foreach (PostBox box in feedList.boxes)
     box.loadImage();
feedList是从Gtk.ListBox继承的类,Box是包含从Gtk.EventBox对象继承的所有PostBox的列表

这是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);             
}

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


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

我用多线程替换了所有异步方法,现在它正以我希望的方式工作。

我认为将图像从PostBox构造函数下载代码到单独的函数中会使,但很明显,这不是我想要的工作方式。你能告诉我应该如何处理它吗?因为我不明白如何正确地执行。您应该检查以下内容:,这里还有一节关于它的内容:我试图以这种方式重写第二个foreach语句:,但结果是一样的。您应该定义一个异步方法,从URL下载图像。调用它的URL参数,并定义回调。明天我可以写一个更复杂的例子,但现在不行。