Qt使用和常用代碼

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 &parameter) {
          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();
  }

資源文件

資源文件以 .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);

智能指針

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;
	}; 

各式無關讀取圖片

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             //目標文件名稱

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
}

自定義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}");
```

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();

//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);

 

 

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