C#Gtk获取渲染大小

本文关键字:获取 C#Gtk | 更新日期: 2023-09-27 17:59:52

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

因此,当我为小部件分配默认大小时,widget.GetSizeRequest(out width, out height);分别返回宽度和高度的-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。
有人能认出我做错了什么吗?

C#Gtk获取渲染大小

您正在查看Allocation属性(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)

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

同样问这个问题,Gtk标记的C语言问题,或者在他们的邮件列表上,可能会给你一个更好的答案,他们的答案是C与C#,根据需要进行转换。请确保您在Gtk2中提到您需要这样做,因为Gtk3是真正的不同。

您要查找的是widget.Allocation,但大小仅在Expose Event中设置。这将为您提供小部件的渲染大小。我猜你也在使用一个固定的容器。widget.SetSizeRequest(-1, -1)清除任何已编程的大小,并允许Gtk库对大小执行它想要的操作。除非您真的需要严格控制每个小部件的放置位置,否则最好使用VBox和HBox等容器。Gtk的一个优点是,它为您完成了许多小部件的精细对齐。

编辑:

您可以一次只绘制一个小部件。它有点,有点"递归"。一旦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的"真正破解"更好),那就是使用首选尺寸系统。GTK+3有get_preferred_width()get_preferred_height()等方法,它们返回可以使用的最小(例如,绝对最小值,因此仅为标签的宽度)和自然大小(小部件更喜欢保持其每个部分可见的更合理的大小);看看哪一个更适合您的用例。高度对应宽度,宽度对应高度几何体(如果您决定这样做的话)。

我不知道这些方法在C#中被称为什么。