如何使用 Python 和 GTK 创建具有自定义文本和透明背景的状态图标/系统托盘图标?

发布于 2024-09-05 14:28:50 字数 2014 浏览 4 评论 0原文

这是迄今为止我定义图标的代码:

icon_bg = gtk.gdk.pixbuf_new_from_file('gmail.png')
w, h = icon_bg.get_width(), icon_bg.get_height()
cmap = gtk.gdk.Colormap(gtk.gdk.visual_get_system(), False)

drawable = gtk.gdk.Pixmap(None, w, h, 24)
drawable.set_colormap = cmap
gc = drawable.new_gc()
drawable.draw_pixbuf(gc, icon_bg, 0, 0, 0, 0, w, h)

drawn_icon = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, False, 8, w, h)
drawn_icon.get_from_drawable(drawable, cmap, 0, 0, 0, 0, w, h)
icon = gtk.status_icon_new_from_pixbuf(drawn_icon)

这可以将 png 放入图标中,但在两个方面存在不足。首先,透明度不起作用。如果我使用具有透明背景且图像居中的 22x22 png,则最终会在我的内部显示其他活动图标的部分,如下所示:

http://i237.photobucket.com/albums/ff311/Raugturi/22x22_image_with_transparency.png

它选择窃取的图标有些随机。有时它是保管箱图标的一部分,有时是 NetworkManager 小程序的一部分。

如果我改为使用此代码:

icon_bg = gtk.gdk.pixbuf_new_from_file('gmail.png')
w, h = icon_bg.get_width(), icon_bg.get_height()
cmap = gtk.gdk.Colormap(gtk.gdk.visual_get_system(), False)

drawable = gtk.gdk.Pixmap(None, w, h, 24)
drawable.set_colormap = cmap
gc = drawable.new_gc()
drawable.draw_pixbuf(gc, icon_bg, 0, 0, 0, 0, w, h)

drawn_icon = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, False, 8, 22, 22)
drawn_icon.get_from_drawable(drawable, cmap, 0, 0, 3, 6, w, h)
icon = gtk.status_icon_new_from_pixbuf(drawn_icon)

并且删除了透明边缘的仅 16x11 的图像,我最终得到的是:

http://i237.photobucket.com/albums/ff311/Raugturi/16x11_image_positioned_in_middle.png

那么我怎样才能得到像第一个这样的透明块呢?不从其他图标中提取内容吗?

至于第二个问题,我需要能够在将图像转换为图标之前在图像上书写。我尝试使用draw_glyphs,它告诉我应该使用Pango布局/上下文。不幸的是,我能找到的所有 Pango 教程都涉及实际窗口,而不是状态图标。 Pango 是否有一个很好的教程适用于这个问题(并且可能至少有一些关于如何告诉它使用什么字体的解释,因为我发现它们似乎都缺乏这个并且它不会写没有它的任何东西)。

注意:抱歉,缺少实际图像且只有一个有效链接,显然这是一项垃圾邮件预防功能,因为我缺乏声誉。

Here is the code that I have so far to define the icon:

icon_bg = gtk.gdk.pixbuf_new_from_file('gmail.png')
w, h = icon_bg.get_width(), icon_bg.get_height()
cmap = gtk.gdk.Colormap(gtk.gdk.visual_get_system(), False)

drawable = gtk.gdk.Pixmap(None, w, h, 24)
drawable.set_colormap = cmap
gc = drawable.new_gc()
drawable.draw_pixbuf(gc, icon_bg, 0, 0, 0, 0, w, h)

drawn_icon = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, False, 8, w, h)
drawn_icon.get_from_drawable(drawable, cmap, 0, 0, 0, 0, w, h)
icon = gtk.status_icon_new_from_pixbuf(drawn_icon)

This works to get the png into the icon, but falls short in two areas. First, transparency is not working. If I use a 22x22 png with transparent background and the image centered, I end up with sections of other active icons showing up inside of mine, like this:

http://i237.photobucket.com/albums/ff311/Raugturi/22x22_image_with_transparency.png

The icon it choose to steal from is somewhat random. Sometimes it's part of the dropbox icon, others the NetworkManager Applet.

If I instead use this code:

icon_bg = gtk.gdk.pixbuf_new_from_file('gmail.png')
w, h = icon_bg.get_width(), icon_bg.get_height()
cmap = gtk.gdk.Colormap(gtk.gdk.visual_get_system(), False)

drawable = gtk.gdk.Pixmap(None, w, h, 24)
drawable.set_colormap = cmap
gc = drawable.new_gc()
drawable.draw_pixbuf(gc, icon_bg, 0, 0, 0, 0, w, h)

drawn_icon = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, False, 8, 22, 22)
drawn_icon.get_from_drawable(drawable, cmap, 0, 0, 3, 6, w, h)
icon = gtk.status_icon_new_from_pixbuf(drawn_icon)

And an image that is only 16x11 with the transparent edges removed, what I end up with is this:

http://i237.photobucket.com/albums/ff311/Raugturi/16x11_image_positioned_in_middle.png

So how do I end up with a transparent block like the 1st one that doesn't pull in stuff from other icons?

As for the second problem, I need the ability to write on the image before converting it to the icon. I tried using draw_glyphs and it told me I should be using Pango layout/context instead. Unfortunately all the Pango tutorials I could find deal with actual windows, not the status icon. Is there a good tutorial out there for Pango that would apply to this issue (and also maybe have at least some explanation of how to tell it what font to use as all of them that I found seem to lack this and it won't write anything without it).

Note: Sorry for the lack of actual images and only one working link, apparently this is a spam prevention feature due to my lack of reputation.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

独闯女儿国 2024-09-12 14:28:50

我编写了这个工具(用 C 语言,但它被设计为一个单独的进程),可以与任何语言(perl、python、tcl、lua、c、c++、bash、ksh...)一起使用,只需使用任何语言启动它即可带有工具提示和左右单击命令的图标数量(仅受托盘大小限制)。然后只需根据需要更改您的图标即可。处理图标的最简单方法是通过 SVG,因为它确实很容易包含其他图像(包括 png)并使用预格式化命令快速定义文本甚至复杂(或简单)形状。

#include <sys/inotify.h>
#include <gtk/gtk.h>
#define EVENT_SIZE  ( sizeof (struct inotify_event) )
#define EVENT_BUF_LEN     ( 1024 * ( EVENT_SIZE + 16 ) )

void leftclick(GtkStatusIcon *si, gpointer s) {
    popen(s,"r"); /* exec s */
}

void rightclick(GtkStatusIcon *si, guint b,guint a_t, gpointer s) {
    popen(s,"r");
}

void refresh(gpointer si, gint fd, GdkInputCondition c) {
    char buffer[EVENT_BUF_LEN];
    read( fd, buffer, EVENT_BUF_LEN ); /* we are just clearing it & do not care what event type */
    gtk_status_icon_set_from_file(si,gtk_status_icon_get_title(si)); /* redraws */
}

int main(int argc, char *argv[]) {
    GtkStatusIcon *si; int i=1, watch, fd;
    gtk_init (&argc, &argv); /* loop through icon, tooltip, click messages */
    while (i<argc) {    fd = inotify_init(); /* get file descriptor to write on if image changes */
        si = gtk_status_icon_new_from_file(argv[i]); /* get a status icon widget */
        gtk_status_icon_set_title(si,argv[i]); /* hack to store the image path */
        watch = inotify_add_watch( fd, argv[i++], IN_CREATE | IN_MODIFY | IN_MOVED_FROM );
        gdk_input_add( fd, GDK_INPUT_READ, refresh, si ); /* inotify fd is ready for reading, refresh */
        gtk_status_icon_set_tooltip_text(si,argv[i++]);
        g_signal_connect(G_OBJECT(si), "activate", G_CALLBACK(leftclick), (gpointer) argv[i++]);
        g_signal_connect(G_OBJECT(si), "popup-menu", G_CALLBACK(rightclick), (gpointer) argv[i++]);
    }
    gtk_main();
}

I wrote this tool (in C, but it is designed to be a separate process) to work with any language (perl, python, tcl, lua, c, c++, bash, ksh,...) Just start it up with any number of icons with tooltips and right and left click commands (only limited by the size of the tray). Then just change your icon as needed. The easiest way to handle the icons is via SVG, since it is really easy to include other images (including png) and quickly define text or even complex (or simple) shapes using pre-formatted commands.

#include <sys/inotify.h>
#include <gtk/gtk.h>
#define EVENT_SIZE  ( sizeof (struct inotify_event) )
#define EVENT_BUF_LEN     ( 1024 * ( EVENT_SIZE + 16 ) )

void leftclick(GtkStatusIcon *si, gpointer s) {
    popen(s,"r"); /* exec s */
}

void rightclick(GtkStatusIcon *si, guint b,guint a_t, gpointer s) {
    popen(s,"r");
}

void refresh(gpointer si, gint fd, GdkInputCondition c) {
    char buffer[EVENT_BUF_LEN];
    read( fd, buffer, EVENT_BUF_LEN ); /* we are just clearing it & do not care what event type */
    gtk_status_icon_set_from_file(si,gtk_status_icon_get_title(si)); /* redraws */
}

int main(int argc, char *argv[]) {
    GtkStatusIcon *si; int i=1, watch, fd;
    gtk_init (&argc, &argv); /* loop through icon, tooltip, click messages */
    while (i<argc) {    fd = inotify_init(); /* get file descriptor to write on if image changes */
        si = gtk_status_icon_new_from_file(argv[i]); /* get a status icon widget */
        gtk_status_icon_set_title(si,argv[i]); /* hack to store the image path */
        watch = inotify_add_watch( fd, argv[i++], IN_CREATE | IN_MODIFY | IN_MOVED_FROM );
        gdk_input_add( fd, GDK_INPUT_READ, refresh, si ); /* inotify fd is ready for reading, refresh */
        gtk_status_icon_set_tooltip_text(si,argv[i++]);
        g_signal_connect(G_OBJECT(si), "activate", G_CALLBACK(leftclick), (gpointer) argv[i++]);
        g_signal_connect(G_OBJECT(si), "popup-menu", G_CALLBACK(rightclick), (gpointer) argv[i++]);
    }
    gtk_main();
}
你好,陌生人 2024-09-12 14:28:50

有没有理由不能只使用 gtk.StatusIcon.set_from_file?它适用于透明图像。

至于你的第二个问题,我非常怀疑是否可以在 gtk.StatusIcon 上使用 pango。
为什么需要在图标上写文字?

Is there a reason you can't just use gtk.StatusIcon.set_from_file? It works fine with transparent images.

As for your second question, I highly doubt that it is possible to use pango on a gtk.StatusIcon.
Why do you need to write text on the icon?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文