Qt4.8單實例啓動的一種方法

原理是使用Qt的QLocalServer和QLocalSocket類創建一個虛擬服務端(因爲不是真實的socket,所以稱之爲虛擬)。

程序啓動時檢測同名服務端是否啓動,如果服務端已經啓動,則退出,否則創建一個服務端並繼續啓動。

代碼如下:

頭文件:

#include <QApplication>

class QLocalServer;

class YxsSingleApplication : public QApplication
{
    Q_OBJECT
public:
    YxsSingleApplication(int &argc, char **argv);
    ~YxsSingleApplication();

    bool isRunning();

public slots:
    void slotNewConnection();

private:
    void initConnection();
    void createServer();
    void setWindowActivated();

private:
    QWidget *m_widget;
    QLocalServer *m_server;
    QString m_server_name;
    bool m_isRunning;
};


源文件:
YxsSingleApplication::YxsSingleApplication(int &argc, char **argv) :
    QApplication(argc, argv),
    m_widget(0),
    m_server(0),
    m_server_name(""),
    m_isRunning(false)
{
    m_server_name = QFileInfo(QCoreApplication::applicationFilePath()).fileName();
    initConnection();
}


YxsSingleApplication::~YxsSingleApplication()
{

}


bool YxsSingleApplication::isRunning()
{
    return m_isRunning;
}


void YxsSingleApplication::slotNewConnection()
{
    QLocalSocket *socket = m_server->nextPendingConnection();
    if (socket)
    {
        socket->waitForReadyRead(1000);
        delete socket;

        setWindowActivated();
    }
}


void YxsSingleApplication::initConnection()
{
    QLocalSocket socket;

    // 連接以應用程序名稱爲server name的server
    // 如果連接不上則代表未啓動,此時創建一個新的server
    m_isRunning = false;
    socket.connectToServer(m_server_name);
    if (socket.waitForConnected(500))
    {
        m_isRunning = true;
        return;
    }

    createServer();
}


void YxsSingleApplication::createServer()
{
    m_server = new QLocalServer(this);
    connect(m_server, SIGNAL(newConnection()), this, SLOT(slotNewConnection()));
    if (!m_server->listen(m_server_name))
    {
        // 此時監聽失敗,可能是程序崩潰是殘留進程的服務所導致,移除
        if (QAbstractSocket::AddressInUseError == m_server->serverError())
        {
            QLocalServer::removeServer(m_server_name);
            m_server->listen(m_server_name);
        }
    }
}


void YxsSingleApplication::setWindowActivated()
{
    if (m_widget)
    {
        m_widget->show();
        m_widget->raise();
        m_widget->activateWindow();
    }
}

使用方式:

int main(int argc, char *argv[])
{
    YxsSingleApplication app(argc, argv);

    if (!app.isRunning())
    {
        YxsMainWindow win;

        win.show();

        return app.exec();
    }

    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章