C# Gtk 获取渲染大小

C# Gtk get rendered size

在 Gtk#(使用 Mono)中,我有时需要将默认大小分配给 widget(我知道你是通过 widget.SetSizeRequest(-1, -1); 来做的。如果这不是正确的方式)。我这样做是为了确保 Button 小部件的大小符合预期。我不希望它太大或太小。分配默认大小可确保按钮不会太大但也不会太小。

因此,当我将默认大小分配给小部件时,widget.GetSizeRequest(out width, out height); returns -1 和 -1 分别用于宽度和高度。
这是预期的,但不是我需要的。我需要知道呈现的大小(分别为宽度和高度),因为我需要相对于它放置另一个小部件。因此,除非我知道它的大小,否则我无法将其他小部件放在正确的位置。

虽然在其他情况下了解渲染大小会有所帮助,但这是主要原因。

我希望你明白我所说的渲染大小的意思。

更新:
由于答案似乎建议使用 widget.Allocation 尽管我已经尝试过(请参阅我的评论),但这是我尝试过的:

Widget[] widgets = GetWidgets();//I initialize the widgets somewhere and get them as an array

//fix is a Gtk.Fixed container
foreach(Widget widget in widgets)
{
    //although this is not the exact way I place the widgets, this is just an example
    fix.Put(widget, GetPosition(widget).X, GetPosition(widget).Y);
    widget.SetSizeRequest(-1, -1);
    Console.WriteLine(w.Allocation.Size);
}
//later on, I need to place a few widgets relative to another

这段代码的输出是:

{Width=1, Height=1}
{Width=1, Height=1}
{Width=1, Height=1}
{Width=1, Height=1}
{Width=1, Height=1}
{Width=1, Height=1}

但是,当我在 ButtonClicked 事件中打印一个 Button 小部件的 Allocation 时,它会按预期打印呈现的大小.然而,在上面的场景中,它只打印 1 和 1.
谁能找出我做错了什么?

您正在查找分配 属性(gtk 中的get_allocation)。

示例:

protected void OnButton2Clicked (object sender, EventArgs e)
{
    var rect = button.Allocation;
    PropertyInfo[] properties = rect.GetType().GetProperties();
    var sb = new System.Text.StringBuilder();
    foreach (PropertyInfo pi in properties)
    {
        sb.Append(
            string.Format("Name: {0} | Value: {1}\n", 
                pi.Name, 
                pi.GetValue(rect, null)
            ) 
        );
    }
    Console.WriteLine (sb);
}

输出:

Name: GType | Value: GdkRectangle
Name: Top | Value: 50
Name: Bottom | Value: 82
Name: Right | Value: 69
Name: Left | Value: 30
Name: IsEmpty | Value: False
Name: Size | Value: {Width=40, Height=33}
Name: Location | Value: (30,50)

更新:

尚未呈现的小部件(包括 Visible=false)没有任何容器分配,因为它不需要任何容器,因此其余可见小部件的打包将正确发生。

Name: GType | Value: GdkRectangle
Name: Top | Value: -1
Name: Bottom | Value: -1
Name: Right | Value: -1
Name: Left | Value: -1
Name: IsEmpty | Value: False
Name: Size | Value: {Width=1, Height=1}
Name: Location | Value: (-1,-1)

如果您确实需要真实的渲染大小(使用当前字体、边框等...),则需要在某处渲染它。真正的 hack 是将它放在双缓冲固定容器上并 'render' 但从不显示它。从中获取并保存分配(可能在字典中),删除小部件并为下一个小部件执行此操作。现在你有了一个与当前运行时环境相匹配的小部件大小的字典......就像我说的,一个真正的 hack......

同时问这个问题一个 Gtk 标记的 C 语言问题,或者在他们的邮件列表上,可能会给你一个更好的答案,他们的答案是 C vs C#,根据需要转换它。请务必提及您需要在 Gtk2 中执行此操作,因为 Gtk3 确实 不同。

您要查找的内容在 widget.Allocation 中,但大小仅在 Expose 事件中设置。这为您提供了小部件的渲染大小。我猜你也在使用 Fixed 容器。 widget.SetSizeRequest(-1, -1) 清除所有已编程的大小调整并让 Gtk 库按其需要的大小执行操作。除非您真的需要严格控制每个小部件的放置位置,否则最好使用 VBox 和 HBox 等容器。 Gtk 的优点之一是它为您做了很多小部件的更精细对齐。

编辑:

您一次只能绘制一个小部件。有点,有点 "recursion"。一旦 Gtk 运行 时间调用公开事件处理程序,小部件的大小就已经确定,因此您可以使用它来放置下一个小部件。这是一个真正简化的示例,它在向下的对角线处绘制了三个按钮。

int idx;
string[] userDefinedText;
Fixed fix;

public MainWindow () : base (Gtk.WindowType.Toplevel) {
    Build ();

    // I'm not really sure how you store the text or just a list of widgets 
    // but for the sake of simplicity I'm just using a string array
    idx = 0;
    userDefinedText = new string[3] { "Medium text length", "Long text that goes on and on", "Short" };

    fix = new Fixed ();
    fix.SetSizeRequest (400, 400);
    Add (fix);
    fix.Show ();

    Button b = new Button ();
    b.SetSizeRequest (-1, -1);
    b.Label = userDefinedText [idx];
    b.ExposeEvent += OnButtonExposeEvent;
    fix.Put (b, 5, 5);
    b.Show ();

    ShowAll ();
}

protected void OnButtonExposeEvent (object sender, ExposeEventArgs args) {
    if (idx < (userDefinedText.Length - 1)) {
        // There are still widgets to be placed on the screen
        ++idx;

        Button b = sender as Button;
        int x = b.Allocation.Right;
        int y = b.Allocation.Bottom;

        Button b2 = new Button ();
        b2.SetSizeRequest (-1, -1);
        b2.Label = userDefinedText [idx];
        b2.ExposeEvent += OnButtonExposeEvent;
        fix.Put (b2, x + 5, y + 5);
        b2.Show ();
    }
}

最后一点,仅当您使用 GTK+ 3 时:

我真的不知道你想要得到的尺寸是什么,但是如果你正在实现自己的容器并且想看看小部件的尺寸想要 是(在某种程度上比 RobertN 的 "real hack" 更好)是使用首选尺寸系统。 GTK+ 3 有 get_preferred_width()get_preferred_height() 等方法,其中 return 都是 minimum(绝对最小值,所以只是...的宽度)例如,对于标签)和 natural(小部件希望保持其每个部分都可见的更合理的大小)您可以使用的大小;查看哪个更适合您的用例。对于高度与宽度和宽度与高度的几何图形也有等价物(如果你决定这样做的话)。

我不知道在 C# 中调用这些方法是什么。