我是 QT 新手,需要使用应用程序指示器构建应用程序。由于 QT 似乎比 GTK+ 更容易,所以我在 QT 中实现。
我会提到我已经安装了 sni-qt 并且 vlc 和 skype 的应用程序指示器在面板上显示正常。我在 Ubuntu 13.04 64 位上使用 QT5。
我一步一步按照本教程进行操作:http: //qt-project.org/doc/qt-4.8/desktop-systray.html
但是当我运行它时,它是这样显示的(十字是我正在使用的图标):

我该如何解决?
我是 QT 新手,需要使用应用程序指示器构建应用程序。由于 QT 似乎比 GTK+ 更容易,所以我在 QT 中实现。
我会提到我已经安装了 sni-qt 并且 vlc 和 skype 的应用程序指示器在面板上显示正常。我在 Ubuntu 13.04 64 位上使用 QT5。
我一步一步按照本教程进行操作:http: //qt-project.org/doc/qt-4.8/desktop-systray.html
但是当我运行它时,它是这样显示的(十字是我正在使用的图标):

我该如何解决?
恐怕目前 sni-qt 不支持 Qt5,因此您要么必须等待支持它的新版本,要么使用 gtk+ 和 libappindicator 使用本指南对其进行编码。甚至还有各种语言的示例。由于 Qt5 还分发 GLib 事件,这使得集成更加容易。首先,您需要确定您是否在 Unity 上运行(以支持更多桌面,而不仅仅是 unity),您可以通过检索 XDG_CURRENT_DESKTOP 环境变量来完成,如果它返回 Unity,则创建 appindicator,否则创建 QSystemTrayIcon。
首先,您需要包含所需的标题:
#undefine signals
extern "C" {
#include <libappindicator/app-indicator.h>
#include <gtk/gtk.h>
}
#define signals public
由于 app-indicator 直接使用“信号”名称,我们需要取消定义通常转换为公共的默认 Qt“关键字”信号。然后,由于我们正在编写 C++ 并且 libappindicator 是用 C 编写的,因此我们需要使用 extern "C" 而不是使用 C++ 名称修饰。
接下来根据我们所在的桌面创建 AppIndicator/QSystemTrayIcon:
QString desktop;
bool is_unity;
desktop = getenv("XDG_CURRENT_DESKTOP");
is_unity = (desktop.toLower() == "unity");
if (is_unity) {
AppIndicator *indicator;
GtkWidget *menu, *item;
menu = gtk_menu_new();
item = gtk_menu_item_new_with_label("Quit");
gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
g_signal_connect(item, "activate",
G_CALLBACK(quitIndicator), qApp); // We cannot connect
// gtk signal and qt slot so we need to create proxy
// function later on, we pass qApp pointer as an argument.
// This is useful when we need to call signals on "this"
//object so external function can access current object
gtk_widget_show(item);
indicator = app_indicator_new(
"unique-application-name",
"indicator-messages",
APP_INDICATOR_CATEGORY_APPLICATION_STATUS
);
app_indicator_set_status(indicator, APP_INDICATOR_STATUS_ACTIVE);
app_indicator_set_menu(indicator, GTK_MENU(menu));
} else {
QSystemTrayIcon *icon;
QMenu *m = new QMenu();
m->addAction(tr("Quit"), qApp, SLOT(quit()));
}
最后,我们创建代理函数以从中调用 Qt 信号,以声明我们需要使用 extern "C" 的函数,因此不会有任何未定义的行为。
extern "C" {
void quitIndicator(GtkMenu *, gpointer);
}
现在代理功能:
void quitIndicator(GtkMenu *menu, gpointer data) {
Q_UNUSED(menu);
QApplication *self = static_cast<QApplication *>(data);
self->quit();
}
只是想补充一点,对于任何使用 Qt 并试图在 Ubuntu 13+ 中显示应用程序指示器的人,因为其他人提到 sni-qt 不起作用,我能够使用上面的回复来制作一个可以工作的 Qt 应用程序,仍然尝试让图标更改并显示弹出消息,但这是一个很好的开始,一旦我让图标和消息正常工作,我可能会将其发布在我的网站Voidrealms.com上:
一定要做sudo apt-get install libappindicator-dev
创建一个包含 QDialog 的新项目并进行如下修改:
轮廓:
#-------------------------------------------------
#
# Project created by QtCreator 2014-03-28T20:34:54
#
#-------------------------------------------------
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = PluginServiceGUI
TEMPLATE = app
# includes for the libappindicator
# /usr/lib/x86_64-linux-gnu libglib-2.0.a
INCLUDEPATH += "/usr/include/libappindicator-0.1"
INCLUDEPATH += "/usr/include/gtk-2.0"
INCLUDEPATH += "/usr/include/glib-2.0"
INCLUDEPATH += "/usr/lib/x86_64-linux-gnu/glib-2.0/include"
INCLUDEPATH += "/usr/include/cairo"
INCLUDEPATH += "/usr/include/pango-1.0"
INCLUDEPATH += "/usr/lib/x86_64-linux-gnu/gtk-2.0/include"
INCLUDEPATH += "/usr/include/gdk-pixbuf-2.0"
INCLUDEPATH += "/usr/include/atk-1.0"
LIBS += -L/usr/lib/x86_64-linux-gnu -lgobject-2.0
LIBS += -L/usr/lib/x86_64-linux-gnu -lappindicator
LIBS += -L/usr/lib/x86_64-linux-gnu -lgtk-x11-2.0
#These seem to not be needed
#LIBS += -L/usr/lib/x86_64-linux-gnu -lcairo
#LIBS += -L/usr/lib/x86_64-linux-gnu -lpango-1.0
#LIBS += -L/usr/lib/x86_64-linux-gnu -lglib-2.0
# end incudes for libappindicator
SOURCES += main.cpp\
dialog.cpp
HEADERS += dialog.h
FORMS += dialog.ui
RESOURCES += \
resources.qrc
在 main.cpp
#include "dialog.h"
#include <QApplication>
#include <QtGui>
#include <QSystemTrayIcon>
#include <QMessageBox>
#include <QSystemTrayIcon>
#include <QMenu>
// http://stackoverflow.com/questions/17193307/qt-systray-icon-appears-next-to-launcher-on-ubuntu-instead-of-on-the-panel
// requires libappindicator-dev
// sudo apt-get install libappindicator-dev
// installs the headers in: /usr/include/libappindicator-0.1/libappindicator
#undef signals
extern "C" {
#include <libappindicator/app-indicator.h>
#include <gtk/gtk.h>
void quitIndicator(GtkMenu *, gpointer);
}
#define signals public
void quitIndicator(GtkMenu *menu, gpointer data) {
Q_UNUSED(menu);
QApplication *self = static_cast<QApplication *>(data);
self->quit();
}
void ShowUnityAppIndicator()
{
AppIndicator *indicator;
GtkWidget *menu, *item;
menu = gtk_menu_new();
item = gtk_menu_item_new_with_label("Quit");
gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
g_signal_connect(item, "activate",
G_CALLBACK(quitIndicator), qApp); // We cannot connect
// gtk signal and qt slot so we need to create proxy
// function later on, we pass qApp pointer as an argument.
// This is useful when we need to call signals on "this"
//object so external function can access current object
gtk_widget_show(item);
indicator = app_indicator_new(
"unique-application-name",
"indicator-messages",
APP_INDICATOR_CATEGORY_APPLICATION_STATUS
);
app_indicator_set_status(indicator, APP_INDICATOR_STATUS_ACTIVE);
app_indicator_set_menu(indicator, GTK_MENU(menu));
}
void ShowQtSysTray(QApplication* app, QDialog* dialog)
{
Q_INIT_RESOURCE(resources);
if (!QSystemTrayIcon::isSystemTrayAvailable()) {
QMessageBox::critical(0, QObject::tr("Systray"),
QObject::tr("I couldn't detect any system tray "
"on this system."));
}
QApplication::setQuitOnLastWindowClosed(false);
QSystemTrayIcon* trayIcon = new QSystemTrayIcon(dialog);
QAction* Action = new QAction("hello", dialog);
QMenu* trayIconMenu = new QMenu(dialog);
trayIconMenu->addAction("Quit", app, SLOT(quit()));
trayIconMenu->addAction(Action);
trayIcon->setContextMenu(trayIconMenu);
trayIcon->setIcon(QIcon (":/icons/Icons/accept.png"));
trayIcon->show();
trayIcon->showMessage("Title","Message");
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Dialog w;
//Determine the desktop type
QString desktop;
bool is_unity;
desktop = getenv("XDG_CURRENT_DESKTOP");
is_unity = (desktop.toLower() == "unity");
if(is_unity)
{
ShowUnityAppIndicator();
}
else
{
//Show the SystemTrayIcon the Qt way
ShowQtSysTray(&a, &w);
}
// w.show();
return a.exec();
}