【问题标题】:GTK TextView auto scroll when text is added to text buffer文本添加到文本缓冲区时 GTK TextView 自动滚动
【发布时间】:2016-06-15 01:57:08
【问题描述】:

我正在尝试创建一个非常简单的类似日志的 GUI 应用程序,它仅动态地和异步地显示来自日志文件的文本。问题是,当更新日志文件时,GUI 中的文本视图会向上滚动到第 1 行。修复此问题的每一次尝试都失败了,我想知道我是否偶然发现了 GTK 中的错误。这是我的代码的摘要:

using Cairo;
using Gtk;

namespace ServerManager {
    public class ServerManager : Window {
        public TextView text_view;
        public TextIter myIter;
        public TextMark myMark;

        public async void read_something_async (File file) {
            var text = new StringBuilder ();
            var dis = new DataInputStream (file.read ());
            string line;

            while ((line = yield dis.read_line_async (Priority.DEFAULT)) != null) {
                text.append (line);
                text.append_c('\n');
            }
            this.text_view.buffer.text = text.str;
            text_view.buffer.get_end_iter(out myIter);
            text_view.scroll_to_iter(myIter, 0, false, 0, 0);
        }

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


        var window = new ServerManager ();

        // The read-only TextView
        window.text_view = new TextView ();
        window.text_view.editable = false;
        window.text_view.cursor_visible = false;
        window.text_view.wrap_mode = Gtk.WrapMode.WORD;

        // Add scrolling functionality to the TextView
        var scroll = new ScrolledWindow (null, null);
        scroll.set_policy (PolicyType.AUTOMATIC, PolicyType.AUTOMATIC);
        scroll.add (window.text_view);

        // Vbox so that our TextView has someplace to live
        var vbox = new Box (Orientation.VERTICAL, 0);
        vbox.pack_start (scroll, true, true, 0);
        window.add (vbox);

        window.set_border_width (12);
        window.set_position (Gtk.WindowPosition.CENTER);
        window.set_default_size (800, 600);
        window.destroy.connect (Gtk.main_quit);
        window.show_all ();

        File file = File.new_for_path ("/home/user/temp.log");
        FileMonitor monitor = file.monitor (FileMonitorFlags.NONE, null);
        stdout.printf ("Monitoring: %s\n", file.get_path ());

        monitor.changed.connect (() => {
            window.read_something_async(file);
        });

        Gtk.main ();
        return 0;
        }
    }
}

我也尝试使用 TextMarks 而不是 Iters,但这没有任何影响。

【问题讨论】:

    标签: gtk gtk3 vala


    【解决方案1】:

    滚动到第一行是因为 read_something_async() 删除了缓冲区的当前内容,然后写入新的内容(这是设置 text 属性所做的)。也许这是您想要的,但除非您跟踪滚动位置,否则您将丢失它。

    你的 scroll_to_iter() 没有按预期工作的原因可能是这样的:

    请注意,此函数使用文本缓冲区中当前计算的行高。行高在空闲处理程序中计算;因此,如果在高度计算之前调用此函数,它可能不会产生预期的效果。为避免奇怪,请考虑使用 gtk_text_view_scroll_to_mark() 保存行验证后要滚动到的点。

    使用“正确的重力”TextMark 调用 TextView.ScrollToMark() 应该适合您。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-04-27
      • 2013-11-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-20
      相关资源
      最近更新 更多