Qt浅談の四十三Linuxの下でシステムトレイが再稼働して実行された例がある

3493 ワード

一、紹介
centosでプログラムを実行し、システムトレイに最小化すると、ユーザーはプログラムがまだ開いていることを忘れてしまう可能性があります.また、プログラムを開こうとします.単一インスタンスではエラーが表示され、単一インスタンスではない場合は新しいプログラムが起動します(複数のプログラムを実行したくない).実行中でシステムトレイに最小化されたプログラムを直接ポップアップするにはどうすればいいですか.解決策:システムトレイ(QSystemTrayIcon)のプログラムにQSharedMemoryを付けて単一インスタンスかどうかを判断し(QtSingleApplicationの方がよい)、signal信号処理(SIGHUP信号受信)を加える.トレイは常に1つのみ
二、詳しく
1、部分コード(1)widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QtGui>
#include<signal.h>
#include "systemtray.h"

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = 0);
    ~Widget();

protected:
    void closeEvent(QCloseEvent *event);

private:
    static void showHandle(int sig);

private:
    SystemTray *systemTray;
    static Widget *instance;
};

#endif // WIDGET_H

(2)widget.cpp
#include "widget.h"

Widget *Widget::instance = NULL;
Widget::Widget(QWidget *parent)
    : QWidget(parent, Qt::WindowMinimizeButtonHint | Qt::WindowCloseButtonHint | Qt::WindowStaysOnTopHint)
{
    setWindowTitle(tr("    "));
    resize(400, 400);
    move((QApplication::desktop()->width() - width())/2,  (QApplication::desktop()->height() - height())/2);

    systemTray = new SystemTray(this);
    systemTray->setMiddleClickText(tr("    "));
    systemTray->setToolTips(tr("        "));
    systemTray->setHideText(tr("           "));
    systemTray->show();

    instance = this;
    signal(SIGHUP, showHandle);
}

Widget::~Widget()
{
    instance = NULL;
}

void Widget::closeEvent(QCloseEvent *event)
{
    if (systemTray->isVisible()) {
        systemTray->startHideTips();
        hide();
        event->ignore();
    }
}

void Widget::showHandle(int sig)
{
    if (instance) {
        instance->showNormal();
    }
//    if (instance && !instance->isVisible()) {
//        instance->show();
//    }
}

(3)main.cpp
#include "widget.h"
#include <QApplication>
#include <QSharedMemory>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QTextCodec *codec = QTextCodec::codecForName("utf8");
    QTextCodec::setCodecForLocale(codec);
    QTextCodec::setCodecForCStrings(codec);
    QTextCodec::setCodecForTr(codec);
    if (!QSystemTrayIcon::isSystemTrayAvailable()) {
        QMessageBox::critical(NULL, QObject::tr("    "), QObject::tr("       "));
        return 1;
    }
    QSharedMemory mem("system_tray");
    if (!mem.create(1)) {
        QString appName =  QApplication::applicationFilePath().section('/', -1);
        QProcess::startDetached(QString("killall -HUP %1").arg(appName));
        return 1;
    }
    Widget w;
    w.show();
    return a.exec();
//    QSharedMemory shared_memory;
//    shared_memory.setKey("systemtray");
//    if(shared_memory.attach()) {
//        return 0;
//    }
//    if(shared_memory.create(1)) {
//        Widget w;
//        w.show();
//        return a.exec();
//    }
}

三、まとめ
(1)上記コードがCSDNにアップロードされました.http://download.csdn.net/detail/taiyang1987912/9436271. (2)プログラム中のQSharedMemoryには大きなリスクがあり、異常中断のたびに共有メモリが削除できない.テストではQSharedMemory mem(「system_tray」)の名前を変更(または手動で共有メモリを削除)することができ、実際のプロジェクトではQtSingleApplicationを使用することが望ましい.(3)signalの他にQDBusを用いてdbus信号を接続されたスロット関数に送信することもできるが,QDBusは相対的に面倒である.(4)質問やアドバイスがあれば、コメントをお願いします.ここで感謝します.