2013-06-19 60 views
10

我是QT新手,需要使用應用程序指示器來構建應用程序。由於QT似乎比GTK +更容易,我正在QT中製作。QT Systray圖標出現在Ubuntu的啓動器旁邊,而不是面板

我會提到,我已經安裝了sni-qt,並且vlc和skype的應用程序指標在面板上顯示爲正常。我在Ubuntu 13.04 64位上使用QT5。

我也跟着一步本教程一步:http://qt-project.org/doc/qt-4.8/desktop-systray.html

但是當我運行它,這裏是它如何出現(十字架是我使用的圖標):

http://i.stack.imgur.com/4bT33.png

我如何解決這個問題?

+1

其中的Qt版本那?你有沒有試過最新版本(5.1.0-rc1)? – peppe

回答

13

恐怕Qt5目前不支持sni-qt,因此您必須等待新版本支持它,或者使用this guide使用gtk +和libappindicator進行編碼。甚至有各種語言的例子。 Since Qt5 also distributes GLib events,使集成更容易。首先,您需要確定您是否在Unity上運行(以支持更多臺式機,而不僅僅是統一),您可以通過檢索XDG_CURRENT_DESKTOP環境變量以及是否返回Unity來創建appindicator,否則創建QSystemTrayIcon。

首先,你需要有必要標題:

#undefine signals             
extern "C" {                 
    #include <libappindicator/app-indicator.h>         
    #include <gtk/gtk.h>              
}                    
#define signals public              

由於APP-指標直接使用「信號」的名字,我們需要取消定義默認的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的信號,宣佈我們需要使用外部的「C」功能所以不會有任何未定義的行爲。

extern "C" {                  
    void quitIndicator(GtkMenu *, gpointer);            
}                    

現在代理功能:

void quitIndicator(GtkMenu *menu, gpointer data) {          
    Q_UNUSED(menu);                
    QApplication *self = static_cast<QApplication *>(data);      

    self->quit();                 
} 
+0

哈哈不錯.. – Goddard

+0

我不認爲GTK +對象在Qt的事件循環中表現不錯。 [This sample](http://paste.ubuntu.com/7687674/)導致[這些錯誤](http://paste.ubuntu.com/7687666/)。 –

5

只想添加,對於使用Qt和試圖顯示在Ubuntu 13+一個應用程序指示任何人如其他人所說的SNI-QT是不是工作,我能夠使用上面的答覆,使一個Qt應用程序的工作,仍然試圖讓圖標改變並顯示彈出消息,但這是一個很好的開始,一旦我得到的圖標和消息工作,我可能會發布它出我的網站Voidrealms.com

一定要做sudo apt-get install libappindicator-dev

在它建立一個新的項目,一個QDialog的和修改,如下圖所示:

Pro的文件:

#------------------------------------------------- 
# 
# 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(); 
} 
相關問題