QT中实现应用程序的单例化

2023-11-14

一介绍

通过编写一个QSingleApplication类,来实现Qt程序的单例化,原文的作者是在Windows Vista + Qt4.4 下实现的,不过应用在其他平台上是没问题的。(本文是我http://www.qtcentre.org/wiki/index.php?title=SingleApplication上看到的)

 

二代码

方案一:使用Qt中的QSharedMemory,QLocalServer和QLocalSocket实现(不过需要在你的.pro里加上QT += network)

别的没翻译,就是大概说了一下,直接来代码吧:

// "single_application.h"

#ifndef SINGLE_APPLICATION_H
#define SINGLE_APPLICATION_H

#include <QApplication>
#include <QSharedMemory>
#include <QLocalServer>

class SingleApplication : public QApplication

{
	Q_OBJECT
public:

	SingleApplication(int &argc, char *argv[], const QString uniqueKey);
	bool isRunning();
	bool sendMessage(const QString &message);
public slots:
	void receiveMessage();
signals:
	void messageAvailable(QString message);
private:
	bool _isRunning;
	QString _uniqueKey;
	QSharedMemory sharedMemory;
	QLocalServer *localServer;
	static const int timeout = 1000;
};

#endif // SINGLE_APPLICATION_H

// "single_application.cpp"
#include <QLocalSocket>
#include "single_application.h"

SingleApplication::SingleApplication(int &argc, char *argv[], const QString uniqueKey) : QApplication(argc, argv), _uniqueKey(uniqueKey)

{
	sharedMemory.setKey(_uniqueKey);
	if (sharedMemory.attach())
		_isRunning = true;
	else
	{
		_isRunning = false;
		// create shared memory.
		if (!sharedMemory.create(1))
		{
			qDebug("Unable to create single instance.");
			return;
		}

		// create local server and listen to incomming messages from other instances.
		localServer = new QLocalServer(this);
		connect(localServer, SIGNAL(newConnection()), this, SLOT(receiveMessage()));
		localServer->listen(_uniqueKey);
	}
}

// public slots.
void SingleApplication::receiveMessage()
{
	QLocalSocket *localSocket = localServer->nextPendingConnection();
	if (!localSocket->waitForReadyRead(timeout))
	{
		qDebug(localSocket->errorString().toLatin1());
		return;
	}

	QByteArray byteArray = localSocket->readAll();
	QString message = QString::fromUtf8(byteArray.constData());
	emit messageAvailable(message);
	localSocket->disconnectFromServer();
}

// public functions.
bool SingleApplication::isRunning()
{
	return _isRunning;
}

bool SingleApplication::sendMessage(const QString &message)
{
	if (!_isRunning)
		return false;
	QLocalSocket localSocket(this);
	localSocket.connectToServer(_uniqueKey, QIODevice::WriteOnly);
	if (!localSocket.waitForConnected(timeout))
	{
		qDebug(localSocket.errorString().toLatin1());
		return false;
	}

	localSocket.write(message.toUtf8());
	if (!localSocket.waitForBytesWritten(timeout))
	{
		qDebug(localSocket.errorString().toLatin1());
		return false;
	}

	localSocket.disconnectFromServer();
	return true;

方案二:使用Qt中的QSharedMemory,和QTimert实现,别的也没翻译,还是直接来代码吧:

// "single_application.h"
#ifndef SINGLE_APPLICATION_H
#define SINGLE_APPLICATION_H

#include <QApplication>
#include <QSharedMemory>

class SingleApplication : public QApplication
{
	Q_OBJECT
public:
	SingleApplication(int &argc, char *argv[], const QString uniqueKey);
	bool isRunning();
	bool sendMessage(const QString &message);
public slots:
	void checkForMessage();
signals:
	void messageAvailable(QString message);
private:
	bool _isRunning;
	QSharedMemory sharedMemory;
};

#endif // SINGLE_APPLICATION_H

// "single_application.cpp"
#include <QTimer>
#include <QByteArray>
#include "single_application.h"

SingleApplication::SingleApplication(int &argc, char *argv[], const QString uniqueKey) : QApplication(argc, argv)
{
	sharedMemory.setKey(uniqueKey);
	if (sharedMemory.attach())
		_isRunning = true;
	else
	{
		_isRunning = false;
		// attach data to shared memory.
		QByteArray byteArray("0"); // default value to note that no message is available.
		if (!sharedMemory.create(byteArray.size()))
		{
			qDebug("Unable to create single instance.");
			return;
		}
		sharedMemory.lock();
		char *to = (char*)sharedMemory.data();
		const char *from = byteArray.data();
		memcpy(to, from, qMin(sharedMemory.size(), byteArray.size()));
		sharedMemory.unlock();

                // start checking for messages of other instances.
		QTimer *timer = new QTimer(this);
		connect(timer, SIGNAL(timeout()), this, SLOT(checkForMessage()));
		timer->start(1000);
	}
}

// public slots.
void SingleApplication::checkForMessage()
{
	sharedMemory.lock();
	QByteArray byteArray = QByteArray((char*)sharedMemory.constData(), sharedMemory.size());
	sharedMemory.unlock();
	if (byteArray.left(1) == "0")
		return;
	byteArray.remove(0, 1);
	QString message = QString::fromUtf8(byteArray.constData());
	emit messageAvailable(message);

        // remove message from shared memory.
	byteArray = "0";
	sharedMemory.lock();
	char *to = (char*)sharedMemory.data();
	const char *from = byteArray.data();
	memcpy(to, from, qMin(sharedMemory.size(), byteArray.size()));
	sharedMemory.unlock();
}

// public functions.
bool SingleApplication::isRunning()
{
	return _isRunning;
}

bool SingleApplication::sendMessage(const QString &message)
{
	if (!_isRunning)
		return false;

	QByteArray byteArray("1");
	byteArray.append(message.toUtf8());
	byteArray.append('/0'); // < should be as char here, not a string!
	sharedMemory.lock();
	char *to = (char*)sharedMemory.data();
	const char *from = byteArray.data();
	memcpy(to, from, qMin(sharedMemory.size(), byteArray.size()));
	sharedMemory.unlock();
	return true;
}

三使用

// "main.cpp"
#include "single_application.h"
int main(int argc, char *argv[])
{
	SingleApplication app(argc, argv, "some unique key string");
	if (app.isRunning())
	{
		app.sendMessage("message from other instance.");
		return 0;
	}

	MainWindow *mainWindow = new MainWindow();

        // connect message queue to the main window.
	QObject::connect(&app, SIGNAL(messageAvailable(QString)), mainWindow, SLOT(receiveMessage(QString)));

        // show mainwindow.
	mainWindow->show();
	return app.exec();

}
我想代码都应该能看得懂吧,这个挺不错的~
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

QT中实现应用程序的单例化 的相关文章

随机推荐

  • 上海国际区块链赋能传统产业峰会-王伟:道道人才链启动

    上海国际区块链赋能传统产业峰会 王伟 道道人才链启动 新闻中国采编网 中国新闻采编网 谋定研究中国智库网 经信研究 国研智库 国情讲坛 万赢信采编 在当前 区块链成为全球技术发展的前沿阵地 谋定研究 对话中国经济和信息化 区块链将加速 可信
  • QPixmap的尺寸设置

    问题描述 在控件上使用QPixmap时 希望能重新修改图片的分辨率 而不是使用图片的原始分辨率 解决方法 主要有两种方法 设置控件的尺寸 例如QPixmap被传入一个QLabel控件时 可以通过设置QLabel控件的尺寸来对QPixmap进
  • C++11 noexcept 关键字用法学习

    最近学习和写了一个 mint 的板子 其中用到了 noexcept 关键字 对这个关键字不太熟悉 便学习一下刘毅学长的文章 C 98 中的异常规范 Exception Specification 傲芙小说网 https www 3973 i
  • kaggle冠军代码汇总

    https www cnblogs com rw rongwei p 6509146 html
  • linux 查看进程和内存使用情况,深入理解linux下查看进程内存的使用情况

    本篇文章是对linux下查看进程内存的使用情况进行了详细的分析介绍 需要的朋友参考下 动态查看一个进程的内存使用 复制代码 代码如下 1 top命令 top d 1 p pid pid 设置为delay 1s 默认是delay 3s 如果想
  • 为什么C++内置类型的局部变量不能默认初始化

    C 有个人所共知的特性 就是它的内置类型是无法在局部区域内默认初始化的 如下所示 int k int main int m cout lt
  • 对象中BigDecimal值转换为JSON中精度丢失(出错)的问题解决方法

    代码如下 1 定义一个包含BigDecimal类型的类 Data public class User private String name private BigDecimal salary 2 分别使用两种方法将对象转换为字符串 pub
  • Linux安装python3

    一 卸载python命令 rpm qa grep python xargs rpm ev allmatches nodeps 强制删除已安装程序及其关联 whereis python xargs rm frv 删除所有残余文件 xargs
  • Opencv寻找轮廓的最小外接矩形,并获取矩形的中心点,旋转角度

    本代码可用于获取物体的坐标偏移量 旋转角度 if thresholdValue Mat src Mat imHeight imWidth CV 8U pImageBuffer Mat mat src copyTo mat threshold
  • springboot 普通类自动注入mapper

    提示 文章写完后 目录可以自动生成 如何生成可参考右边的帮助文档 文章目录 解决方法 解决方法 普通类使用 Component注解修饰 添加本类型静态属性 所需mapper属性 添加init方法 用 PostConstruct注解修饰 方法
  • vue +element实现图片上传加展示

    一 声明变量 我们在这里声明了两个qrcodeaddress 分别是绑定表单的字段和作为展示图片的字段 二 编写html部分 在这里img标签是我们上传之后 展示的地方 action是上传路径 on success是上传成功后的方法 三编写
  • Vue之路由

    Vue之路由 今天来看看vue怎么实现路由功能 我们在vue cil脚手架搭建好的基础上来实现路由功能 如果搭建完初始化项目时没有路由功能则需在npm安装路由 命令 npm install vue router 然后在main js中引用路
  • 【Python】os.path.exists()的含义 及文件存在但os.path.exists()返回False的原因

    os path exists 函数的功能是查看给定的文件 目录是否存在 存在返回True 不存在返回False 如果给定的文件只有文件名 会在当前文件的目录下索引 给定的文件 目录可以是绝对索引 文件存在但os path exists 返回
  • Nacos 注册中心的设计原理:让你的应用轻松实现高效注册与发现!

    当应用开始脱离单机运行和访问时 服务发现就诞生了 目前的网络架构是每个主机都有 个独立的 IP 地址 服务发现基本都是通过某种方式获取到服务所部署的 IP 地址 DNS 协议是最早将 个网络名称翻译为网络 IP 的协议 在最初的架构选型中
  • cenos自动启动tomcat

    首先创建一个脚本 关闭tomcat 等待2分钟 启动tomcat 并且把日志输出在 usr local tomcat tomcatchognqi log bin bash export JAVA HOME usr local jdk jdk
  • 创建Unity项目

    1 点击 新项目 2 根据实际所需选择对应模板 3 等待创建项目完成 4 点击项目即会在新窗口打开项目
  • 如何自动更新-CMD

    不打算讲得很细 我本人能看懂就行 现在客户端自动更新 一般要用到更新程序 这样就是两个项目 两个exe了 所以对我这来说比较反感 所以就选择了另外一种方法 cmd 由于是自动更新客户端 且是内置的 所以要关闭自身 但是cmd在process
  • VScode远程服务器docker环境

    经常会遇到需要对docker容器中的代码调试的问题 远程使用IDE是很好的选择 具体操作 1 在VScode中下载Remote SSH 2 创建一个ssh连接服务器 3 启动一个docker并注明服务器端口与docker端口的映射关系 Ti
  • 使用 RestSharp访问接口返回 空 数据原因(ssl加密)解决方法

    例子 var client new RestClient https wwwcie ups com rest Track var request new RestRequest Method POST request AddHeader p
  • QT中实现应用程序的单例化

    一介绍 通过编写一个QSingleApplication类 来实现Qt程序的单例化 原文的作者是在Windows Vista Qt4 4 下实现的 不过应用在其他平台上是没问题的 本文是我在http www qtcentre org wik