使用Vala

时间:2017-01-02 13:31:01

标签: segmentation-fault widget gtk vala

我正在尝试使用Vala创建一个简单的自定义GTK小部件:

public class PageView : Gtk.Widget {

    public PageView () {
        //base ();
        set_name ("pageview");
        set_has_window (true);
    }


    /*
     *              Method and Signal Overrides
     */

    public override Gtk.SizeRequestMode get_request_mode () {
        return Gtk.SizeRequestMode.CONSTANT_SIZE;
            // Don’t trade height-for-width or width-for-height
    }

    public override void get_preferred_width
                                               (out int minimum,
                                                out int natural) {
        stdout.printf ("PageView#get_preferred_width\n");
        minimum = natural = pg_pixel_width;
    }

    public override void get_preferred_height
                                               (out int minimum,
                                                out int natural) {
        stdout.printf ("PageView#get_preferred_height\n");
        minimum = natural = pg_pixel_height;
    }

    public override void get_preferred_width_for_height
                                               (    int height,
                                                out int minimum,
                                                out int natural) {
        stdout.printf ("PageView#get_preferred_width_for_height\n");
        minimum = natural = pg_pixel_width;
    }

    public override void get_preferred_height_for_width
                                               (    int width,
                                                out int minimum,
                                                out int natural) {
        stdout.printf ("PageView#get_preferred_height_for_width\n");
        minimum = natural = pg_pixel_height;
    }


    public override void size_allocate (Gtk.Allocation alloc) {
        stdout.printf ("PageView#size_allocate\n");

        set_allocation (alloc);

        if (get_window() != null) {
            get_window().move_resize (
                alloc.x, alloc.y, alloc.width, alloc.height);
        }
    }

    public override void realize () {
        stdout.printf ("PageView#realize\n");

        set_realized (true);

        if (get_window() == null) {
            Gtk.Allocation allocation;
            get_allocation (out allocation);
            _window_attr = Gdk.WindowAttr () {
                x = allocation.x,
                y = allocation.y,
                width = allocation.width,
                height = allocation.height,
                event_mask = get_events() | Gdk.EventMask.EXPOSURE_MASK,
                window_type = Gdk.WindowType.CHILD,
                wclass = Gdk.WindowWindowClass.INPUT_OUTPUT
            };
            _window_attr_type =  Gdk.WindowAttributesType.X |
                                 Gdk.WindowAttributesType.Y;

            _window = new Gdk.Window (
                get_parent_window (), _window_attr, _window_attr_type);
            set_window (_window);
        }
    }

    public override void unrealize () {
        stdout.printf ("PageView#unrealize\n");
    }


    public override bool draw (Cairo.Context cr) {
        stdout.printf ("PageView#draw\n");

        Gtk.Allocation allocation;
        get_allocation (out allocation);
        get_style_context () .render_background (cr,
            allocation.x,     allocation.y,
            allocation.width, allocation.height);

        cr.save ();
            cr.scale (allocation.width, allocation.height);
            cr.set_source_rgba (255, 255, 0, 1.0);
            cr.set_line_width (10);
            cr.line_to (1, 1);
            cr.stroke ();
        cr.restore ();


        return true;
    }


    /*
     *                  Public Attributes
     */

    public int pg_pixel_width {
        get { return 480; }
    }

    public int pg_pixel_height {
        get { return 480; }
    }


    /*
     *                  Private Members
     */

    private Gdk.Window      _window;

    private Gdk.WindowAttr  _window_attr;

    private Gdk.WindowAttributesType _window_attr_type;

}

问题是,当我将它添加到我的主Gtk.Window时,我得到了一个分段错误。这些是我得到的调试信息:

PageView#get_preferred_height
PageView#get_preferred_width
PageView#size_allocate
PageView#realize
PageView#get_preferred_height
PageView#get_preferred_width
PageView#size_allocate
PageView#size_allocate
Segmentation fault (core dumped)

似乎如果我将set_window (_window)realize ()的调用更改为set_window(null),或者我将空父窗口传递给新创建的Gdk.Window,则应用程序运行时不会分段错误(但小部件不会像在任何一种情况下那样显示)。我主要跟随this example来实现虚拟方法,并尝试在Vala中移植C代码。可能是问题的原因是什么?

2 个答案:

答案 0 :(得分:1)

最后,我从构造函数中删除了set_has_window(true),并且只实现了draw()信号。这似乎已经成功了!以下是工作代码段:

public class PageView : Gtk.Widget {

    public PageView () {
        set_name ("pageview");
    }


    /*
     *              Method and Signal Overrides
     */

    public override Gtk.SizeRequestMode get_request_mode () {
        return Gtk.SizeRequestMode.CONSTANT_SIZE;
            // Don’t trade height-for-width or width-for-height
    }

    public override void get_preferred_width
                                               (out int minimum,
                                                out int natural) {
        stdout.printf ("PageView#get_preferred_width\n");
        minimum = natural = pg_pixel_width;
    }

    public override void get_preferred_height
                                               (out int minimum,
                                                out int natural) {
        stdout.printf ("PageView#get_preferred_height\n");
        minimum = natural = pg_pixel_height;
    }

    public override void size_allocate (Gtk.Allocation alloc) {
        stdout.printf ("PageView#size_allocate\n");
        base.size_allocate (alloc);

    }

    public override void realize () {
        stdout.printf ("PageView#realize\n");
        base.realize ();
    }

    public override void unrealize () {
        stdout.printf ("PageView#unrealize\n");
        base.unrealize ();
    }


    public override bool draw (Cairo.Context cr) {
        stdout.printf ("PageView#draw\n");

        Gtk.Allocation allocation;
        get_allocation (out allocation);

        cr.set_line_width (1);
        cr.set_source_rgba (255, 255, 0, 1);    
        cr.save ();
            cr.scale (allocation.width, allocation.height);
            cr.move_to (0, 0);
            cr.line_to (1, 1);
        cr.restore ();
        cr.stroke ();

        return false;
    }

    ...

}

答案 1 :(得分:0)

这里有几点建议:

  1. 使用GDB / Nemvier / Builder调试崩溃的应用程序,以确切了解问题所在。我使用以下命令行来调试vala / gtk应用程序:

    G_DEBUG =致命警告gdb路径/到/可执行文件

  2. 使用内置的GTK功能而不是重新发明它。如果您想要将窗口小部件设置为特定大小,请使用Gtk.Widget.set_size_request(),并且您不需要上面90%的代码。要实现自定义绘图,请创建一个Gtk.DrawingArea,连接到绘制信号,实现它,然后你就完成了。