Заставить GtkLabel обрезать выравниваемый по центру текст

У меня есть GtkLabel чей текст должен оставаться в центре независимо от того, короче он или длиннее надписи.

Например, статический элемент управления Win32, который имеет SS_CENTER набор флагов стиля ведет себя так:

             ┌===========================┐
             │     Lorem ipsum dolor     │
             └===========================┘

- когда текст короче контрольного;

             ┌===========================┐
  Lorem ipsum│dolor sit amet, consectetur│adipiscing
             └===========================┘

- когда текст длиннее контрольного.

NB. Единственная часть текста, видимая пользователем, находится внутри фрейма.

Я ожидал GtkLabel-сделать одно и то же, но на самом деле они отображают центрированный текст по-разному:

             ┌===========================┐
             │     Lorem ipsum dolor     │
             └===========================┘

- когда текст короче контрольного;

             ┌===========================┐
             │Lorem ipsum dolor sit amet,│consectetur adipiscing
             └===========================┘

- когда текст длиннее контрольного.

Как сделать центрированный текст в GtkLabel оставаться в центре, даже когда это долго?

На всякий случай: фактический текст, который видит пользователь, обновляется со скоростью ~4 FPS и неизвестен до времени выполнения.

2 ответа

Это может быть выполнимо, но показ полуслучайной части предложения не имеет смысла с точки зрения пользовательского опыта.

Может быть, посмотреть gtk_label_set_ellipsize? Они используют PangoEllipsizeMode сказать, какую часть предложения скрыть. Затем вы можете скрыть начальную, среднюю или конечную часть метки. Это перечисление, а не флаг, поэтому вы не сможете скрыть начало и конец, чтобы показать только среднюю часть.

Итак, возможные решения, которые я вижу:

  • подкласс GtkLabel и сделать рисунок самостоятельно, возможно, с PangoCairo
  • или добавить новый режим обтекания в GTK+ и реализовать его (внутри 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 так что первый мог перемещать последнего в его пределах.

Другие вопросы по тегам