QT各种类 2020-11-07

  • QThread
  • QMutexLocker
  • QWaitCondition
  • QLocalServer
  • QLocalSocket
  • QUdpSocket
  • QTimer
  • QHostAddress
  • QDnsLookup
  • QHostInfo
  • QNetworkReply
  • QNetworkInterface

注意事项

  • 继承自QThread的类,如果添加多个数据成员,在修改/读取数据成员时,为了保障数据一致性,需要使用QMutex 锁起来.
  • 线程的启动/运行中等待/退出
    • 启动使用start(),
    • 运行中表示方法run()还没有运行完毕,可以使用isRunning()查询状态
    • 要想退出,需要让run()访问退出,一般要破坏掉run()方法中的while循环条件(如果其中还有其他的暂停等待的功能实现,例如使用了QWaitCondition,让线程处于暂行等待的状态,也需要满足等待条件(调用QWaitCondition::wakeOne())),然后调用wait()方法等待run()运行完成.

其他注意事项

  • 类的构造函数如果只有一个参数,一般要使用 explicit 关键字,防止类型转换
  • Qt中资源的释放,大多靠构造时传入的parent(QObject *parent = nullptr)参数的析构函数,所以在构造类实例时尽可能传入parent参数.
  • 根据对代码运行结果的分析,如果widget(例如QLabel)在new时没有传入parent,但是该widget被加入layout,当调用setLayout后,没有parent的widget也有了widget.
  • 在继承QWidget时,如果有些子Widget不需要在多个成员方法中用到,可以不用把这些widget作为类的成员,只需要在构造界面的函数中直接使用.
  • 当不在main函数中,想要获取命令行参数的方法:
    QStringList args = QCoreApplication::instance()->arguments();
    args.takeFirst();           // 需要注意,第一个参数时应用的名称,跳过
    
  • QCoreApplication的正确使用方式是:
      int main(int argc, char **argv)
      {
          using namespace std;
    
          QCoreApplication app(argc, argv);
          QStringList arguments = app.arguments();
          arguments.takeFirst();      // remove the first argument, which is the program's name
    
          if (arguments.isEmpty()) {
          printf("Qt Download example\n"
                 "Usage: downloadmanager url1 [url2... urlN]\n"
                 "\n"
                 "Downloads the URLs passed in the command-line to the local directory\n"
                 "If the target file already exists, a .0, .1, .2, etc. is appended to\n"
                 "differentiate.\n");
          return 0;
          }
    
          DownloadManager manager;
          manager.append(arguments);
    
          QObject::connect(&manager, &DownloadManager::finished,
                       &app, &QCoreApplication::quit);      ///<<-=-=-==-=-=-=-=-=-=-=这里是重点
          return app.exec();
      }
    
    

QUdpSocket的使用

  • 一般使用方法就是先调用bind()方法, 然后调用 writeDatagram() / readDatagram() / receiveDatagram() 传输数据.
  • 如果只是发送数据报, 不必调用bind()方法.
  • 如果想使用 QIODevice 中的 read(), readLine(), write(),等方法,首先必须调用connectToHost().
  • 每次数据报发送完成后,都会触发信号: bytesWritten()
  • 当收到数据报时,会触发信号: readyRead() ,此时 hasPendingDatagrams() 返回 true. 调用 pendingDatagramSize() 可以获得第一个数据报的大小, 然后可以调用 readDatagram() 或者 receiveDatagram() 读取数据报内容.
  • qint64 QUdpSocket::readDatagram(char *data, qint64 maxSize, QHostAddress *address = nullptr, quint16 *port = nullptr)
  • QNetworkDatagram QUdpSocket::receiveDatagram(qint64 maxSize = -1)

QTimer的使用

  • 类似于interval
     QTimer *timer = new QTimer(this);
     connect(timer, &QTimer::timeout, this, QOverload<>::of(&AnalogClock::update));
     timer->start(1000);
  • 一次性的闹钟
setSingleShot(true)

     QTimer::singleShot(200, this, &Foo::updateCaption);

QTimer使用注意事项

  • 在多线程应用中,QTimer可以在任何有 an event loop的线程中使用.
  • 在非GUI应用中,可以通过调用QThread::exec()来开启event loop.
  • 调用QTimer的start(), stop(),都必须在其所在的线程中.
  • 其他的timer
    1. Qt::PreciseTimer 精度:1毫秒
    2. Qt::CoarseTimer 精度: 5% of the interval
    3. Qt::VeryCoarseTimer 精度:500 ms
    4. 调用QObject::startTimer() / QObject::killTimer()
    5. QBasicTimer

QHostAddress 使用

  • QHostAddress 可以用于IPv4 和IP v6的地址

  • 不解析dns. 想要解析域名,需要使用QHostInfo

  • 包含一些常用的主机地址

    • QHostAddress::Null
      The null address object. Equivalent to QHostAddress(). See also QHostAddress::isNull().
    • QHostAddress::LocalHost
      The IPv4 localhost address. Equivalent to QHostAddress("127.0.0.1").
    • QHostAddress::LocalHostIPv6
      The IPv6 localhost address. Equivalent to QHostAddress("::1").
    • QHostAddress::Broadcast
      The IPv4 broadcast address. Equivalent to QHostAddress("255.255.255.255").
    • QHostAddress::AnyIPv4
      The IPv4 any-address. Equivalent to QHostAddress("0.0.0.0"). A socket bound with this address will listen only on IPv4 interfaces.
    • QHostAddress::AnyIPv6
      The IPv6 any-address. Equivalent to QHostAddress("::"). A socket bound with this address will listen only on IPv6 interfaces.
    • QHostAddress::Any
      The dual stack any-address. A socket bound with this address will listen on both IPv4 and IPv6 interfaces.

QDnsLookup 使用

使用步骤如下:

  1. new一个QDnsLookup
  2. connect finished() signal
  3. 设置type, 调用setType()
    包括:
    • QDnsLookup::A
      IPv4 address records.
    • QDnsLookup::AAAA
      IPv6 address records.
    • QDnsLookup::ANY
      any records.
    • QDnsLookup::CNAME
      canonical name records.
    • QDnsLookup::MX
      mail exchange records.
    • QDnsLookup::NS
      name server records.
    • QDnsLookup::PTR
      pointer records.
    • QDnsLookup::SRV
      service records.
    • QDnsLookup::TXT
      text records.
  4. 设置name,调用setName()
  5. 调用lookup()
  6. 在处理finished信号的函数中,根据type不同,调用不同的函数
    • QList canonicalNameRecords() const
    • QList hostAddressRecords() const
    • QList mailExchangeRecords() const
    • QList nameServerRecords() const
    • QHostAddress nameserver() const
    • QList pointerRecords() const
    • QList serviceRecords() const
    • QList textRecords() const

实例代码

 void MyObject::lookupServers()
 {
     dns = new QDnsLookup(this);
     connect(dns, SIGNAL(finished()),
             this, SLOT(handleServers()));

     dns->setType(QDnsLookup::A);
     dns->setName("www.baidu.com");
     dns->lookup();
 }

 void MyObject::handleServers()
 {
     // Check the lookup succeeded.
     if (dns->error() != QDnsLookup::NoError) {
         qWarning("DNS lookup failed");
         dns->deleteLater();
         return;
     }

     // Handle the results.
     const auto records = dns->hostAddressRecords();
     for (auto record : records) {
         //...
     }
     dns->deleteLater();
 }

QHostInfo 使用

  • 异步方式(通过signal/slot接收结果)
 // To find the IP address of qt-project.org
 QHostInfo::lookupHost("qt-project.org",
                       this, SLOT(printResults(QHostInfo)));

 // To find the host name for 4.2.2.1
 QHostInfo::lookupHost("4.2.2.1",
                       this, SLOT(printResults(QHostInfo)));

//在printResults() 函数中 调用  addresses() 或者hostName() 获取结果
  • 在获取结果过程中,可以调用QHostInfo::abortHostLookup(int id) 取消操作.
  • 同步方式
 QHostInfo info = QHostInfo::fromName("qt-project.org");

  • 还有本地信息:
    • 获取主机名称: QHostInfo::localHostName()
    • 获取主机域名: QHostInfo::localDomainName()

QNetworkReply 使用

  • 常规的使用方式如下:
      QNetworkRequest request(url);
      currentDownload = manager.get(request);
      connect(currentDownload, &QNetworkReply::downloadProgress,
              this, &DownloadManager::downloadProgress);
      connect(currentDownload, &QNetworkReply::finished,
              this, &DownloadManager::downloadFinished);
      connect(currentDownload, &QNetworkReply::readyRead,
              this, &DownloadManager::downloadReadyRead);
    
    void DownloadManager::downloadProgress(qint64 bytesReceived, qint64 bytesTotal){ }
    void DownloadManager::downloadFinished(){ }
    void DownloadManager::downloadReadyRead()
    {
        output.write(currentDownload->readAll());
    }
    
    
  • 从QNetworkReply获取statusCode
    bool DownloadManager::isHttpRedirect(QNetworkReply *reply)
    {
        int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
        return statusCode == 301 || statusCode == 302 || statusCode == 303
               || statusCode == 305 || statusCode == 307 || statusCode == 308;
    }
    
  • 从中获取302跳转的新地址(Location头的值)
      QVariant target = currentDownload->attribute(QNetworkRequest::RedirectionTargetAttribute);
      if (!target.isValid())
          return;
      QUrl redirectUrl = target.toUrl();
      if (redirectUrl.isRelative())
          redirectUrl = requestUrl.resolved(redirectUrl);
    
  • 使用完毕后,要delete
    reply->deleteLater();
    

QNetworkInterface的使用

  • 获取本机所有的网卡
    QList ipAddressesList = QNetworkInterface::allAddresses();
    

你可能感兴趣的:(QT各种类 2020-11-07)