Qt使用和常用代码
https://blog.csdn.net/u014678728/article/details/101155667
Qt基础和库
QObject
//删除
obj->deleteLater()或 delete obj
deleteLater会等这次事件循环结束再释放内存 必须在运行事件循环的线程中调用
//类型转化
QObject *obj = new QTimer; // QTimer inherits QObject
QTimer *timer = qobject_cast<QTimer *>(obj);
// timer == (QObject *)obj
QAbstractButton *button = qobject_cast<QAbstractButton *>(obj);
// button == 0
要转化的类必须继承QObject和声明Q_OBJECT宏
//查找子类
QList<QWidget *> widgets = parentWidget.findChildren<QWidget *>("widgetname");
QList<QPushButton *> allPButtons = parentWidget.findChildren<QPushButton *>();
QList<QPushButton *> childButtons = parentWidget.findChildren<QPushButton *>(QString(), Qt::FindDirectChildrenOnly);
//事件过滤
class KeyPressEater : public QObject
{
Q_OBJECT
...
protected:
bool eventFilter(QObject *obj, QEvent *event) override;
};
bool KeyPressEater::eventFilter(QObject *obj, QEvent *event)
{
if (event->type() == QEvent::KeyPress) {
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
qDebug("Ate key press %d", keyEvent->key());
return true;
} else {
// standard event processing
return QObject::eventFilter(obj, event);
}
}
And here's how to install it on two widgets:
KeyPressEater *keyPressEater = new KeyPressEater(this);
QPushButton *pushButton = new QPushButton(this);
QListView *listView = new QListView(this);
pushButton->installEventFilter(keyPressEater);
listView->installEventFilter(keyPressEater);
//注册函数到原对象系统
Q_INVOKABLE void invokableMethod();
使用QMetaObject::invokeMethod(obj, "invokableMethod");
//原对象系统
跨线程连接信号和槽 参数不是qt基本类
使用
int id = qRegisterMetaType<MyStruct>();
所有要使用信号和槽的类 必须继承QObject和声明Q_OBJECT宏
//属性
Q_PROPERTY(type name
(READ getFunction [WRITE setFunction] |
MEMBER memberName [(READ getFunction | WRITE setFunction)])
[RESET resetFunction]
[NOTIFY notifySignal]
[REVISION int]
[DESIGNABLE bool]
[SCRIPTABLE bool]
[STORED bool]
[USER bool]
[CONSTANT]
[FINAL])
Q_PROPERTY(QString title READ title WRITE setTitle USER true)
//信号
signals:
void signal_1();
emit signal_1 发射信号
//槽
public slots:
void slot_1();
connect(obj, SIGNAL(signal_1), obj2, SLOT(slot_1));
c++11
connect(sender, &Sender::valueChanged, reciver, &Reciver::showValue)
lambad
connect(sender, &Sender::valueChanged, [](){
});
支持编译时检查, 支持相容类型自动转化, 可以连接任何函数不用声明 slot
如果信号和槽有重载:
connect(sender, static_cast<void(QSpinBox::*) (int)> (&QSpinBox::valueChanged)) ,
this, &MainWindow::onSpinBoxChanged);
qt基本容器
QList<T>
QLinkedList<T>
QVector<T>
QStack<T>
QQueue<T>
QSet<T>
QMap<Key, T>
QMultiMap<Key, T>
QHash<Key, T>
QMultiHash<Key, T>
//JAVA风格遍历
QList<QString> list;
list << "A" << "B" << "C" << "D";
QListIterator<QString> i(list);
while (i.hasNext())
qDebug() << i.next();
QListIterator<QString> i(list);
i.toBack();
while (i.hasPrevious())
qDebug() << i.previous();
//迭代器中 插入删除使用 QMutableMapIterator
QMap<QString, QString> map;
map.insert("Paris", "France");
map.insert("Guatemala City", "Guatemala");
map.insert("Mexico City", "Mexico");
map.insert("Moscow", "Russia");
...
QMutableMapIterator<QString, QString> i(map);
while (i.hasNext()) {
if (i.next().key().endsWith("City"))
i.remove();
}
//STL风格遍历
QList<QString> list;
list << "A" << "B" << "C" << "D";
QList<QString>::iterator i;
for (i = list.begin(); i != list.end(); ++i)
*i = (*i).toLower();
//反向迭代
QList<QString> list;
list << "A" << "B" << "C" << "D";
QList<QString>::reverse_iterator i;
for (i = list.rbegin(); i != list.rend(); ++i)
*i = i->toLower();
}
//只读
QList<QString>::const_iterator i;
for (i = list.constBegin(); i != list.constEnd(); ++i)
qDebug() << *i;
//foreach迭代---注意不要在迭代器里删除元素
QLinkedList<QString> list;
...
foreach (const QString &str, list) {
if (str.isEmpty())
break;
qDebug() << str;
}
数据库
QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL", "Project"); //数据库类型,别名
db.setDatabaseName("mysql"); db.setHostName("127.0.0.1");
db.setUserName("root");
db.setPassword("");
db.open();
//执行sql语句
query = QSqlQuery(QSqlDatabase::database("Project"));
query.exec("create table if not exists time_table (`time` text NOT NULL, `info` text)");
//查询表
query.exec(QString("select * from time_table"));
while (query.next()) {
QString info = query.value("info").toString();
foreach (QString timeInfo, allTimeInfoList) {
if(info.contains(timeInfo)) {
QStringList &list= m_timeSendList[QTime::fromString(query.value("time").toString(), "hh::mm::ss")];
if(!list.contains(info)) {
list.append(info);
}
break;
}
}
}
//tableview
model = new QSqlQueryModel(this);
ui->tableView->setModel(model);
model->setQuery(QString("SELECT *from %3 where time >= '%1' and time <= '%2'").
arg(ui->dateTimeEdit->dateTime().toString("yyyy-MM-dd hh:mm:ss")).arg(ui->dateTimeEdit_2->dateTime().toString("yyyy-MM-dd hh:mm:ss")).arg(m_table), QSqlDatabase::database("Project"));
//设置显示头
if(model->columnCount() >= 4) {
model->setHeaderData(0, Qt::Horizontal, tr("系统"));
model->setHeaderData(1, Qt::Horizontal, tr("描述"));
model->setHeaderData(2, Qt::Horizontal, tr("时间"));
model->setHeaderData(3, Qt::Horizontal, tr("操作者"));
} else {
model->setHeaderData(0, Qt::Horizontal, tr("描述"));
model->setHeaderData(1, Qt::Horizontal, tr("时间"));
model->setHeaderData(2, Qt::Horizontal, tr("操作者"));
}
HTTP
QNetworkAccessManager *manager = new QNetworkAccessManager(this);
connect(manager, &QNetworkAccessManager::finished,
this, &MyClass::replyFinished);
manager->get(QNetworkRequest(QUrl("http://qt-project.org")));
QNetworkRequest request;
request.setUrl(QUrl("http://qt-project.org"));
request.setRawHeader("User-Agent", "MyOwnBrowser 1.0");
QNetworkReply *reply = manager->get(request);
connect(reply, &QIODevice::readyRead, this, &MyClass::slotReadyRead);
connect(reply, QOverload<QNetworkReply::NetworkError>::of(&QNetworkReply::error),
this, &MyClass::slotError);
connect(reply, &QNetworkReply::sslErrors,
this, &MyClass::slotSslErrors);
//使用
accessManager = new new QNetworkAccessManager();
//POST
void Common::post(const QString &url, const QString &data)
{
QNetworkRequest request;
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
//request.setHeader(QNetworkRequest::ContentLengthHeader, data.size());
//request.setHeader(QNetworkRequest::ContentLengthHeader, data.size());
request.setUrl(QUrl(url));
QByteArray postData;
postData.append(data);
QNetworkReply* reply = accessManager->post(request, postData);
connect(reply, &QNetworkReply::finished, [this, reply, url]{
emit getmessage(reply->readAll());
reply->deleteLater();
});
}
void Common::get(const QString &url)
{
QNetworkRequest request;
request.setUrl(QUrl(url));
QNetworkReply* reply = accessManager->get(request);
connect(reply, &QNetworkReply::finished, [this, reply, url]{
QByteArray alldata = reply->readAll();
emit getmessage(alldata);
reply->deleteLater();
});
}
//JOSN
QMap<QString, QVariant> GFun::jsonParse(const QByteArray &jsonData)
{
QJsonParseError jsonError;
QJsonDocument doucment = QJsonDocument::fromJson(jsonData, &jsonError); // 转化为 JSON 文档
if (!doucment.isNull() && (jsonError.error == QJsonParseError::NoError)) { // 解析未发生错误
if (doucment.isObject()) { // JSON 文档为对象
QJsonObject object = doucment.object(); // 转化为对象
return object.toVariantMap();
}
}
QMap<QString, QVariant> data;
return data;
}
TCP/UDP
UDP
void Server::initSocket()
{
udpSocket = new QUdpSocket(this);
udpSocket->bind(QHostAddress::LocalHost, 7755);
connect(udpSocket, SIGNAL(readyRead()),
this, SLOT(readPendingDatagrams()));
}
void Server::readPendingDatagrams()
{
while (udpSocket->hasPendingDatagrams()) {
QNetworkDatagram datagram = udpSocket->receiveDatagram();
processTheDatagram(datagram);
}
}
192.168.1.255广播地址
//服务端
tcpServer = new QTcpServer(this);
if (!tcpServer->listen(QHostAddress::Any, 1883)) {
close();
return;
}
connect(tcpServer, &QTcpServer::newConnection, this, &Server::sendFortune);
connect(tcpServer, &QTcpServer::acceptError, this, [](QAbstractSocket::SocketError socketError){
});
void Server::sendFortune()
{
QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_5_10);
out << fortunes[QRandomGenerator::global()->bounded(fortunes.size())];
QTcpSocket *clientConnection = tcpServer->nextPendingConnection();
connect(clientConnection, &QAbstractSocket::disconnected,
clientConnection, &QObject::deleteLater);
clientConnection->write(block);
clientConnection->disconnectFromHost();
}
//客户端
//初始化TCP客户端
tcpClient = new QTcpSocket(this); //实例化tcpClient
tcpClient->abort(); //取消原有连接
connect(tcpClient, &QTcpSocket::readyRead, this, [tcpClient]{
tcpClient->readAll();
});
connect(tcpClient, &QTcpSocket::connected, this, [tcpClient]{
qDebug()<"连接成功";
});
connect(tcpClient, &QTcpSocket::disconnected, this, [tcpClient]{
qDebug()<"断开连接";
});
connect(tcpClient, SIGNAL(error(QAbstractSocket::SocketError)), \
this, SLOT(ReadError(QAbstractSocket::SocketError)));
Signals
void connected()
void disconnected()
void error(QAbstractSocket::SocketError socketError)
void hostFound()
void proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *authenticator)
void stateChanged(QAbstractSocket::SocketState socketState)
disconnectFromHost 断开连接,等待缓冲区写入完成
abort 直接断开,不等待
进程和线程
开启新的进程
C++
system();
Qt
//!!! Qt5
QString program = "C:/Windows/System32/cmd.exe";
QStringList arguments;
arguments << "/c" << "dir" << "C:\\";
QProcess *cmdProcess = new QProcess; cmdProcess->start(program, arguments);
QObject::connect(cmdProcess, &QProcess::readyRead, [=] () {
QTextCodec *codec = QTextCodec::codecForName("GBK");
QString dir = codec->toUnicode(cmdProcess->readAll());
//线程 moveToThread
class Worker : public QObject
{
Q_OBJECT
public slots:
void doWork(const QString ¶meter) {
QString result;
/* ... here is the expensive or blocking operation ... */
emit resultReady(result);
}
signals:
void resultReady(const QString &result);
};
class Controller : public QObject
{
Q_OBJECT
QThread workerThread;
public:
Controller() {
Worker *worker = new Worker;
worker->moveToThread(&workerThread);
connect(&workerThread, &QThread::finished, worker, &QObject::deleteLater);
connect(this, &Controller::operate, worker, &Worker::doWork);
connect(worker, &Worker::resultReady, this, &Controller::handleResults);
workerThread.start();
}
~Controller() {
workerThread.quit();
workerThread.wait();
}
public slots:
void handleResults(const QString &);
signals:
void operate(const QString &);
};
//线程 RUN
class WorkerThread : public QThread
{
Q_OBJECT
void run() override {
QString result;
/* ... here is the expensive or blocking operation ... */
emit resultReady(result);
}
signals:
void resultReady(const QString &s);
};
void MyObject::startWorkInAThread()
{
WorkerThread *workerThread = new WorkerThread(this);
connect(workerThread, &WorkerThread::resultReady, this, &MyObject::handleResults);
connect(workerThread, &WorkerThread::finished, workerThread, &QObject::deleteLater);
workerThread->start();
}
QThread::idealThreadCount() //获取CPU数量
//互斥锁
QMutex mutex;
int number = 6;
void method1()
{
mutex.lock();
number *= 5;
number /= 4;
mutex.unlock();
}
void method2()
{
mutex.lock();
number *= 3;
number /= 2;
mutex.unlock();
}
//QMutexLocker 析构自动释放锁
int complexFunction(int flag)
{
QMutexLocker locker(&mutex);
return 1;
}
//读写锁
QReadWriteLock lock;
void ReaderThread::run()
{
...
lock.lockForRead();
read_file();
lock.unlock();
...
}
void WriterThread::run()
{
...
lock.lockForWrite();
write_file();
lock.unlock();
...
}
//信号量
QSemaphore sem(5); // sem.available() == 5
sem.acquire(3); // sem.available() == 2
sem.acquire(2); // sem.available() == 0
sem.release(5); // sem.available() == 5
sem.release(5); // sem.available() == 10
sem.tryAcquire(1); // sem.available() == 9, returns true
sem.tryAcquire(250); // sem.available() == 9, returns false
//条件变量
forever {
mutex.lock();
keyPressed.wait(&mutex);
do_something();
mutex.unlock();
}
forever {
getchar();
keyPressed.wakeAll();
}
QAtomicInt
QAtomicPointer
资源文件
资源文件以 .qrc结尾
在c++中使用资源文件 路径 :/image/a.png
qml使用资源文件 qrc:/Button.qml
.pro中执行qmake编译资源文件
system($$[QT_INSTALL_BINS]/rcc.exe -binary $$PWD/res.qrc -o $$PWD/myresource.rcc)
再main中QResource::registerResource("./myresource.rcc");
c++11
c++11支持, 在.pro中增加 CONFIG += c++11
constexpr 用于向编译器指出, 函数或变量在编译时运算。 QT5中使用 Q_DECL_CONSTEXPR
static_assert 静态断言, 编译时检测一些条件是否成立 Q_STATIC_ASSERT
override 修饰函数, 函数必须覆盖父类的函数, Q_DECL_OVERRIDE
void MyWidget::mouseMoveEvent() Q_DECL_OVERRIDE
final 打断virtual的传播 如果一个虚函数被final修饰所有的子类都不能覆盖该函数, Q_DECL_FINAL
delete 显示禁止c++编译器生成代码, 被修饰的函数不能被调用。 Q_DECL_DELETE
Lambad
Lambda 表达式: Lambda表达式就是匿名函数,。
[capture](parameter)mutable -> return-type{state}
capture 是捕捉列表。
parameter 是参数列表,就是函数的那些传入变量。
mutable 这个后面再介绍。
return-type 返回值的类型,如果返回值明确,也可以省略。
state 是函数体
connect(sender, &StringDialog::stringChanged, [=](QString str)) {
if(str == "qt") {
} else {}
});
Lambad 表达式引入符:
[] 不捕获任何局部变量
[=] 以传值的方式捕获外部变量
[&] 以引用的方式捕获外部变量
[x, &y] x传值捕获, y引用捕获
[=, &x] x引用捕获, 其他传值捕获
[&, x] x传值捕获, 其它引用捕获
[a, &str]->QString{} 传值捕获a, 引用捕获str, 返回值是QString。
带默认参数的槽函数:
connect(sender, &sender::signal, [](){ pushButton->anumateClick });
QWidget
setAttribute(Qt::WA_DeleteOnClose); //关闭窗口自动销毁
setWindowFlags(Qt::Dialog);
setWindowFlags(windowFlags() ^ Qt::WindowContextHelpButtonHint);
setWindowModality(Qt::WindowModal); //模态对话框
//设置窗体透明但是其中的部件不透明
setWindowFlags(Qt::FramelessWindowHint);
setAttribute(Qt::WA_TranslucentBackground, true);
智能指针
QPointer
QSharedPointer
QWeakPointer
QScopedPointer
QScopedArryPointer
QExplicitlyShareDataPointer
std::auto_ptr
std::shared_ptr
std::weak_ptr
std::unique_ptr
//QPointer 弱类型指针 允许外部删除对象
QPointer<QLabel> label = new QLabel;
label->setText("&Status:");
...
if (label)
label->show();
QLabel被删除 label值自动为NULL
//QSharedPointer 强引用指针,采用引用计数,当引用计数为0时调用 delete回调函数
static void doDeleteLater(MyObject *obj)
{
obj->deleteLater();
}
void otherFunction()
{
QSharedPointer<MyObject> obj =
QSharedPointer<MyObject>(new MyObject, doDeleteLater);
// continue using obj
obj.clear(); // calls obj->deleteLater();
}
QSharedPointer<MyObject> obj =
QSharedPointer<MyObject>(new MyObject, &QObject::deleteLater);
//QWeakPointer 弱类型指针 允许外部删除对象
QWeakPointer<int> weakref;
// ...
QSharedPointer<int> strong = weakref.toStrongRef();
if (strong)
qDebug() << "The value is:" << *strong;
else
qDebug() << "The value has already been deleted";
提升为 QSharedPointer会检测对象是否被删除
//QScopedPointer类存储指向动态分配对象的指针,并在销毁时删除它
void myFunction(bool useSubClass)
{
// assuming that MyClass has a virtual destructor
QScopedPointer<MyClass> p(useSubClass ? new MyClass() : new MySubClass);
QScopedPointer<QIODevice> device(handsOverOwnership());
if (m_value > 3)
return;
process(device);
}
Custom Cleanup Handlers
Arrays as well as pointers that have been allocated with malloc must not be deleted using delete. QScopedPointer's second template parameter can be used for custom cleanup handlers.
The following custom cleanup handlers exist:
QScopedPointerDeleter - the default, deletes the pointer using delete
QScopedPointerArrayDeleter - deletes the pointer using delete []. Use this handler for pointers that were allocated with new [].
QScopedPointerPodDeleter - deletes the pointer using free(). Use this handler for pointers that were allocated with malloc().
QScopedPointerDeleteLater - deletes a pointer by calling deleteLater() on it. Use this handler for pointers to QObject's that are actively participating in a QEventLoop.
You can pass your own classes as handlers, provided that they have a public static function void cleanup(T *pointer).
// this QScopedPointer deletes its data using the delete[] operator:
QScopedPointer<int, QScopedPointerArrayDeleter<int> > arrayPointer(new int[42]);
// this QScopedPointer frees its data using free():
QScopedPointer<int, QScopedPointerPodDeleter> podPointer(reinterpret_cast<int *>(malloc(42)));
// this struct calls "myCustomDeallocator" to delete the pointer
struct ScopedPointerCustomDeleter
{
static inline void cleanup(MyCustomClass *pointer)
{
myCustomDeallocator(pointer);
}
};
// QScopedPointer using a custom deleter:
QScopedPointer<MyCustomClass, ScopedPointerCustomDeleter> customPointer(new MyCustomClass);
//std::auto_ptr 指针对象析构 指向对象自动释放
void Function()
{
auto_ptr<Obj> ptr( new Obj(20) );
...
if (error occur)
throw exception...
}
auto_ptr复制构造函数中把真是引用的内存指针进行的转移 可能产生野指针
//std::shared_ptr
shared_ptr自动销毁所管理的对象
std::shared_ptr 是一种智能指针,它能够记录多少个 shared_ptr 共同指向一个对象,从而消除显示的调用 delete,当引用计数变为零的时候就会将对象自动删除。
std::shared_ptr 可以通过 get() 方法来获取原始指针,通过 reset() 来减少一个引用计数,并通过get_count()来查看一个对象的引用计数。
shared_ptr<int> p1;
//被初始化成为一个空指针
shared_ptr<int> p2 (new int(4));
//指向一个值是4的int类型数据
shared_ptr<int> p3 = new int(4);
//错误,必须直接初始化
shared_ptr<T> p;
//空智能指针,可指向类型是T的对象
if(p)
//如果p指向一个对象,则是true
(*p)
//解引用获取指针所指向的对象
p -> number == (*p).number;
p.get();
//返回p中保存的指针
swap(p,q);
//交换p q指针
p.swap(q);
//交换p,q指针
make_shared<T>(args)
//返回一个shared_ptr的对象,指向一个动态类型分配为T的对象,用args初始化这个T对象
shared_ptr<T> p(q)
//p 是q的拷贝,q的计数器++,这个的使用前提是q的类型能够转化成是T*
shared_pts<T> p(q,d)
//p是q的拷贝,p将用可调用对象d代替delete
//上面这个我其实没懂,也没有查出来这个的意思
p =q;
//p的引用计数-1,q的+1,p为零释放所管理的内存
p.unique();
//判断引用计数是否是1,是,返回true
p.use_count();
//返回和p共享对象的智能指针数量
p.reset();
p.reset(q);
p.reset(q,d);
//reset()重新设置 新的指想对象
//std::weak_ptr
weak_ptr是一种不控制所指向对象生存期的智能指针,指向shared_ptr管理的对象,但是不影响shared_ptr的引用计数。它像shared_ptr的助手,一旦最后一个shared_ptr被销毁,对象就被释放,weak_ptr不影响这个过程。
weak_ptr是为配合shared_ptr而引入的一种智能指针来协助shared_ptr工作,它可以从一个shared_ptr或另一个weak_ptr对象构造,它的构造和析构不会引起引用计数的增加或减少。没有重载 * 和 -> 但我们可以通过lock来获得一个shared_ptr对象来对资源进行使用,如果引用的资源已经释放,lock()函数将返回一个存储空指针的shared_ptr。 expired函数用来判断资源是否失效。
weak_ptr的使用更为复杂一点,它可以指向shared_ptr指针指向的对象内存,却并不拥有该内存,而使用weak_ptr成员lock,则可返回其指向内存的一个share_ptr对象,且在所指对象内存已经无效时,返回指针空值nullptr。
注意:weak_ptr并不拥有资源的所有权,所以不能直接使用资源。
可以从一个weak_ptr构造一个shared_ptr以取得共享资源的所有权。
weak_ptr<T> w(sp);
//定义一个和shared_ptr sp指向相同对象的weak_ptr w,T必须能转化成sp指向的类型
w = p;
//p是shared_ptr或者weak_ptr,w和p共享对象
w.reset();
//w置为空
w.use_count();
//计算与w共享对象的shared_ptr个数
w.expired();
//w.use_count()为0,返回true
w.lock();
//w.expired()为true,返回空shared_ptr,否则返回w指向对象的shared_ptr
//std::unique_ptr
unique_ptr 不共享它的指针。它无法复制到其他 unique_ptr,无法通过值传递到函数,也无法用于需要副本的任何标准模板库 (STL) 算法。只能移动unique_ptr。
可以使用 移动语义转移所有权
unique_ptr<int> pInt(new int(5));
unique_ptr<int> pInt2 = std::move(pInt); // 转移所有权 转换为右值
函数可以返回 unique_ptr 类似移动语义 函数返回值是右值
unique_ptr<int> clone(int p)
{
unique_ptr<int> pInt(new int(p));
return pInt; // 返回unique_ptr
}
int main() {
int p = 5;
unique_ptr<int> ret = clone(p);
cout << *ret << endl;
}
//示例代码
#include <memory>
#include <iostream>
#include <utility>
class Foo{
public:
Foo() = default;
Foo(int a):_a(a) {}
~Foo() {}
int get_a(){
return _a;
}
void set_a(int a) {
_a = a;
}
private:
int _a;
};
std::unique_ptr<Foo> change_a(std::unique_ptr<Foo> f)
{
f->set_a(10);
return f;
}
int main()
{
// std::make_unique是c++14才有
std::unique_ptr<Foo> pf = std::make_unique<Foo>(10);
// unique_ptr的复制构造函数和拷贝构造函数是删除了的,这样保证了对象独占,如果不是独占,那么跟shared_ptr
// 就是一样的功能了。
// std::unique_ptr<Foo> pf1 = pf; // compile error
// 按值传参,会有拷贝问题,同上
// auto p = change_a(pf); //compile error
auto p = change_a(std::move(pf));
std::cout << "get_a = " << p->get_a() << std::endl;
if(!pf)
{
std::cout << "pf is nullptr" << std::endl;
}
//owner transfer from function
std::unique_ptr<Foo> pf2 = std::make_unique<Foo>(11);
std::unique_ptr<Foo> p2 = change_a(std::move(pf2));
std::cout << "get_a = " << p2->get_a() << std::endl;
if(!pf2)
{
std::cout << "pf2 is nullptr" << std::endl;
}
//使用reset
pf2.reset(new Foo(12));
std::cout << "pf2 is not null: " << pf2->get_a() << std::endl;
//release获取原始指针
Foo* ff = pf2.release();
if(!pf2)
{
std::cout << "pf2 is nullptr" << std::endl;
}
std::cout << "ff is not null: " << ff->get_a() << std::endl;
return 0;
}
自定义隐士共享
#include <QSharedData>
#include <QString>
class EmployeeData : public QSharedData
{
public:
EmployeeData() : id(-1) { }
EmployeeData(const EmployeeData &other)
: QSharedData(other), id(other.id), name(other.name) { }
~EmployeeData() { }
int id;
QString name;
};
class Employee
{
public:
Employee() { d = new EmployeeData; }
Employee(int id, QString name) {
d = new EmployeeData;
setId(id);
setName(name);
}
Employee(const Employee &other)
: d (other.d)
{
}
void setId(int id) { d->id = id; }
void setName(QString name) { d->name = name; }
int id() const { return d->id; }
QString name() const { return d->name; }
private:
QSharedDataPointer<EmployeeData> d;
};
QT常用功能
各式无关读取图片
QByteArray m_photo = vCard.photo();
QBuffer buffer;
buffer.setData(m_photo);
buffer.open(QIODevice::ReadOnly);
QImageReader imageReader(&buffer);
QImage image = imageReader.read();
工程文件参数
TEMPLATE = app / lib app/ .dll
CONFIG += c++11 //支持c++11
CONFIG += link_pkgconfig
DEFINES += LOG_TO_FILE
DESTDIR = $$PWD/ //生成文件路径
TARGET = file //目标文件名称
OBJDIR = obj_temp
UI_DIR = $$OBJDIR/ui
RCC_DIR = $$OBJDIR/rcc
MOC_DIR = $$OBJDIR/moc
OBJECTS_DIR = $$OBJDIR/obj
INCLUDEPATH += $$PWD/include //头文件路径
DEPENDPATH += $$PWD/include //文件搜索路径
CONFIG += resources_big //存储大资源文件
QMAKE_CXXFLAGS += -Wno-unused-parameter -Wno-unused-variable //消除编译时没有使用参数和变量的警告
CONFIG(debug, debug|release) {
LIBS += -L$$[QT_INSTALL_BINS] -lQt5Solutions_SingleApplication-headd
} else {
LIBS += -L$$[QT_INSTALL_BINS] -lQt5Solutions_SingleApplication-head
}
//执行系统命令
system($$[QT_INSTALL_BINS]/rcc.exe -binary $$PWD/res.qrc -o $$PWD/myresource.rcc)
RC_ICONS = Image/app.ico //应用程序图标
//条件编译
!win32: {
RESOURCES += \
res.qrc
}
//补充
QMAKE_RPATHDIR “运行”的时候,去找的目录。运行的时候,要找 .so 文件
QMAKE_RPATHLINKDIR 这个也是用于“链接”的时候的,例如你显示指定的需要 FOO.so,但是
FOO.so 本身是需要 BAR.so 的,后者你并没有指定,而是 FOO.so 引用到它,这个时候,会先从 -rpath-link 给的路径里找。
//pkg-config使用
CONFIG += link_pkgconfig
PKGCONFIG += ogg dbus-1
应用程序主题
QStyleFactory::keys() 获取所有的 支持的风格类型
void QApplication::setStyle(QStyle * style) 应用该风格
QStyle * QApplication::setStyle(const QString & style)
qss换肤
QString Style::getStylesheet(const QString &filename)
{
QFile file(filename);
if (!file.open(QFile::ReadOnly | QFile::Text))
{
qWarning() << "Stylesheet " << filename << " not found";
return QString();
}
return resolve(file.readAll());
}
qt加载flash
1.在pro文件中加入 QT += axcontainer
2.加入头文件
3.加入代码
QAxWidget object;
object.setControl("{d27cdb6e-ae6d-11cf-96b8-444553540000}");
object.dynamicCall("LoadMovie(long, QString)", 0, "J:\\flash2509.swf");
object.show();
QFileIconProvider 获取文件图标
QFileIconProvider iconProvider;
QIcon icon=iconProvider.icon(QFileIconProvider::Folder);
qt 加载外部字体
int fontId=QFontDatabase::addApplicationFont(":/Font/fontawesome-webfont");
QStringList fontFamilies=QFontFatabase::applicationFontFamilies(fontId);
QFont font;
font.setFamily(fontFamilies.at(0));
font.setPointSize(20);
QCryptographicHash MD5 SHA
QCryptographicHash::hash("AAA", QCryptographicHash::Md5)
处理事件循环
QCoreApplication::processEvents();
全局鼠标
QCursor::pos() //当前鼠标坐标 全局
QApplication::mouseButtons() //当前鼠标按键
自定义QDebug
1.重写输出函数
```
#include <qapplication.h>
#include <stdio.h>
#include <stdlib.h>
void myMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
QByteArray localMsg = msg.toLocal8Bit();
switch (type) {
case QtDebugMsg:
fprintf(stderr, "Debug: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
break;
case QtWarningMsg:
fprintf(stderr, "Warning: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
break;
case QtCriticalMsg:
fprintf(stderr, "Critical: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
break;
case QtFatalMsg:
fprintf(stderr, "Fatal: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
abort();
}
}
int main(int argc, char **argv)
{
qInstallMessageHandler(myMessageOutput);
QApplication app(argc, argv);
...
return app.exec();
}
```
2使用qt自带的函数注册输出格式
```
qSetMessagePattern("[%{time h:mm:ss.zzz} %{if-debug}Debug%{endif}%{if-warning}Waring%{endif}%{if-critical}
Critical%{endif}%{if-fatal}Fatal%{endif}] %{file}:%{line} : %{message}");
```
//debug 过滤打印
QLoggingCategory
声明 : Q_DECLARE_LOGGING_CATEGORY(testLog)
定义 : Q_LOGGING_CATEGORY(testLog, "test.usb")
过滤: QLoggingCategory::setFilterRules("test.usb*=true");
QLoggingCategory::setFilterRules("test.usb.debug=true");
//设置配置文件过滤
~/.config/QtProject/qtlogging.ini
[Rules]
*.debug=false
driver.usb.debug=true
//环境变量过滤
QT_LOGGING_RULES="*.debug=false;driver.usb.debug=true"
//使用
qCDebug(testLog)<<"OK";
//开启和关闭 源代码位置
.pro DEFINES QT_MESSAGELOGCONTEXT or QT_NO_MESSAGELOGCONTEXT.
线程池
QtConcurrent::run(QThreadPool::globalInstance(), [this](){ 实现代码 });
QChar
QChartView *chartView = new QChartView(childWidget);
chartView->setRenderHint(QPainter::Antialiasing);
chartView->resize(childWidget->size());
int index = analysis.indexOf("名称");
QtCharts::QChart *chart = chartView->chart();
if(chart == nullptr) {
return;
}
chart->setTheme(QtCharts::QChart::ChartThemeDark);
chart->setMargins(QMargins(0, 0, 0, 0));
if(index >= 0) {
chartView->chart()->setTitle(analysis.at(index + 1));
}
chartView->chart()->legend()->hide();
QSplineSeries *series = new QSplineSeries(chartView);
chartView->chart()->addSeries(series);
QValueAxis *axisHorizontal = new QValueAxis();
QValueAxis *axisVertical = new QValueAxis();
chartView->chart()->addAxis(axisHorizontal, Qt::AlignBottom);
chartView->chart()->addAxis(axisVertical, Qt::AlignLeft);
series->attachAxis(axisVertical);
series->attachAxis(axisHorizontal);
axisHorizontal->setTickCount(24);
axisHorizontal->setLabelFormat("%i");
axisHorizontal->setRange(0, 24);
axisVertical->setTickCount(5);
axisVertical->setRange(0, 10);
series->append(0, 23);
series->append(1, 45);
series->append(2, 123);
series->append(3, 23);
axisVertical->setRange(0, 123 + 10);
动态库和插件
//加载动态库 .dll .so
QLibrary myLib("mylib");
typedef void (*MyPrototype)();
MyPrototype myFunction = (MyPrototype) myLib.resolve("mysymbol");
if (myFunction)
myFunction();
//2
typedef void (*MyPrototype)();
MyPrototype myFunction = (MyPrototype) QLibrary::resolve("mylib", "mysymbol");
if (myFunction)
myFunction();
//创建插件
//1 通用插件
class GenericPlugin : public QGenericPlugin
{
Q_OBJECT
#if QT_VERSION >= 0x050000
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QGenericPluginFactoryInterface" FILE "untitled1.json")
#endif // QT_VERSION >= 0x050000
public:
GenericPlugin(QObject *parent = nullptr);
virtual QObject* create(const QString& name, const QString &spec);
};
//插件创建
要创建插件需要如下步骤:
1. 首先声明一个继承QObject和 插件接口类
2. 使用Q_INTERFACES() 注册接口到元对象系统
3. 使用Q_PLUGIN_METADATA()导出数据到元对象系统
4. 对。pro文件编译
//动态插件
class FilterInterface
{
public:
virtual ~FilterInterface() {}
virtual QStringList filters() const = 0;
virtual QImage filterImage(const QString &filter, const QImage &image,
QWidget *parent) = 0;
};
Q_DECLARE_INTERFACE(FilterInterface, "my.fileplugin")
#include <QObject>
#include <QtPlugin>
#include <QStringList>
#include <QImage>
#include <plugandpaint/interfaces.h>
class ExtraFiltersPlugin : public QObject, public FilterInterface
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.Examples.PlugAndPaint.FilterInterface" FILE "extrafilters.json")
Q_INTERFACES(FilterInterface)
public:
QStringList filters() const;
QImage filterImage(const QString &filter, const QImage &image,
QWidget *parent);
};
大小端转换
T qFromBigEndian(T src)
T qFromBigEndian(const void *src)
void qFromBigEndian(const void *src, qsizetype count, void *dest)
T qFromLittleEndian(T src)
T qFromLittleEndian(const void *src)
void qFromLittleEndian(const void *src, qsizetype count, void *dest)
T qToBigEndian(T src)
void qToBigEndian(T src, void *dest)
void qToBigEndian(const void *src, qsizetype count, void *dest)
T qToLittleEndian(T src)
void qToLittleEndian(T src, void *dest)
void qToLittleEndian(const void *src, qsizetype count, void *dest)
Unuutu安装 qt
ubuntu包地址 https://packages.ubuntu.com/focal/qt5-default
sudo apt install build-essential 编译器
sudo apt-get install qt5-default qtdeclarative5-dev
QML module not found(QtQuick.Controls)
apt-get install qml qmlscene
apt-get install qtdeclarative5-dev
apt -y install qml-module-qtquick-controls
apt -y install qml-module-qtquick-controls2
Qt使用模块代码
qt mqtt
1 下载mqtt库源码
git clone git://code.qt.io/qt/qtmqtt.git
2 进入上述文件主目录,编译(需要先把qt 5.12的qmake添加到环境变量中去)
windows下
qmake
mingw32-make
mingw32-make install
linux下
qmake
make
make install
3 成功后,会在qt的 QT_INSTALL_LIBS目录下看到mqtt的库
4 qt 工程 pro文件添加 matt,不会报错了
QT += mqtt
//使用
m_client = new QMqttClient(this);
m_client->setHostname(ui->lineEditHost->text());
m_client->setPort(ui->spinBoxPort->value());
m_client->setClientId("mqtt_1");
m_client->setUsername("275667");
m_client->setPassword("");
m_client->connectToHost();
//接收
connect(this, &QMqttClient::messageReceived, this, [this](const QByteArray &message, const QMqttTopicName &topic){
emit MQTTProtocol::messageReceived(message, topic.name());
});
//发布
QMqttClient::publish(topic, message, qos, retain);
//订阅
QMqttSubscription *subscription = QMqttClient::subscribe(topic, static_cast<quint8(qos));
connect(this, &QMqttClient::disconnected, subscription, &QObject::deleteLater);
//SSL连接
再main里添加 CA证书
const auto certs = QSslCertificate::fromPath("C:/Users/Administrator/Desktop/*.pem",
QSsl::Pem, QRegExp::Wildcard);
for (const QSslCertificate &cert : certs) {
QSslSocket::addDefaultCaCertificate(cert);
}
sslPeerName就是证书里面的 cert.issuerInfo(QSslCertificate::CommonName);
//连接
connectToHostEncrypted(sslPeerName);
qt xlsx
1 下载xlsx库源码
git clone https://github.com/dbzhang800/QtXlsxWriter.git
2 进入上述文件主目录,编译(需要先把qt 5.12的qmake添加到环境变量中去)
windows下
qmake
mingw32-make
mingw32-make install
linux下
qmake
make
make install
错误
C:\QtXlsxWriter\src\xlsx\xlsxzipreader.cpp:51: error: C2440: “初始化”: 无法从“QVector<QZipReader::FileInfo>”转换为“QList<QZipReader::FileInfo>”
修改 QList为QVector
3 成功后,会在qt的 QT_INSTALL_LIBS目录下看到xlsx的库
4 qt 工程 pro文件添加 xlsx,不会报错了
QT += xlsx
5 使用
QXlsx::Document xlsx;
xlsx.addSheet("在线报表");
xlsx.setColumnWidth(1, 30);
xlsx.setColumnWidth(2, 10);
xlsx.setColumnWidth(3, 30);
xlsx.setColumnWidth(4, 10);
for(int i = 0; i < model->rowCount(); i++)
{
for(int j = 0; j < model->columnCount(); j++)
{
xlsx.write(i, j + 1, model->index(i, j).data());
}
}
QString fileName = QFileDialog::getSaveFileName(this, "导出报表", QString(), "(*.xlsx)");
if(!fileName.isEmpty())
xlsx.saveAs(fileName);
qt-solutions
1 下载qt-solutions库源码
git clone https://github.com/qtproject/qt-solutions.git
2 进入上述文件主目录,编译(需要先把qt 5.12的qmake添加到环境变量中去)
windows下
qmake
mingw32-make
mingw32-make install
linux下
qmake
make
make install
3 成功后,会在qt的 QT_INSTALL_LIBS目录下看到Qt5Solutions_SingleApplication-headd的库
4 qt 工程 pro文件添加
CONFIG(debug, debug|release) {
LIBS += -L$$[QT_INSTALL_BINS] -lQt5Solutions_SingleApplication-headd
} else {
LIBS += -L$$[QT_INSTALL_BINS] -lQt5Solutions_SingleApplication-head
}
5 使用
QtSingleApplication a(argc, argv);
if(a.isRunning())
return -1;
qtcreater msvc
1 安装qt选择 msvc 相应选项
2 下载msvc 编译工具
Build Tools for Visual Studio 2017 (version 15.9)
3 在 .pro中添加 msvc:QMAKE_CXXFLAGS += -execution-charset:utf-8
防止乱码
4 开发
qt openssl支持
1.查看qt使用的 ssl库版本
qDebug()<<QSslSocket::sslLibraryBuildVersionNumber();
qDebug()<<QSslSocket::sslLibraryBuildVersionString();
2.下载安装openssl
如果没有相同版本 选择相近版本
https://slproweb.com/products/Win32OpenSSL.html
qt mapboxgl插件 linux编译
sudo apt-get install build-essential
sudo apt-get install libicu-dev
sudo apt-get install zlib1g-dev
sudo apt-get install qt5-default
sudo apt-get install qtdeclarative5-dev
sudo apt-get install qt5-doc
sudo apt-get install qml
sudo apt-get install qtdeclarative5-private-dev
sudo apt-get install qtlocation5-dev
sudo apt-get install qtpositioning5-dev
下载 对应版本 qtlocation-everywhere-src-5.12.2.tar
复制qt头文件到 /usr/include/x86_64/qt5 下
头文件安装run包获取
解压:
qtlocation
进入解压目录:
qmake
make sub-src -j4 根据自己cpu设置并行数量
完成后在 plugin下有编译完成插件
qt 打包 Linux
下载:linuxdeployqt-x86_64.AppImage
地址: https://github.com/probonopd/linuxdeployqt/releases
inuxdeployqt-6-x86_64.AppImage
//测试
$ chmod +x linuxdeployqt-x86_64.AppImage
$ mv linuxdeployqt-x86_64.AppImage linuxdeployqt
$ mv linuxdeployqt /usr/local/bin
$ linuxdelpoyqt --version
#输出的版本信息
linuxdeployqt 5 (commit 37631e5), build 631 built on 2019-01-25 22:47:58 UTC
//配置环境变量
#add QT ENV
export PATH=/home/Qt5.12.6/5.12.6/gcc_64/bin:$PATH
export LD_LIBRARY_PATH=/home/Qt5.12.6/5.12.6/gcc_64/lib:$LD_LIBRARY_PATH
export QT_PLUGIN_PATH=/home/Qt5.12.6/5.12.6/gcc_64/plugins:$QT_PLUGIN_PATH
export QML2_IMPORT_PATH=/home/Qt5.12.6/5.12.6/gcc_64/qml:$QML2_IMPORT_PATH
//打包
创建目录 拷贝可执行文件到目录 进入目录
linuxdeployqt ./app -appimage如果提示libc太新 用下面的
linuxdeployqt ./ExcaMonitor -appimage -unsupported-allow-new-glibc
//拷贝缺少库
plugins/
├── bearer
├── geoservices
├── imageformats
├── platforminputcontexts
├── platforms
├── position
├── sqldrivers
└── xcbglintegrations
qml
├── Qt
├── QtCanvas3D
├── QtGraphicalEffects
├── QtLocation
├── QtPositioning
├── QtQml
├── QtQuick
└── QtQuick.2
lib
├── libQt5Core.so.5
├── libQt5DBus.so.5
├── libQt5Gui.so.5
├── libQt5Location.so.5
├── libQt5Network.so.5
├── libQt5PositioningQuick.so.5
├── libQt5Positioning.so.5
├── libQt5Qml.so.5
├── libQt5QuickControls2.so.5
├── libQt5Quick.so.5
├── libQt5QuickTemplates2.so.5
├── libQt5QuickWidgets.so.5
├── libQt5SerialPort.so.5
├── libQt5Sql.so.5
├── libQt5Svg.so.5
├── libQt5VirtualKeyboard.so.5
├── libQt5Widgets.so.5
├── libQt5XcbQpa.so.5
//openssl匹配 版本一定要对应
wget https://www.openssl.org/source/old/1.1.1/openssl-1.1.1b.tar.gz
./configure
make
cp libcrypto.so* ../lib/
cp libssl.so* ../lib/
添加 run.sh
chmod +x run.sh
//内容
#!/bin/bash
export LD_LIBRARY_PATH=./lib:$LD_LIBRARY_PATH
export QT_PLUGIN_PATH=./plugins:$QT_PLUGIN_PATH
export QML2_IMPORT_PATH=./qml:$QML2_IMPORT_PATH
./AppRun
//或者添加 qt.conf
Prefix = ./
Plugins = plugins
Imports = qml
Qml2Imports = qml
//可选项
桌面图标
#-- 全局安装(所有用户可用),将xxx.desktop 复制到/usr/share/applications
#-- 当前用户可用, 将xxx.desktop 复制到 ~/.local/share/applications 目录即可
#--appName.desktop
[Desktop Entry]
Version=1.0 #app的版本
Name=cleanRobot #app的名字
Comment= this app use for xxx #说明信息
Exec=/path/to/your/QtApp/cleanRobot #app的执行路径,绝对路径
Icon=/path/to/your/app_icon/cleanRobot.ico #icon 路径,绝对路径
Terminal=false #是否在终端启动,效果自己试一下就知道了
Type=Application
Categories=Utility;Application;
./ExcaMonitor >> my.log 2>&1 重定向输出到 文件
//开机自启动
搜索
startup Application 添加启动命令
//
vi /etc/profile
================ End
来源:oschina
链接:https://my.oschina.net/u/4397718/blog/4267146