GtkAda中点击Gtk_Button触发回调显示Gtk_Entry无响应问题求助
问题核心原因
代码存在以下几处关键错误:
- 回调函数
Le_Callback中声明的V : T_Test是局部栈变量,其内部创建的Conteneur容器从未被添加到主窗口的组件渲染树中,回调执行结束后该局部变量会被直接回收,关联的Entry自然无法显示 Initialise_Conteneur过程的Object参数是传值模式,过程内对Object.Conteneur的Gtk_New操作只会修改参数副本,不会生效到实参本身,需要改为in out传参模式- 主程序
Main.adb的信号连接代码中,传入的回调函数名错误:实际定义的回调是Le_Callback,代码中写的是不存在的Le_Test'Access,属于编译级错误 - 现有回调逻辑重复创建了
Gtk_Fixe容器,而主窗口中已经绑定了Posix.Conteneur实例,无需重复创建容器,直接将Entry添加到已挂载的Posix.Conteneur即可
修正后代码
File.ads
Package Test is Type T_Test is record Conteneur : Gtk_Fixe; L_Entree : Gtk_Entry; end Record; -- 回调增加用户数据参数,接收外部传入的T_Test实例 Procedure Le_Callback (Emetteur : access Gtk_Button_Record'Class; User_Data : T_Test); -- 使用带用户数据的回调实例化包 Package P is new Gtk.Handlers.User_Callback (Gtk_Button_Record, T_Test); Use P; -- 参数改为in out模式 Procedure Initialise_Conteneur (Object : in out T_Test); end Test;
File.adb
Package body Test is Procedure Initialise_Conteneur (Object : in out T_Test) is begin Gtk_New (Object.Conteneur); end Initialise_Conteneur; Procedure Le_Callback (Emetteur : access Gtk_Button_Record'Class; User_Data : T_Test) is begin -- 直接操作传入的已挂载容器,无需重复创建Conteneur Gtk_New (User_Data.L_Entree); User_Data.Conteneur.Add (User_Data.L_Entree); -- 设置Entry的显示位置,避免和按钮重叠被遮挡 User_Data.Conteneur.Put (User_Data.L_Entree, 10, 50); User_Data.L_Entree.Show; end Le_Callback; end Test;
Main.adb
Procedure Main is Win : Gtk_Window; Button : Gtk_Button; Posix : T_Test; begin Init; Initialise_Conteneur (Posix); -- 调用修正后的初始化方法 Gtk_New (Win); Win.Set_Default_Size (600,400); Gtk_New (Button,"Bouton"); -- 绑定信号时传入Posix作为用户数据,回调函数名修正为Le_Callback Test.P.Connect (Widget => Button, Name => Signal_Clicked, Marsh => P.To_Marshaller (Le_Callback'Access), User_Data => Posix, After => true); Posix.Conteneur.Put (Button, 10, 10); Posix.Conteneur.Add (Button); Win.Add (Posix.Conteneur); Win.Show_All; Main; end Main;
内容的提问来源于stack exchange,提问作者Danielle Mandi Mayagha
相关产品推荐
相关产品推荐

