我希望使用透明/半透明背景(或没有背景)渲染文本,而不是像GtkImage或GtkButton等其他gtk小部件。 主要目标是在后台将文本显示在Gtk Widgets(尤其是GtkImage)上。 我可以使用pangocairo库在GtkFrame上渲染文本,但我无法摆脱GtkFrame的背景。
我见过让GtkWindow变得透明或半透明的例子,但是我想用GtkLayout设置不透明的GtkWindout来放置GtkWidgets,然后将GtkImage放在布局上并在GtkImage上渲染Text,这样它就为我的文本提供了一个很好的背景
我也尝试过使用GtkDrawingArea,但后来我在创建cairo上下文时迷路了 pixbuf和渲染文本。任何帮助表示赞赏。
注意:我正在使用Compiz来合成窗口。
答案 0 :(得分:1)
你可以使用GtkOverlay小部件(至少Gtk + 3.2)
GtkOverlay - 一个将小部件叠加在一起的容器
答案 1 :(得分:0)
这是执行此操作的整个程序。构建和运行它所需的一切都在GitHub上。
https://github.com/sweckhoff/GTK-Cairo-Sinusoids/blob/master/gtk_cairo_sinusoid_plot.c
#include <gtk/gtk.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
const gdouble pi = 3.14159265359;
#define ERASER_WIDTH 150
#define LABEL_STR_LEN 20
typedef struct {
gint width;
gint height;
gdouble rad_step;
gint scale_factor;
gint y_zero;
gint x_step;
gdouble rads;
gint last_x;
gint last_y;
gint current_x;
gint current_y;
gint current_eraser_x;
cairo_surface_t *plot_surface;
cairo_t *plot;
cairo_t *eraser;
GtkWidget *widget;
GtkWidget *label;
gdouble (*funct)(gdouble);
} graph_data_packet_t;
gboolean
do_graph (graph_data_packet_t *packet)
{
static gchar label_str[LABEL_STR_LEN];
if (packet->rads >= 2.0) {
packet->rads = 0.0;
}
gdouble pi_rads = pi * packet->rads;
snprintf(label_str, LABEL_STR_LEN, "%s%f%s", "Radians ", packet->rads, "pi");
gtk_label_set_text(GTK_LABEL(packet->label), label_str);
packet->rads += packet->rad_step;
if (packet->current_x > packet->width) {
packet->current_x = 0;
}
packet->last_x = packet->current_x;
packet->last_y = packet->current_y;
packet->current_x += packet->x_step;
packet->current_y = packet->y_zero - (packet->scale_factor * packet->funct (pi_rads));
packet->current_eraser_x += packet->x_step;
if (packet->current_eraser_x > packet->width) {
packet->current_eraser_x = 0;
}
gtk_widget_queue_draw(packet->widget);
return TRUE;
}
gboolean
draw_callback (GtkWidget *widget, cairo_t *drawing_area, graph_data_packet_t *packet)
{
// Erase Old
cairo_move_to (packet->eraser, packet->current_eraser_x, 0);
cairo_line_to (packet->eraser, packet->current_eraser_x, packet->height);
cairo_stroke(packet->eraser);
// Plot New
cairo_move_to (packet->plot, packet->last_x, packet->last_y);
cairo_line_to (packet->plot, packet->current_x, packet->current_y);
cairo_stroke (packet->plot);
// Apply source to drawing area
cairo_set_source_surface (drawing_area, packet->plot_surface, 0.0, 0.0);
cairo_paint(drawing_area);
return FALSE;
}
static void
destroy (GtkWidget *window, gpointer data)
{
gtk_main_quit();
}
gboolean
delete_event (GtkWidget *window, GdkEvent *event, gpointer data)
{
return FALSE;
}
int
main(int argc, char **argv)
{
GtkWidget *window = NULL;
GtkWidget *overlay = NULL;
GtkWidget *image_background = NULL;
GtkWidget *image = NULL;
GtkWidget *drawing_area = NULL;
GtkWidget *label = NULL;
graph_data_packet_t packet = {
.width = 400,
.height = 200,
.rad_step = 0.05,
.scale_factor = 75,
.y_zero = 100,
.x_step = 1,
.rads = 0.0,
.last_x = 0,
.last_y = 0,
.current_x = 0,
.current_y = 0,
.current_eraser_x = ERASER_WIDTH,
.plot_surface = NULL,
.plot = NULL,
.eraser = NULL,
.widget = NULL,
.label = NULL,
.funct = NULL
};
if (argc > 1) {
if (!strcmp("sine", argv[1])) {
packet.funct = sin;
} else if (!strcmp("cosine", argv[1])) {
packet.funct = cos;
} else {
packet.funct = sin;
}
} else {
packet.funct = sin;
}
gtk_init(&argc, &argv);
// Setup Cairo stuff
packet.plot_surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 400, 200);
if (NULL == packet.plot_surface) {
return EXIT_FAILURE;
}
packet.plot = cairo_create (packet.plot_surface);
if (NULL == packet.plot) {
return EXIT_FAILURE;
}
cairo_set_source_rgb (packet.plot, 1.0, 0.0, 0.0);
packet.eraser = cairo_create (packet.plot_surface);
if (NULL == packet.eraser) {
return EXIT_FAILURE;
}
cairo_set_source_rgba (packet.eraser, 0.0, 0.0, 0.0, 0.0);
cairo_set_operator(packet.eraser, CAIRO_OPERATOR_CLEAR);
// Window
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
if(NULL == window) {
return EXIT_FAILURE;
}
packet.widget = window;
gtk_widget_set_size_request (window, 400, 200);
g_signal_connect (G_OBJECT (window), "destroy",
G_CALLBACK (destroy), NULL);
g_signal_connect (G_OBJECT (window), "delete_event",
G_CALLBACK (delete_event), NULL);
// Overlay
overlay = gtk_overlay_new ();
if (NULL == overlay) {
return EXIT_FAILURE;
}
// Background Image
image = gtk_image_new_from_file ("plot_background.png");
if (NULL == image) {
return EXIT_FAILURE;
}
image_background = gtk_image_new_from_file ("pi_background.png");
if (NULL == image_background) {
return EXIT_FAILURE;
}
// Plot
drawing_area = gtk_drawing_area_new ();
if (NULL == drawing_area) {
return EXIT_FAILURE;
}
gtk_widget_set_size_request (drawing_area, 400, 200);
g_signal_connect (G_OBJECT (drawing_area), "draw",
G_CALLBACK (draw_callback), &packet);
// Label
label = gtk_label_new ("Radians: 0.0 pi");
if (NULL == label) {
return EXIT_FAILURE;
}
packet.label = label;
gtk_widget_set_halign (label, GTK_ALIGN_START);
gtk_widget_set_valign (label, GTK_ALIGN_END);
// Put it all together
gtk_container_add(GTK_CONTAINER(overlay), image_background);
gtk_overlay_add_overlay (GTK_OVERLAY (overlay), image);
gtk_overlay_add_overlay (GTK_OVERLAY (overlay), drawing_area);
gtk_overlay_add_overlay (GTK_OVERLAY (overlay), label);
gtk_container_add (GTK_CONTAINER (window), overlay);
gtk_widget_show_all (window);
g_timeout_add(100, (GSourceFunc) do_graph, &packet);
gtk_main();
return EXIT_SUCCESS;
}