目前使QT运行一个实例有三种方式:
1.QSharedMemory
使用共享内存,当第二个进程启动时,判断内存区数据是否建立,如有,则退出; 这种方式有弊端,在程序发生崩溃时,未及时清除共享区数据,导致程序不能正常启动.
2. QtSingleApplication
使用QT扩展库QtSingleApplication,能很好的解决这个问题. 详见: http://qt.nokia.com/products/qt-addons/solutions-archive. 里面就是用的QLocalServer/QLocalSocket建立本地socket来判断实例是否存在
3. 利用QLocalServer实现
MyApplication.h
class MyApplication:public QApplication
{
Q_OBJECT
public:
MyApplication(int argc,char **argv);
bool isRunning();
private slots:
void newLocalConnection();
private:
QLocalServer *server;
bool _isRunning;
};
MyApplication.cpp
MyApplication::MyApplication(int argc, char **argv):QApplication(argc,argv)
{
_isRunning=false;
QCoreApplication::setApplicationName("localserver");
QString serverName=QCoreApplication::applicationName();
QLocalSocket socket;
socket.connectToServer(serverName);
if(socket.waitForConnected(500))
{
QTextStream stream(&socket);
QStringList args=QCoreApplication::arguments();
if(args.count()>1)
{
stream<<args.last();
}else
{
stream<<QString();
}
stream.flush();
qDebug()<<"Connected server,program will quit";
socket.waitForBytesWritten();
/**
*qApp->quit(); 此代码是用来退出事件循环的;在构造函数中,事件循环
*尚未启动,因此就无法退出. 最好就是设置标志判断在外部判断
*/
_isRunning=true;
return;
}
qDebug()<<"Can't connect to server,build a server";
server=new QLocalServer(this);
connect(server,SIGNAL(newConnection()),this,SLOT(newLocalConnection()));
if(server->listen(serverName))
{
//防止程序崩溃时,残留进程服务,移除之
if(server->serverError()==QAbstractSocket::AddressInUseError&&QFile::exists(server->serverName()))
{
QFile::remove(server->serverName());
server->listen(serverName);
}
}
}
void MyApplication::newLocalConnection()
{
QLocalSocket *socket=server->nextPendingConnection();
if(!socket)
return;
socket->waitForReadyRead(1000);
//显示传入参数值
QTextStream in(socket);
QString vl;
in>>vl;
qDebug()<<"The value is: "<<vl;
delete socket;
}
bool MyApplication::isRunning()
{
return _isRunning;
}
主程序:
main.cpp
int main(int argc,char **argv)
{
MyApplication app(argc,argv);
if(app.isRunning())
return 0;
QLabel label;
label.setText("Hello world");
label.show();
return app.exec();
}
第一个实例: