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}
但是,当我在Button
的Clicked
事件中打印Button
小部件的Allocation
时,它会按预期打印渲染大小。然而,在上面的场景中,它只打印1和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与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#中被称为什么。