在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}
但是,当我在Allocation
的{{1}}事件中打印Button
的{{1}}小部件时,会按预期打印呈现的大小。但是,在上面的场景中,它只打印1和1
谁能确定我做错了什么?
答案 0 :(得分:1)
您正在查找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 vs C#,根据需要进行转换。请务必提及您需要在Gtk2中执行此操作,因为Gtk3 真的不同。
答案 1 :(得分:0)
您要查找的内容是widget.Allocation
,但大小仅在Expose事件中设置。这为您提供了窗口小部件的渲染大小。我猜你也在使用固定容器。 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 ();
}
}
答案 2 :(得分:0)
最后一点,只有你使用的是GTK + 3:
我真的不知道你想要获得什么样的尺寸,如果你正在实现自己的容器并希望看到小部件想要的大小(在比RobertN的“真正的黑客”更好的方法是使用首选尺寸系统。 GTK + 3有get_preferred_width()
和get_preferred_height()
等方法,它们都返回最小值(绝对最小值,因此只是标签的宽度...)和自然(小部件更喜欢的大小,以保持其每个部分可见)大小,你可以使用;看看哪一个更适合你的用例。高度宽度和高度宽度几何等效(如果您决定这样做)。
我不知道在C#中调用这些方法是什么。