- 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
- Qt::PreciseTimer 精度:1毫秒
- Qt::CoarseTimer 精度: 5% of the interval
- Qt::VeryCoarseTimer 精度:500 ms
- 调用QObject::startTimer() / QObject::killTimer()
- 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.
- QHostAddress::Null
QDnsLookup 使用
使用步骤如下:
- new一个QDnsLookup
- connect finished() signal
- 设置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.
- QDnsLookup::A
- 设置name,调用setName()
- 调用lookup()
- 在处理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
- QList
实例代码
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();