2013-06-04 65 views
0

我想在運行超時動畫的時候在vala/clutter中加載圖像文件,使用「image.set_load_async」在請求文件加載時停止一段時間的動畫。這是源:Vala/Clutter紋理加載線程

// valac --thread --pkg clutter-1.0 --pkg=gio-2.0 test_1.vala -o test_1 
using Clutter; 
class SlideImage : Clutter.Actor { 


    protected Texture image = new Texture(); 
    public int loaded = 0; 
    public SlideImage (string file) { 
     try { 
      loaded = 1; 
      image.set_load_async (true); 
      image.load_finished.connect((t, a) => { 
              loaded = 2; 
              this.add_actor (image); 
              }); 
      image.set_from_file (file); 
     } catch (Error e) { 
      warning("Error setting SlideImageReflected gradient : %s", e.message); 
     } 
    } 
} 
class ClutterSlideShow { 
    protected Stage stage; 
    protected int width = 800; 
    protected int height =700; 
    protected string[] file_names = {}; 
    private int file_pointer = 0; 
    private int counter = 0; 
    private SlideImage showA = null; 
    private SlideImage showB = null; 
    private SlideImage showC = null; 
    private SlideImage showD = null; 
    private SlideImage showE = null; 
    public ClutterSlideShow (string folder) { 
     try { 
      var directory = File.new_for_path (folder); 
      var enumerator = directory.enumerate_children (FileAttribute.STANDARD_NAME,0); 
      FileInfo file_info; 
      while ((file_info = enumerator.next_file()) != null) { 
       file_names += folder+"/"+file_info.get_name(); 
      } 
     } catch (Error e) { 
      stderr.printf ("Error ClutterSlideShow listing files: %s\n", e.message); 
     } 
     stage = Stage.get_default(); 
     stage.hide.connect (Clutter.main_quit); 
     stage.color = Color() { red = 0, green = 0, blue = 0, alpha = 255 };; 
     stage.set_size (width, height); 
     stage.show_all(); 
    } 
    protected string get_next_file() { 
     file_pointer++; 
     if (file_pointer > file_names.length) file_pointer = 1; 
     return file_names[file_pointer-1]; 
    } 
    public void start() { 
     Timeout.add (15, run); 
    } 
    private bool run() { 
     if (showA == null) { 
      showA = new SlideImage (get_next_file()); 
      showA.set_x (0); 
      showA.set_y (0); 
     } else if (showA.loaded == 2) { 
      stage.add_actor (showA); 
      showA.loaded = 3; 
     } else if (showA.loaded == 3) { 
      showA.set_y (showA.get_y() + 1); 
      counter++; 
      if (counter==100) { 
       showB = new SlideImage (get_next_file()); 
       showB.set_x (100); 
       showB.set_y (0); 
       stage.add_actor (showB); 
       showC = new SlideImage (get_next_file()); 
       showC.set_x (200); 
       showC.set_y (0); 
       stage.add_actor (showC); 
       showD = new SlideImage (get_next_file()); 
       showD.set_x (300); 
       showD.set_y (0); 
       stage.add_actor (showD); 
       showE = new SlideImage (get_next_file()); 
       showE.set_x (400); 
       showE.set_y (0); 
       stage.add_actor (showE); 
      } 
     } 
     return true; 
    } 
} 
int main (string[] args) { 
    if (Thread.supported() == false) { 
     stderr.printf ("Threads are not supported!\n"); 
     return -1; 
    } 
    var result = init (ref args); 
    if (result != Clutter.InitError.SUCCESS) { 
     stderr.printf("Error: %s\n", result.to_string()); 
     return 1; 
    } 
    var slide_show = new ClutterSlideShow ("/usr/share/backgrounds/"); 
    slide_show.start(); 
    Clutter.main(); 
    return 0; 
} 

我也嘗試使用「線程」但我得到一個「分段故障(核心轉儲)」,我不知道如何調試或修復。這是例如:

// valac --thread --pkg clutter-1.0 --pkg=gio-2.0 test_2.vala -o test_2 
using Clutter; 
class SlideImage : Clutter.Actor { 
    protected Texture image = new Texture(); 
    public int loaded = 0; 
    public SlideImage (string file) { 
     loaded = 1; 
     load_image_in_background.begin(file, (obj, res) => { 
      try { 
       loaded = 2; 
       this.add_actor (image); 
      } catch (ThreadError e) { 
       string msg = e.message; 
       stderr.printf(@"Thread error: $msg\n"); 
      } 
     }); 
    } 
    async void load_image_in_background (string file) throws ThreadError { 
     SourceFunc callback = load_image_in_background.callback; 
     ThreadFunc<void*> run =() => { 
      try { 
       // Help ! The next line results in "Segmentation fault" 
       image.set_from_file (file); 
      } catch (Error e) { 
       warning("Error setting SlideImage texture : %s", e.message); 
      } 
      Idle.add((owned) callback); 
      return null; 
     }; 
     Thread.create<void*>(run, false); 
     yield; 
    } 
} 
class ClutterSlideShow { 
    protected Stage stage; 
    protected int width = 800; 
    protected int height =700; 
    protected string[] file_names = {}; 
    private int file_pointer = 0; 
    private int counter = 0; 
    private SlideImage showA = null; 
    private SlideImage showB = null; 
    private SlideImage showC = null; 
    private SlideImage showD = null; 
    private SlideImage showE = null; 
    public ClutterSlideShow (string folder) { 
     try { 
      var directory = File.new_for_path (folder); 
      var enumerator = directory.enumerate_children (FileAttribute.STANDARD_NAME,0); 
      FileInfo file_info; 
      while ((file_info = enumerator.next_file()) != null) { 
       file_names += folder+"/"+file_info.get_name(); 
      } 
     } catch (Error e) { 
      stderr.printf ("Error ClutterSlideShow listing files: %s\n", e.message); 
     } 
     stage = Stage.get_default(); 
     stage.hide.connect (Clutter.main_quit); 
     stage.color = Color() { red = 0, green = 0, blue = 0, alpha = 255 };; 
     stage.set_size (width, height); 
     stage.show_all(); 
    } 
    protected string get_next_file() { 
     file_pointer++; 
     if (file_pointer > file_names.length) file_pointer = 1; 
     return file_names[file_pointer-1]; 
    } 
    public void start() { 
     Timeout.add (15, run); 
    } 
    private bool run() { 
     if (showA == null) { 
      showA = new SlideImage (get_next_file()); 
      showA.set_x (0); 
      showA.set_y (0); 
     } else if (showA.loaded == 2) { 
      stage.add_actor (showA); 
      showA.loaded = 3; 
     } else if (showA.loaded == 3) { 
      showA.set_y (showA.get_y() + 1); 
      counter++; 
      if (counter==100) { 
       showB = new SlideImage (get_next_file()); 
       showB.set_x (100); 
       showB.set_y (0); 
       stage.add_actor (showB); 
       showC = new SlideImage (get_next_file()); 
       showC.set_x (200); 
       showC.set_y (0); 
       stage.add_actor (showC); 
       showD = new SlideImage (get_next_file()); 
       showD.set_x (300); 
       showD.set_y (0); 
       stage.add_actor (showD); 
       showE = new SlideImage (get_next_file()); 
       showE.set_x (400); 
       showE.set_y (0); 
       stage.add_actor (showE); 
      } 
     } 
     return true; 
    } 
} 
int main (string[] args) { 
    if (Thread.supported() == false) { 
     stderr.printf ("Threads are not supported!\n"); 
     return -1; 
    } 
    var result = init (ref args); 
    if (result != Clutter.InitError.SUCCESS) { 
     stderr.printf("Error: %s\n", result.to_string()); 
     return 1; 
    } 
    var slide_show = new ClutterSlideShow ("/usr/share/backgrounds/"); 
    slide_show.start(); 
    Clutter.main(); 
    return 0; 
} 

回答

0

執行「停止」產生由於兩個原因:

  • 文件負載(可以制有螺紋)
  • 圖像/演員創建(不能螺紋但改善)

我收到的幫助從專家(感謝維克多),下一個代碼與改善它:

  • 線程文件加載
  • 圖像可擴展到其最後的「混亂」大小

這是代碼:

/** 
* Build with: 
* valac --thread --pkg clutter-1.0 --pkg gio-2.0 --pkg gdk-3.0 --target-glib=2.32 test_2.vala -o test_2 
*/ 

const string SLIDESHOW_PATH = "/usr/share/backgrounds"; 

public class SlideImage : Clutter.Actor { 
    public bool ready { get; private set; default = false; } 

    private Clutter.Image image; 
    private Thread thread; 

    public SlideImage (File file, int width, int height) { 
     load_image_async.begin (file, width, height, (obj, res) => { 
      if (image == null) 
       return; 

      set_size (width, height); 
      set_content_scaling_filters (Clutter.ScalingFilter.TRILINEAR, 
             Clutter.ScalingFilter.LINEAR); 
      set_content_gravity (Clutter.ContentGravity.CENTER); 
      set_content (image); 

      ready = true; 
     }); 
    } 

    private async void load_image_async (File file, int width, int height) { 
     var pixbuf = yield load_pixbuf_from_file_async (file); 

     if (pixbuf != null) { 
      image = new Clutter.Image(); 

      try { 
       float relation_w = pixbuf.get_width()/width; 
       float relation_h = pixbuf.get_height()/height; 
       float offset_x = 0.0f; 
       float offset_y = 0.0f; 
       float scale = 1.0f; 

      if (relation_w > relation_h) { 
       scale = (float) height/(float) pixbuf.get_height(); 
       if (pixbuf.get_width() > width) 
        offset_x = -((float) ((pixbuf.get_width() * scale) - width))/2.0f; 
       } else { 
        scale = (float) width/(float) pixbuf.get_width(); 
        if (pixbuf.get_height() > height) 
         offset_y = -((float) ((pixbuf.get_height() * scale) - height))/2.0f; 
       } 

       var pixbuf_scaled = new Gdk.Pixbuf (pixbuf.get_colorspace(), 
                pixbuf.get_has_alpha(), 
                pixbuf.get_bits_per_sample(), 
                width, 
                height); 
       pixbuf.scale (pixbuf_scaled, 0, 0, width, height, offset_x, offset_y, scale, scale, Gdk.InterpType.BILINEAR); 
       image.set_data (pixbuf_scaled.get_pixels(), 
           pixbuf_scaled.get_has_alpha() ? Cogl.PixelFormat.RGBA_8888 : Cogl.PixelFormat.RGB_888, 
           pixbuf_scaled.get_width(), 
           pixbuf_scaled.get_height(), 
           pixbuf_scaled.get_rowstride()); 
      } catch (Error err) { 
       warning ("Could not set image from pixbuf: %s", err.message); 
       image = null; 
      } 
     } 
    } 

    private async Gdk.Pixbuf? load_pixbuf_from_file_async (File file) { 
     SourceFunc callback = load_pixbuf_from_file_async.callback; 
     Gdk.Pixbuf? pixbuf = null; 

     ThreadFunc<void*> thread_func =() => { 
      try { 
       pixbuf = new Gdk.Pixbuf.from_file (file.get_path()); 
       message ("loaded pixbuf"); 
      } catch (Error e) { 
       warning ("Error loading pixbuf: %s", e.message); 
      } 

      Idle.add ((owned) callback); 
      return null; 
     }; 

     thread = new Thread<void*> ("load-pixbuf-in-background", thread_func); 
     yield; 

     return pixbuf; 
    } 
} 

public class ClutterSlideShow { 
    private const int WIDTH = 800; 
    private const int HEIGHT = 600; 

    private int counter = 0; 
    private List<File> files; 
    private Clutter.Stage stage; 
    private SlideImage showA; 
    private SlideImage showB; 
    private SlideImage showC; 
    private SlideImage showD; 
    private SlideImage showE; 

    public ClutterSlideShow (string folder) { 
     load_files (File.new_for_path (folder)); 
     init_stage(); 
    } 

    public void start() { 
     Timeout.add (15, run); 
    } 

    protected File? get_next_file() { 
     var file = files.nth_data (0); 

     if (file != null) 
      files.remove (file); 

     return file; 
    } 

    private void load_files (File directory) { 
     files = new List<File>(); 

     try { 
      var enumerator = directory.enumerate_children (FileAttribute.STANDARD_NAME,0); 

      FileInfo file_info; 

      while ((file_info = enumerator.next_file()) != null) { 
       var child_file = directory.get_child (file_info.get_name()); 
        files.prepend (child_file); 
      } 
     } catch (Error e) { 
      warning (e.message); 
     }  
    } 

    private void init_stage() { 
     stage = new Clutter.Stage(); 
     stage.background_color = Clutter.Color() { red = 0, green = 0, blue = 0, alpha = 255 }; 
     stage.set_size (WIDTH, HEIGHT); 

     stage.show(); 

     stage.hide.connect (Clutter.main_quit); 
    } 

    private bool run() { 
     if (showA == null) { 
      showA = new SlideImage (get_next_file(), 400, 400); 
      showA.x = 0; 
      showA.y = 0; 
     } else if (showA.get_parent() != stage) { 
      stage.add_child (showA); 
     } else if (showA.ready) { 
      showA.set_y (showA.get_y() + 1); 
      counter++; 

      if (counter == 50) { 
      showB = new SlideImage (get_next_file(), 400, 400); 
      showB.set_x (100); 
      showB.set_y (0); 
      stage.add_child (showB); 
      showC = new SlideImage (get_next_file(), 400, 400); 
      showC.set_x (200); 
      showC.set_y (0); 
      stage.add_child (showC); 
      showD = new SlideImage (get_next_file(), 400, 400); 
      showD.set_x (300); 
      showD.set_y (0); 
      stage.add_child (showD); 
      showE = new SlideImage (get_next_file(), 400, 400); 
      showE.set_x (400); 
      showE.set_y (0); 
      stage.add_child (showE); 
      } 
     } 
     return true; 
    } 
} 

void main (string[] args) { 
    var result = Clutter.init (ref args); 

    if (result != Clutter.InitError.SUCCESS) 
     error ("Failed to init clutter: %s", result.to_string()); 

    var slide_show = new ClutterSlideShow (SLIDESHOW_PATH); 

    slide_show.start(); 
    Clutter.main(); 
} 
+0

只是一個穿線評論:它很少需要油嘴/ GTK +,並且使用線程往往是難以調試問題的途徑......加載圖像也不例外,請參閱http://stackoverflow.com/questions/10831889瞭解異步圖像加載的一個示例。 – jku