2013-06-19 7 views
10

Jestem nowy w QT i muszę zbudować aplikację ze wskaźnikiem aplikacji. Ponieważ QT wydaje się łatwiejsze niż GTK +, robię to w QT.Ikona QS Systray pojawia się obok programu uruchamiającego na Ubuntu zamiast na panelu

Wspomnę, że mam zainstalowane sni-qt, a wskaźniki aplikacji vlc i skype są normalne na panelu. Używam QT5 na 64-bitowym systemie Ubuntu 13.04.

Śledziłem ten Tutorial krok po kroku: http://qt-project.org/doc/qt-4.8/desktop-systray.html

Ale kiedy go uruchomić, oto jak wydaje się (Krzyż jest ikona używam):

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

Jak to zrobić napraw to?

+1

Która wersja Qt jest że? Czy wypróbowałeś najnowszą wersję (5.1.0-rc1)? – peppe

Odpowiedz

13

Obawiam się, że Qt5 nie jest obecnie obsługiwany przez sni-qt, więc albo musisz poczekać na nowe wydanie, które je obsługuje, albo zakodować je przy pomocy gtk + i libappindicator, używając this guide. Istnieją nawet przykłady różnych języków. Since Qt5 also distributes GLib events sprawia, że ​​integracja jest o wiele łatwiejsza. Najpierw musisz dowiedzieć się, czy używasz Unity, czy nie (aby obsługiwać więcej komputerów niż tylko jedność), możesz to zrobić, pobierając zmienną środowiskową XDG_CURRENT_DESKTOP i jeśli zwróci Unity, utworzysz appindicator, w przeciwnym razie stwórz QSystemTrayIcon.

Najpierw trzeba to wymagane nagłówki:

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

Od app-wskaźnik wykorzystuje bezpośrednio „sygnały” Nazwa musimy undefine domyślny Qt sygnały „słów kluczowych”, które zazwyczaj przekłada się publicznie. Następnie, ponieważ kodujemy C++, a libappindicator jest kodowany w C, musimy użyć zewnętrznego "C", aby nie używać mangowania nazw C++.

Następny stworzyć AppIndicator/QSystemTrayIcon na podstawie tego co pulpicie jesteśmy na:

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()));      
}                    

końcu tworzymy funkcję proxy, aby wywołać sygnał Qt od niego, aby zadeklarować funkcję musimy użyć extern „C” więc nie będzie żadnego niezdefiniowanego zachowania.

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

Teraz funkcja proxy:

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

    self->quit();                 
} 
+0

haha ​​nice one .. – Goddard

+0

Nie sądzę, że obiekty GTK + grają dobrze z pętlą zdarzeń Qt. [Ten przykład] (http://paste.ubuntu.com/7687674/) skutkuje [tymi błędami] (http://paste.ubuntu.com/7687666/). –

5

Chciałem tylko dodać, że dla każdego, kto jest przy użyciu Qt i stara się pokazać wskaźnik aplikacji w Ubuntu 13+ jak wspominają inni sni-qt nie jest pracując, mogłem użyć powyższej odpowiedzi, aby stworzyć działającą aplikację Qt, wciąż próbując zmienić ikonę i wyświetlając wyskakujące okienka, ale to świetny początek, gdy dostanę ikonę i komunikat do pracy, mogę opublikować na mojej stronie Voidrealms.com:

Pamiętaj, aby wykonać sudo apt-get install libappindicator-dev

Utwórz nowy projekt z QDialog w nim i modyfikować jak widać poniżej:

Pro file:

#------------------------------------------------- 
# 
# 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 

W 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(); 
} 
Powiązane problemy