Qt小技巧(1)
一、Qt实现睡眠函数
自己定义qSleep(int ms)
#ifdef Q_OS_WIN
#include <windows.h> // for Sleep
#endif
#ifdef Q_OS_UNIX
#include <time.h>
#endif
void qSleep(int ms)
{
#ifdef Q_OS_WIN
Sleep( uint(ms) );
#else
struct timespec ts = {
ms / 1000, (ms % 1000) * 1000 * 1000
};
nanosleep(&ts, NULL);
#endif
}
二、qDebug()输出unicode码的问题
用qDebug()的时候,无意间发现了一个问题。输出QString,如果QString里面有中文,则输出其unicode码。
看下面代码:
QString s("你好");
qDebug() << s;
//输出:"\u4F60\u597D"。输出unicode码,带双引号。
qDebug().noquote() << s;
//输出为:你好。输出了中文并且不带引号。
qDebug() << s.toStdString().c_str();
//输出为:你好。输出了中文并且不带引号。
为什么一个去掉引号就不一样了呢?我打开Qt帮助文档仔细看了一下QDebug类,愣是没看出什么来。于是在网上搜了一下QDebug,看到了官方在线帮助文档的QDebug类的说明,才明白了。
QDebug & QDebug::operator<<(const QString & s)
**Writes the string, s, to the stream and returns a reference to the stream. Normally, QDebug prints the string inside quotes and transforms non-printable characters to their Unicode values (\u1234). **
To print non-printable characters without transformation, enable the noquote() functionality. Note that some QDebug backends might not be 8-bit clean.
我就纳闷了,为什么我本地的帮助文档和Qt官方网站的在线文档竟然不一样?幸运的是,只要有网,不用*就可以看......
三、Qt实现应用程序的单例化
通过编写一个QSingleApplication类,来实现Qt程序的单例化。
两种方法:
方案一:使用Qt中的QSharedMemory,QLocalServer和QLocalSocket实现(不过需要在你的.pro里加上QT += network)
//"single_application.h"
#ifndef 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( QObject::tr("message from other instance.") );
QMessageBox::critical( 0, QObject::tr("myScreenShot"),QObject::tr("myScreenShot is already running !!") );
return 0;
}
MainWindow *mainWindow = new MainWindow();
mainWindow->show();
return app.exec();
}
总结
这些技巧在做实际项目的时候绝对会用到的,也许不在今天,就在明天。