首页 > 解决方案 > 使用 scroll_to_iter 在 gtkada 中自动滚动 Text_View

问题描述

我正在编写一个程序,使用 gtkada 显示一个带有 Text_View(在 Scrolled_Window 内)的窗口,该窗口将从 GEntry 更新。

我已经让它几乎按照我想要的方式工作了,除了滚动。

由于从 GEntry 处理输入并插入到 Text_View 我希望它自动滚动,因此最新的条目在底部可见。

如果我理解正确,则在插入文本后执行 Scroll_To_Iter 将不起作用。需要使用空闲处理程序来处理滚动。

我只需要有关如何调用它的指针。

从 GEntry 插入文本的过程如下所示:

procedure Insert_Text (S_Out: String) is

      Iter        : Gtk_Text_Iter;
      Scroll_Okay : Boolean;

   begin

      Get_End_Iter (TextBuffer, Iter);
      Insert (TextBuffer, Iter, "You entered:" & ASCII.LF);

      Get_End_Iter (TextBuffer, Iter);
      Insert (TextBuffer, Iter, S_Out & ASCII.LF);


      Get_End_Iter (TextBuffer, Iter);
      Scroll_Okay := Scroll_To_Iter
        (TextView, Iter, 0.0, True, 1.0, 1.0);


   end Insert_Text;

我在其中包含的 Scroll_To_Iter 调用只是为了说明;我知道那行不通。

我在同一个包中有一个单独的过程:

   procedure Idle_Scroll (Object : access Gtk_Widget_Record'Class) is

      Iter        : Gtk_Text_Iter;
      Scroll_Okay : Boolean;

   begin

      Get_End_Iter (TextBuffer, Iter);
      Scroll_Okay := Scroll_To_Iter
        (TextView, Iter, 0.0, True, 1.0, 1.0);

   end Idle_Scroll;

所以我只想知道如何设置适当的空闲处理程序。感激地收到任何帮助。

除了下面的答案(谢谢),我已经尝试修改代码,将过程更改为函数,它似乎朝着正确的方向发展。尝试调用 Idle_Scroll 回调时我仍然卡住,我收到错误'...在 glib-main.ads 中定义的预期类型“G_Source_Func”...找到对函数“Idle_Scroll”的类型访问...'我试图在读取 glibmain.h 中的条目后,设置传递给 G_Source_Func 类型的 Idle_Scroll 的参数,但我似乎在绕圈子。我在这里上传到 sourceforge 的完整代码:https ://sourceforge.net/projects/test-textview/files/

标签: gtkada

解决方案


设法让它工作。

更改了 test_textview_declare.ads 包中的声明:

   package Idle_Cb is new Glib.Main.Generic_Sources (Gtk_Text_View);

   Idle_Id : G_Source_Id;

test_textview_cb.adb 中的 Idle_Scroll 函数现在是:

   function Idle_Scroll (The_View : Gtk_Text_View) return Boolean is

      Iter        : Gtk_Text_Iter;
      Scroll_Okay : Boolean;

   begin

      Get_End_Iter (TextBuffer, Iter);
      Scroll_Okay := Scroll_To_Iter
        (The_View, Iter, 0.0, True, 1.0, 1.0);
      return True;

   end Idle_Scroll;

“return True”是拼图的最后一块。我曾多次阅读参考手册,但错过了我需要该行以使空闲功能继续运行的事实。今天下午,我在程序执行时运行了 Idle_Scroll,但只运行了一次。Return True 确保它被重复调用。

我之前还编辑了该行以在 test_textview_start.adb 中添加空闲函数:

 Idle_Id := Idle_Cb.Idle_Add (Idle_Scroll'Access, TextView);

再次感谢您的帮助。

说得太早了。

我的上述解决方案效果很好。将 GEntry 中的文本输入 Text_View 后,它会自动滚动到底部,但我无法将滚动条向上移动以查看较早的内容。

解决此问题的方法是将调用 Idle_Add 移动到回调包 test_testview.adb 中,并在函数 Idle_Scroll 中将返回行更改为“Return := False;”。这样在输入文本后它会滚动到底部,但仍然允许上下移动滚动条。

test_textview.adb 的最终版本如下所示:

package body Test_TextView_Cb is


   function Idle_Scroll (The_View : Gtk_Text_View) return Boolean is

      Iter    : Gtk_Text_Iter;
      Success : Boolean;

   begin

      Get_End_Iter (TextBuffer, Iter);
      Success := Scroll_To_Iter (The_View, Iter, 0.0, True, 1.0, 1.0);
      return False;

   end Idle_Scroll;


   procedure Insert_Text (OutStr: String) is

      Iter : Gtk_Text_Iter;

   begin

      Get_End_Iter (TextBuffer, Iter);
      Insert (TextBuffer, Iter, "You entered:" & ASCII.LF
        & OutStr & ASCII.LF);
      Idle_Id := Idle_Cb.Idle_Add     (Idle_Scroll'Access, TextView);

   end Insert_Text;


   procedure Enter_Pressed (Self : access     Gtk_Widget_Record'Class) is
      Entered_Text : String := Get_Text (Cmd_Entry);

   begin

      Insert_Text (Entered_Text);
      Set_Text (Cmd_Entry, "");

   end Enter_Pressed;


   procedure Main_Quit (Self : access Gtk_Widget_Record'Class) is

   begin

      Gtk.Main.Main_Quit;

   end Main_Quit;


   procedure Button_Quit (Self : access Gtk_Widget_Record'Class) is

   begin

      Destroy (Self);

   end Button_Quit;


end Test_TextView_Cb;

推荐阅读