2013-03-26 55 views
0

我在处理这个在vala类中的行为时几乎没有问题。这个难以理解的行为

这里是我的代码:(build_and_send1和build_and_send2的信号按一个按钮升起)

using GLib; 
using Gtk; 

public class Main : Object 
{ 

    /* 
    * Uncomment this line when you are done testing and building a tarball 
    * or installing 
    */ 
    //const string UI_FILE = Config.PACKAGE_DATA_DIR + "/" + "gtk_httpclient.ui"; 
    const string UI_FILE = "src/gtk_httpclient.ui"; 

    /* ANJUTA: Widgets declaration for gtk_httpclient.ui - DO NOT REMOVE */ 


    private Builder builder; 

    public Main() 
    { 

     try 
     { 
      this.builder = new Builder(); 
      this.builder.add_from_file (UI_FILE); 
      this.builder.connect_signals (this); 

      var window = this.builder.get_object ("window") as Window; 
      /* ANJUTA: Widgets initialization for gtk_httpclient.ui - DO NOT REMOVE */ 
      window.show_all(); 

      stderr.printf ("constructor:\n"); 
      stderr.printf ("this: %p\n", this); 
      stderr.printf ("builder: %p\n", this.builder); 
     } 
     catch (Error e) { 
      stderr.printf ("Could not load UI: %s\n", e.message); 
     } 

    } 

    [CCode (instance_pos = -1)] 
    public void on_destroy (Widget window) 
    { 
     Gtk.main_quit(); 
    } 

    public void build_and_send1 (Widget button) 
    { 
     stderr.printf ("\nbuild_and_send1:\n"); 
     stderr.printf ("this: %p\n", this); 
     stderr.printf ("builder: %p\n", this.builder); 
    } 

    [CCode (instance_pos = -1)] 
    public void build_and_send2 (Widget button) 
    { 
     stderr.printf ("\nbuild_and_send2:\n"); 
     stderr.printf ("this: %p\n", this); 
     stderr.printf ("builder: %p\n", this.builder); 
    } 

    static int main (string[] args) 
    { 
     Gtk.init (ref args); 
     new Main(); 

     Gtk.main(); 

     return 0; 
    } 
} 

我有这样的输出:

constructor: 
this: 0x1a524a0 
builder: 0x1a6a230 

build_and_send1: 
this: 0x1aa2030 
builder: 0x5a4fe823 

build_and_send2: 
this: 0x1a524a0 
Program has been terminated receiving signal 11 (Segmentation fault) 

我认为,如果我想的一样Main的实例在我的信号中,它们必须以[CCode(instance_pos = -1)]开头。 但是,builder.connect_signals(this)的目标是什么?

为什么this.builder提出了在build_and_send2,而不是在构造分段错误?

+0

顺便说一下,我使用Anjuta 3.6.2和Glade 3.14.2 – 2013-03-26 11:00:25

回答

0

最有可能的,new Main()的结果在施工后被超出范围,被垃圾收集。将其分配给一个变量。

+0

Thx的解释。我已经解决了我的问题,将构建器声明为静态变量。 – 2013-03-27 07:23:16

0

我对此有所了解。

在我的项目中,我做了一个UIHandler类来处理UI事件。

当我在它的构造函数中连接这个类的实例时,它不起作用,但是如果我在类之外连接实例,它工作正常。

错误:这将以分段错误终止。

// Constructor 
public UIHandler (Builder builder) { 
    var button = builder.get_object ("send-button") as Button; 
    Object (button: button); 

    bulder.connect_signals (this); 
} 
... 
[CCode (instance_pos = -1)] 
public void activate (Entry location) { 
    this.button.clicked(); 
} 

正确的:这将会消失。

主要类:

public Main() 
{ 

    try 
    { 
     var builder = new Builder(); 
     builder.add_from_file (UI_FILE); 

     builder.connect_signals (new UIHandler (builder)); 

     var window = builder.get_object ("window") as Window; 

     /* ANJUTA: Widgets initialization for gtk_http_client.ui - DO NOT REMOVE */ 
     window.show_all(); 
    } 
    catch (Error e) { 
     stderr.printf ("Could not load UI: %s\n", e.message); 
    } 

} 

UIHandler类:

// Constructor 
public UIHandler (Builder builder) { 
    var button = builder.get_object ("send-button") as Button; 
    Object (button: button); 
} 
... 
[CCode (instance_pos = -1)] 
public void activate (Entry location) { 
    this.button.clicked(); 
} 

这behavoir解决了我原来的问题。

+0

您似乎误解了为什么会这样。这归结于Gtk.Builder.connect_signals采用void *的事实。当你向一个指针传递一个值时,Vala目前几乎忽略了内存管理,所以这个参数将会像一个拥有的参数或者一个非拥有的参数,这取决于你传递的参数。由于您正在connect_signals调用中创建UIHandler的新实例,因此Vala将其视为拥有的参数。您可以通过使用“(拥有)”来传输引用或手动调用GLib.Object.ref来在UIHandler构造函数中实现类似效果。 – nemequ 2013-04-25 03:40:01

+0

我在发布此响应之后,阅读了关于拥有和未拥有的实例。你确认我的想法。 Thx的解释,我会在稍后尝试。 – 2013-04-25 10:41:18