强制 GtkLabel 裁剪其居中对齐的文本
Force GtkLabel to clip its center-aligned text
我有一个 GtkLabel
其文本将保持居中,无论它比标签短还是长。
例如,设置了 SS_CENTER
样式标志的 Win32 静态控件的行为如下:
┌===========================┐
│ Lorem ipsum dolor │
└===========================┘
— when the text is shorter than the control;
┌===========================┐
Lorem ipsum│dolor sit amet, consectetur│adipiscing
└===========================┘
— when the text is longer than the control.
N.B.: 用户看到的唯一部分文本在框架内。
我原以为 GtkLabel
-s 会做同样的事情,但实际上它们以不同的方式呈现居中文本:
┌===========================┐
│ Lorem ipsum dolor │
└===========================┘
— when the text is shorter than the control;
┌===========================┐
│Lorem ipsum dolor sit amet,│consectetur adipiscing
└===========================┘
— when the text is longer than the control.
如何使 GtkLabel
中的居中文本即使很长也能保持居中?
以防万一:用户看到的实际文本以约 4 FPS 的速度更新,并且在运行前是未知的。
这可能是可行的,但从用户体验的角度来看,显示句子的半随机部分并没有多大意义。
也许可以看看 gtk_label_set_ellipsize
?
他们使用 PangoEllipsizeMode
来告诉隐藏句子的哪一部分。然后您可以隐藏标签的开头、中间或结尾部分。不过它是一个枚举,而不是一个标志,因此您将无法隐藏开始 + 结束以仅显示中间部分。
所以我看到的可能的解决方案是:
- 继承 GtkLabel 并自己绘制,可能使用 PangoCairo
- 或者在 GTK+ 中添加新的 wrap 模式并实现它(在 pango 内?PangoCairo?两者?)
如果这不是一个强烈的要求,只需使用更明智的行为并使用现有的 elipsize 模式。
解决方案终于准备好了。
#include <gtk/gtk.h>
struct SCTX {
GtkWidget *text;
GdkRectangle rect;
};
void Resize(GtkWidget *view, GdkRectangle *rect, gpointer user) {
struct SCTX *sctx = user;
GtkRequisition requ;
if ((sctx->rect.width != rect->width )
|| (sctx->rect.height != rect->height)) {
sctx->rect = *rect;
gtk_widget_size_request(sctx->text, &requ);
gtk_layout_move(view, sctx->text, (rect->width - requ.width ) / 2,
(rect->height - requ.height) / 2);
}
}
int main(int argc, char *argv[]) {
GtkWidget *hwnd, *view;
struct SCTX sctx = {0};
gtk_init(&argc, &argv);
hwnd = gtk_window_new(GTK_WINDOW_TOPLEVEL);
g_signal_connect(hwnd, "destroy", gtk_main_quit, 0);
view = gtk_layout_new(0, 0);
g_signal_connect(view, "size-allocate", G_CALLBACK(Resize), &sctx);
gtk_widget_set_size_request(view, 320, 200);
sctx.text = gtk_label_new("Lorem ipsum dolor sit amet, consectetur "
"adipiscing elit, sed do eiusmod tempor "
"incididunt ut labore et dolore magna aliqua");
gtk_container_add(view, sctx.text);
gtk_container_add(hwnd, view);
gtk_container_set_border_width(GTK_CONTAINER(hwnd), 32);
gtk_window_set_position(GTK_WINDOW(hwnd), GTK_WIN_POS_CENTER);
gtk_widget_show_all(hwnd);
gtk_main();
return 0;
}
这里的关键部分是将 GtkLayout
包裹在我们的 GtkLabel
周围,以便前者可以在其范围内移动后者。
我有一个 GtkLabel
其文本将保持居中,无论它比标签短还是长。
例如,设置了 SS_CENTER
样式标志的 Win32 静态控件的行为如下:
┌===========================┐ │ Lorem ipsum dolor │ └===========================┘
— when the text is shorter than the control;
┌===========================┐ Lorem ipsum│dolor sit amet, consectetur│adipiscing └===========================┘
— when the text is longer than the control.
N.B.: 用户看到的唯一部分文本在框架内。
我原以为 GtkLabel
-s 会做同样的事情,但实际上它们以不同的方式呈现居中文本:
┌===========================┐ │ Lorem ipsum dolor │ └===========================┘
— when the text is shorter than the control;
┌===========================┐ │Lorem ipsum dolor sit amet,│consectetur adipiscing └===========================┘
— when the text is longer than the control.
如何使 GtkLabel
中的居中文本即使很长也能保持居中?
以防万一:用户看到的实际文本以约 4 FPS 的速度更新,并且在运行前是未知的。
这可能是可行的,但从用户体验的角度来看,显示句子的半随机部分并没有多大意义。
也许可以看看 gtk_label_set_ellipsize
?
他们使用 PangoEllipsizeMode
来告诉隐藏句子的哪一部分。然后您可以隐藏标签的开头、中间或结尾部分。不过它是一个枚举,而不是一个标志,因此您将无法隐藏开始 + 结束以仅显示中间部分。
所以我看到的可能的解决方案是:
- 继承 GtkLabel 并自己绘制,可能使用 PangoCairo
- 或者在 GTK+ 中添加新的 wrap 模式并实现它(在 pango 内?PangoCairo?两者?)
如果这不是一个强烈的要求,只需使用更明智的行为并使用现有的 elipsize 模式。
解决方案终于准备好了。
#include <gtk/gtk.h>
struct SCTX {
GtkWidget *text;
GdkRectangle rect;
};
void Resize(GtkWidget *view, GdkRectangle *rect, gpointer user) {
struct SCTX *sctx = user;
GtkRequisition requ;
if ((sctx->rect.width != rect->width )
|| (sctx->rect.height != rect->height)) {
sctx->rect = *rect;
gtk_widget_size_request(sctx->text, &requ);
gtk_layout_move(view, sctx->text, (rect->width - requ.width ) / 2,
(rect->height - requ.height) / 2);
}
}
int main(int argc, char *argv[]) {
GtkWidget *hwnd, *view;
struct SCTX sctx = {0};
gtk_init(&argc, &argv);
hwnd = gtk_window_new(GTK_WINDOW_TOPLEVEL);
g_signal_connect(hwnd, "destroy", gtk_main_quit, 0);
view = gtk_layout_new(0, 0);
g_signal_connect(view, "size-allocate", G_CALLBACK(Resize), &sctx);
gtk_widget_set_size_request(view, 320, 200);
sctx.text = gtk_label_new("Lorem ipsum dolor sit amet, consectetur "
"adipiscing elit, sed do eiusmod tempor "
"incididunt ut labore et dolore magna aliqua");
gtk_container_add(view, sctx.text);
gtk_container_add(hwnd, view);
gtk_container_set_border_width(GTK_CONTAINER(hwnd), 32);
gtk_window_set_position(GTK_WINDOW(hwnd), GTK_WIN_POS_CENTER);
gtk_widget_show_all(hwnd);
gtk_main();
return 0;
}
这里的关键部分是将 GtkLayout
包裹在我们的 GtkLabel
周围,以便前者可以在其范围内移动后者。