admin管理员组文章数量:1310450
I have a Gtk.Label in an app I am working on migrating from Gtk3 to Gtk4. In Gtk3, Label had a set_angle
method that allowed rotating a label about its center.
That was removed in Gtk4, but there isn't any clear guidance on how to accomplish the same thing.
Following a few comments on various forum threads, I've tried using a CSS transform like
#my-widget {
transform: rotate(90deg);
}
this does rotate the content of the label, but it doens't seem to rotate the size of the label, so the text ends up overlapping other widgets and/or getting truncated if it is near the edge of the window.
I've also tried implementing a custom measure
method that swaps the orientation, and a custom size_allocate
that passes in a rotated transform to gtk_widget_allocate
on the child widget. But then the text doesn't show up at all. I think because it is rotating around the origin instead of the center. Rotating around the center would require knowing the actual size of the widget.
I've also seen suggestions to use pango directly, but that adds significant complexity, and requires calculating the size of the rotated text myself.
Surely there is a simpler way to accomplish this?
I'd really love to see a working example of how to do this.
I have a Gtk.Label in an app I am working on migrating from Gtk3 to Gtk4. In Gtk3, Label had a set_angle
method that allowed rotating a label about its center.
That was removed in Gtk4, but there isn't any clear guidance on how to accomplish the same thing.
Following a few comments on various forum threads, I've tried using a CSS transform like
#my-widget {
transform: rotate(90deg);
}
this does rotate the content of the label, but it doens't seem to rotate the size of the label, so the text ends up overlapping other widgets and/or getting truncated if it is near the edge of the window.
I've also tried implementing a custom measure
method that swaps the orientation, and a custom size_allocate
that passes in a rotated transform to gtk_widget_allocate
on the child widget. But then the text doesn't show up at all. I think because it is rotating around the origin instead of the center. Rotating around the center would require knowing the actual size of the widget.
I've also seen suggestions to use pango directly, but that adds significant complexity, and requires calculating the size of the rotated text myself.
Surely there is a simpler way to accomplish this?
I'd really love to see a working example of how to do this.
Share Improve this question asked Feb 3 at 9:12 ThayneThayne 7,0423 gold badges46 silver badges73 bronze badges1 Answer
Reset to default 0There are certainly several variants to rotate a widget. In my variant, I created my own class "rotated_label", which I can then use flexibly.
class_rotated_label.h
// class-rotated-label.h
#pragma once
#include<gtk/gtk.h>
#define ROTATED_TYPE_LABEL (rotated_label_get_type())
G_DECLARE_FINAL_TYPE (RotatedLabel, rotated_label, ROTATED, LABEL, GtkWidget)
GtkWidget *rotated_label_new(int angle, const char *text);
class_rotated_label.c
// class-rotated-label.c
#include"class-rotated-label.h"
#include<math.h>
struct _RotatedLabel
{
GtkWidget parent_instance;
GtkWidget *label;
int angle;
int flag;
};
struct _RotatedLabelClass
{
GtkWidgetClass parent_class;
};
G_DEFINE_TYPE (RotatedLabel, rotated_label, GTK_TYPE_WIDGET)
static void
rotated_label_init(RotatedLabel *self)
{
self->label = gtk_label_new("");
self->flag = 0;
gtk_widget_set_parent(GTK_WIDGET(self->label),GTK_WIDGET(self));
// LayoutManager
GtkLayoutManager *center_layout;
center_layout = gtk_widget_get_layout_manager (GTK_WIDGET(self));
gtk_center_layout_set_start_widget (GTK_CENTER_LAYOUT (center_layout),self->label);
}
static void
rotated_label_snapshot (GtkWidget *widget,
GtkSnapshot *snapshot)
{
RotatedLabel *self = ROTATED_LABEL (widget);
int angle = self->angle;
GtkWidget *child;
child = gtk_widget_get_first_child(widget);
int child_width, child_height;
child_width = gtk_widget_get_width (child);
child_height = gtk_widget_get_height(child);
gtk_snapshot_translate(snapshot, &(graphene_point_t){child_width / 2,child_height /2});
gtk_snapshot_rotate (snapshot,angle);
gtk_snapshot_translate(snapshot, &(graphene_point_t){- child_width / 2,- child_height /2.});
gtk_widget_snapshot_child (widget, child, snapshot);
// Calculate the necessary height of the widget
double radiant = angle * (M_PI / 180 );
double sinus = sin(radiant);
double cosinus = cos(radiant);
double result = child_width * ABS(sinus) + child_height * ABS(cosinus);
// only apply once during initialization
if (self->flag == 0)
{
gtk_widget_set_size_request(GTK_WIDGET(self),-1,result);
self->flag = 1;
}
}
static void rotated_label_dispose(GObject *gobject)
{
RotatedLabel *self = ROTATED_LABEL(gobject);
g_clear_pointer(&self->label,gtk_widget_unparent);
G_OBJECT_CLASS (rotated_label_parent_class)->dispose;
}
static void
rotated_label_class_init (RotatedLabelClass *class)
{
G_OBJECT_CLASS(class)->dispose = rotated_label_dispose;
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
widget_class->snapshot = rotated_label_snapshot;
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_CENTER_LAYOUT);
}
GtkWidget *
rotated_label_new (int angle, const char* text)
{
RotatedLabel *self;
self = g_object_new (ROTATED_TYPE_LABEL,NULL);
self->angle = angle;
gtk_label_set_text(GTK_LABEL(self->label),text);
return GTK_WIDGET (self);
}
One possible application could then be as follows:
// rotated-label.c
#include"rotated-label.h"
#include"class-rotated-label.h"
void activate (GtkApplication *app, gpointer data)
{
GtkWidget *window;
window =gtk_application_window_new(app);
GtkWidget *box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL,0);
GtkWidget *label = rotated_label_new(0,"- first -");
GtkWidget *label1 = rotated_label_new(45,"- second -");
GtkWidget *label2 = rotated_label_new(90,"- third -");
GtkWidget *label3 = rotated_label_new(135,"- fourth -");
GtkWidget *label4 = rotated_label_new(180,"- fifth -");
gtk_box_append(GTK_BOX(box),label);
gtk_box_append(GTK_BOX(box),label1);
gtk_box_append(GTK_BOX(box),label2);
gtk_box_append(GTK_BOX(box),label3);
gtk_box_append(GTK_BOX(box),label4);
gtk_window_set_child(GTK_WINDOW(window),box);
gtk_widget_set_visible(window,TRUE);
}
The result looks like this:
I should perhaps add that I wanted to show just one of the principles. The example is of course still expandable.
Have fun programming.
本文标签: gtkHow to rotate a widget in Gtk4Stack Overflow
版权声明:本文标题:gtk - How to rotate a widget in Gtk4 - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741831176a2399939.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论