QT学习笔记(七)

2023-11-12

第12章 输入与输出

Qt提供了读写字节块的设备类QIODevice,QIODevice类是抽象的,无法被实例化,一般是使用它的子类。它包括如下子类:
在这里插入图片描述
其中,QProcess,QTcpSocket,QUdpSocket,QSslSocket都是顺序存取设备,这意味着所存储的数据从第一个字节开始到最后一个字节为止只能被读取一次。QFile,QTemporaryFile,QBuffer则是随机存取设备,因此可以从任意位置多次读取字节位所存储的数据,随机存取设备支持使用seek()函数来定位到任意位置。QProcess类允许启动外部程序并通过标准输入、输出及标准错误通道(cin,cout和cerr)与外部程序交互。
除了设备类,Qt还提供了两个更高级别的流类,使我们可以从任意的输入输出设备读取或者写入数据:QDataStream用来读写二进制数据,QTextStream用来读写文本数据。它们提供了一种与运行平台无关的存储格式。

  1. 读取和写入二进制数据

Qt中载入和保存二进制数据最简单的方式是:通过实例化一个QFile打开文件,然后通过QDataStream对象存取它。QDataStream支持多种类型的类,如:整型和双精度浮点型等基本的C++类,QList<T>和QMap<T>等Qt容器类,以及QByteArray、QIamgae、QString和QVariant等多种Qt数据类型。
二进制文件格式提供了数据存储最通用最紧凑的方式,而且QDataStream也使得存取二进制数据非常容易。
1)下面是在一个名为facts.dat的文件中存储一个整型数据、一个QImage以及一个QMap<QString,QColor>的代码:

QImage image("philip.png");

QMap<QString,QColor> map;
map.insert("red",Qt::red);
map.insert("green",Qt::green);
map.insert("blue",Qt::blue);

QFile file("facts.dat");                      //实例化一个QFile打开文件
if(!file.open(QIODevice::WriteOnly)) {
    std::cerr << "Cannot open file for writting: "
              << qPrintable(file.errorString()) << std::endl;   // 如果不能打开文件,就通知用户并返回
    retrn;
}

QDataStream out(&file);             //如果成功打开文件,就创建QDataStream对象             
out.setVersion(QDataStream::Qt_4_3);    //设置版本号

out << quint32(0x12345678) << image << map;    //向文件中写入数据

注意:我们将二进制数据写入数据流对象或从数据流中读取二进制数据,都需要串行化,就像上例中的quint32(0x12345678)。

//串行化字符串
out << QString("the answer is");
//串行化整数
out << (qint32) 42;

可以在串行化数据时选择使用哪种字节顺序,默认是高字节在前(big-endian),可以通过调用setByteOrder()来改变,但改为小端有可能会破坏可移植性。

我们不必明确的关闭这个文件,因为当QFile变量离开它的作用域的时候,文件会自动关闭(也可以调用close()函数强制关闭文件)。如果想检验数据是否被真正的写入,可以调用刷新函数flush()并检验其返回值(若返回值为true,则表示成功写入数据)
2) 从文件中读回数据:

quint32 n;
QImage image;
QMap<QString,Qcolor> map;

QFile file("facts.dat");                  //实例化一个QFile打开文件
if(!file.open(QIODevice::ReadOnly)) {
     std::cerr << "Cannot open file for writting: "
                   << qPrintable(file.errorString()) << std::endl;   // 如果不能打开文件,就通知用户并返回
    return;
}

QDataStream in(&file);                 //如果成功打开文件,就创建QDataStream对象
in.setVersion(QDataStream::Qt_4_3);   //设置版本号

in >> n >> image >> map;    //从文件中读取数据

当从QDataStream读取数据的时候,错误处理相当容易。流有一个status()值,可以是QDataStream::OK、QDataStream::ReadPastEnd或者QDataStream::ReadCorruptData。如果错误发生,则>>操作符总是读取0值或者空值。这表示通常可以简单的读取一个文件而不用担心出错,并在最后检查status()值以确定读取的文件数据是否有效。
3) 还可以通过重载<<或>>操作符为用户的自定义类型增加支持。格式如下:

QDataStream& operator<< (QDataStream& out,const Painting &painting); // 重载流运算符,其中Painting为自定义类型

4)如果想一次读取或者写入一个文件,可以完全不用QDataStream而使用QIODevice的 write() 和 readAll() 函数。例如:

bool copyFile(const QString &source,const QString &dest)
{
    QFile sourceFile(source);
    if(!sourceFile.open(QIODevice::ReadOnly))
            return false;
    QFile destFile(dest);
    if(!destFile.open(QIODevice::WriteOnly))
            return false;

    destFile.write(sourceFile.readAll());

    return  sourceFile.error() == QFile::NoError
              && destFile.error() == QFile::NoError;
}

在调用readAll()的那一行中,输入文件的所有内容都被读入到一个QByteArray中,然后将它传给write()函数以写到输出文件中。虽然获得QByteArray中的数据比逐项读取数据需要更多的内存,但它也带来了一些方便。例如:在这之后可以使用qComPress()和qUnCompress()函数来压缩和解压缩数据。

  1. 读取和写入文本

虽然二进制文件格式比通常基于文本的格式更加紧凑,但是它们是机器语言,无法人工阅读或者编辑。在二进制文件无法适应的场合,可以使用文本格式来代替。Qt提供了 QTextStream类读写纯文本文件以及如HTML、XML和源代码等其他文本格式的文件。QTextStream类可以在QIODevice、QByteArray和QString上进行操作。用法:
1)下面的代码将“Thomas M. Disch:334 \n”写到文件sf-book.txt中:

QFile file("sf-book.txt");
if (!file.open(QIODevice::WriteOnly())) {
    std::cerr << "Cannot open file for writing: "
                  << qPrintable(file.errorString()) <<std::endl;
    return; 
}

QTextStream out(&file);
out << "Thomas M. Disch: " << 334 << endl;

在默认情况下,QTextStream使用系统的本地编码进行读取和写入。但可以使用setCodec()函数改变:stream.setCodec("UTF-8");
如果想将文本直接写入QIODevice,那么必须为open()函数明确的指定QIODevice::Text标记,例如:file.open(QIODevice::WriteOnly | QIODevice::Text);
当写入的时候,这个标记将通知QIODevice将"\n"字符转换为Windows下的“\r\n”。当读取的时候,这个标记将告知设备忽略所有平台中的换行字符,然后使用“\n”作为换行符。
QTextStream提供了流操作器,可以在流上设置并改变流数据的状态。例如:

out << showbase << uppercasedigits << hex << 12345678;  //分别设置了“显示前缀”“在十六进制数中使用大写字母”“使用十六进制”状态

也可以通过成员函数来设置这些选项:

out.setNumberFlags(QTextStream::ShowBase
                                   | QTextStream::UppercaseDigits);
out.setIntegerBase(16);
out << 12345678;

2)写入文本数据很容易,但读取文本却是一个挑战。因为文本数据与使用QDataStream写入的二进制数据不同,从根本上说是含糊而不确定的。
QTextStream使用16位的QChar类型基本数据单元。
读取文本时通常通过在QChar上使用>>来一个字符一个字符地读取数据,或者通过使用QTextStream::readLine()来逐行读取数据 。如果要处理全部的文本,且不考虑内存的使用大小或者已经知道所读文件很小的情况下,可以使用QTExtStream::readAll()一次读取整个文件。用法:

QTextStream in(&file);
QString line = in.readLine();   //一次读取一行文本数据,readLine()函数自动去掉行尾的“\n”

while(!in.atEnd())
{
    in >> ch;                   //使用while循环 和>>运算符一个一个字符的读取数据
}
  1. 遍历目录

QDir类提供了一种与平台无关的遍历目录并获得有关文件信息的方法。QDir类用来访问目录结构及其内容,它可以操作底层的文件系统,还可以访问Qt的资源系统。 用法:

const QString &path;  //字符串中存储给定的路径,这个路径可以是当前目录下的相对路径也可以是绝对路径
QDir dir(path);  //使用给定的路径创建一个QDir对象

Qt使用“/”作为通用的目录分隔符,QDir可以使用相对路径或者绝对路径来指向一个文件。一个目录的路径可以使用path()函数获取,使用setPath()函数可以设置新的路径。
使用mkdir()来创建目录,使用rmdir()来删除目录,使用cd()来跳转到指定目录。用法:

//显示出当前目录下的所有.h文件
QDir myDir(QDir::currentPath());
myDir.setNameFilters(QStringList("*.h"));
myDir.entryList();
//创建目录并跳转
myDir.mkdir("mydir");
myDir.cd("mydir");

目录中会包含很多条目,如文件、目录和符号链接等。一个目录中条目的个数可以使用count()来返回,所有条目的名称列表可以使用entryList()来获取。如果需要每一个条目的信息,则可以使用entrylnfoList()函数来获取一个QFileInfo类对象的列表。
QFileInfo类可以访问文件的属性,如文件的名称、大小、路径、访问权限、属主和时间戳(最近一次修改/读取的时间)等等。QFileInfo可以使用相对路径或绝对路径来指向一个文件。用法:

#include <QFileInfo>
QFileInfo info(file);
qdebug << QObject::tr("绝对路径:") << info.absoluteFilePath() << endl << QObject::tr("文件名:") << info.fileName() << endl
              << QObject::tr("后缀:") << info.suffix() << endl << QObject::tr("大小")  << info.size();

在这里插入图片描述

  1. 嵌入资源

除了利用上面的输入输出方法在外部设备中存取数据外,还可以利用Qt的资源系统在可执行文件中嵌入二进制数据或文本。嵌入的文件与文件系统中的普通文件一样也可以通过QFile读取。
通过Qt资源编译器rcc,可以将资源转换为C++代码。还可以通过下面一行代码加到.pro文件中来告诉qmake包括专门的规则以运行rcc:

RESOURCES = myresourcefile.qrc
myresourcefile.qrc文件是一个XML文件,它列出了所有嵌入到可执行文件中的文件。

在应用程序中,资源是通过":/ "路径前缀识别的。

在可执行文件中嵌入数据具有不易丢失的优点,而且有利于可执行文件的独立性。但它有两个缺点:第一,如果要改变嵌入的数据,则整个可执行文件都要跟着替换;第二,由于必须容纳被嵌入的数据,可执行文件本身将会变得比较大。

  1. 临时文件QTemporaryFile

QTemporaryFile类可以安全地创建一个唯一的临时文件。当调用open()函数时便会创建一个临时文件(调用open()函数时,默认会使用QIODevice::ReadWrite模式),临时文件的文件名是唯一的。用法:

QTemporaryFile file;
if (file.open()) {
     //在这里对临时文件进行操作,file.fileName()可以返回唯一的文件名
}

当销毁QTemPoraryFile对象时,该文件会被自动删除掉。但调用close()函数后重新打开QTemporaryFile是安全的,只要QTemporaryFile的对象没有被销毁,那么唯一的临时文件就会一直存在且由QTemporaryFile内部保持打开。
临时文件默认会生成在系统的临时目录里,这个目录的路径可以使用QDir::tempPath()来获取。

  1. 缓冲区

QBuffer类为QByteArray提供了一个QIODevice接口,它允许使用QIODevice接口来访问QByteArray。
默认的,创建一个QBuffer时,则自动在内部创建一个QByteArray缓冲区。可以向QBuffer的构造函数中传递一个QByteArray类对象,来访问这个QByteArray缓冲区。用法:

//使用QDataStream 和 QBuffer 来向 QByteArray 写入数据
QByteArray byteArray;
QBuffer buffer(&byteArray);
buffer.open(QIODevice::WriteOnly);
QDataStream out(&buffer);
out << QApplication::palette();
//从QByteArray中读取数据
QPalette palette;
QBuffer buffer(&byteArray);
buffer.open(QIODevice::ReadOnly);
QDataStream in(&buffer);
in >> palette;

当新的数据到达了缓冲区时,QBuffer会发射readyRead()信号。通过关联这个信号,可以使QBuffer来存储临时的数据。

  1. 进程间通信

如果在当前的应用程序中调用外部的程序来实现一定的功能,这就会使用到进程。
QProcess类允许我们执行外部程序并且和他们进行通信。这个类是异步工作的,且它在后台完成它的工作,这样用户界面就可以保持响应。当外部进程完成时,QProcess会发出信号通知我们。用法:

private:
    QProcess  process;    //在窗口部件类的类声明中将QProcess类对象声明为private成员。

connect(&process,SIGNAL(error(QProcess::ProcessError)),this,SLOT(processError(QProcess::ProcessError)));
                                      // 在窗口部件类的构造函数中将QProcess对象的信号和窗口的私有槽进行连接
process.start("进程名称",参数);    //在成员函数中利用程序名称以及它所需要的参数来调用QProcess::start()函数,开始进程。

要启动一个进程,可以使用start()函数。–(执行完start()函数后,QProcess进入Starting状态)
当程序已经运行后,QProcess会发射started()信号。-- (QProcess进入Running状态)
当进程退出时,会发出finished()信号,发射的finished()信号提供了进程的退出状态。QProcess::ExitStatus给出了程序结束的状态值。–(QProcess重新进入NotRunning状态(初始状态))
任何时候发生了错误,如程序不能开启,QProcess都会发出error()信号,QProcess::ProcessError给出了错误的类型值。

QProcess异步执行的意思是:我们告知QProcess去运行某个程序并立即将控制权返还给用户界面程序,这样,当进程在后台运行时可以让用户界面始终保持响应。
但在某些情况下,在自己的应用程序进一步执行前,必须先完成外部进程,这时需要同步操作QProcess。QProcess同步操作时并不需要信号和槽的连接。有两种方法:
一种方法是使用QProcess::execute()静态函数,该函数运行外部进程,并当该外部进程完成时停止。
另一种更好的方法是:创建QProcess对象,并对它调用start(),然后通过调用QProcess::waitForStarted()强制使它停止。如果成功,再调用QProcess::waitForFinished()。
waitForStarted() 阻塞,直到进程启动、waitForFinished() 阻塞,直到进程结束
这两个函数会挂起调用的线程,直到确定的信号被发射。在主线程(QApplication::exec()的线程)中调用这些函数可能会引起用户界面的冻结。

QProcess继承自QIODevice,QProcess允许将一个进程视为一个顺序I/O设备。可以调用write()向进程的标准输入进行写入,调用read(), readLine()和getChar()等从标准输出进行读取。

第14章 多线程

在多线程应用程序中,图形用户界面运行于它自己的线程中,而另外的事件处理过程则会发生在一个或多个其他线程中。这样在处理那些数据密集的事件时,应用程序也能对图形用户界面保持响应。
在单一处理器上运行时,多线程应用程序可能会比实现同样功能的单线程应用程序运行的慢一些,无法体现出优势。但在多处理器系统中,多线程应用程序可以在不同的处理器上同时执行多个线程,从而获得更好的总体性能。

  1. 创建线程

在Qt应用程序中提供多线程:只需要子类化QThread并且重实现它的run()函数就可以了。
Qt中的QThread类提供了与平台无关的线程类。一个QThread代表了一个在应用程序中可以独立控制的线程,它与进程中的其他线程分享数据,但是是独立执行的。
相对于一般的程序从main()函数开始执行,QThread从run()函数开始执行。默认的,run()通过调用exec()来开启事件循环,并在线程内运行一个Qt事件循环。
实例:

//子类化QThread
#include <QThread>
class Thread : public QThread
{
    Q_OBJECT
public:
    explicit Thread(QObject *parent = 0);            //构造函数
    void stop();
protect:
    void run();          //重实现run()函数
private:
    volatile bool stopped;        //volatile关键字表示编译器不会对访问该变量的代码进行优化,当要求使用改变量的值的时候,系统总是重新从它所在的内存                                                     读取数据
}

可以在外部创建线程的实例,然后调用start()函数开始执行该线程,start()默认调用run()函数。当从run()函数返回后,线程便执行结束,就像应用程序离开main()函数一样。
QThread提供了一个terminate()函数,该函数可以在一个线程还在运行的时候就终止它的执行。我们不推荐使用terminate(),因为它可以随时停止线程的执行而不给这个线程自我清空的机会。一种更安全的方法是像上面那样使用stopped变量和stop()函数。
QThread会在开始、结束和终止时发射started()、finished()和terminated()信号(区别:terminate()函数),可以使用isFinished()和isRunning()来查询线程的状态。可以使用wait()来阻塞,直到线程结束执行。
实例:

//创建线程
Thread threadA;    //创建线程实例
Thread threadB;

threadA.strat();     //开始线程,start()默认调用run()函数
threadA.stop();     //结束线程
threadA.wait();     //阻塞
  1. 同步线程

对于多线程应用程序,一个最基本的要求是能实现几个线程的同步执行。虽然使用线程的思想是多个线程可以尽可能地并发执行,但总有一些时刻一些线程必须停止来等待其他线程,例如,如果两个线程尝试同时访问相同的全局变量。Qt中的QMutex、QReadWriteLock、QSemaphore和QWaitCondition提供了同步线程的方法。
1)QMutex类提供了一个互斥量。
它提供了一种保护一个变量或者一段代码的方法,每次只让一个线程读取它。这个类提供了一个lock()函数来锁住互斥量(mutex),unlock()函数解锁互斥量。如果互斥量是解锁的,那么当前线程就立即占用并锁定它。否则,当前线程就阻塞,直到掌握这个互斥量的线程对它解锁为止。用法:

QMutex mutex;
mutex.lock();
mutex.unlock();

2)QReadWriteLock类提供了一个读-写锁。
与QMutex很相似,只不过它将对共享数据的访问区分为“读”访问与“写”访问,允许多个线程同时对数据进行“读”访问。在可能的情况下使用QReadWriteLock代替QMutex,可以提高多线程程序的并发度。
3)QSemaphore类提供了一个信号量。
QSemaphore类用于保护一定数量的相同资源。信号量(semaphore)是互斥量的另外一种泛化表现形式。通过acquire()函数获取一个资源,本信号量获取的资源将不能被其他的信号量获取,直到资源被release()函数释放。用法:

QSemaphore semaphore(1);
semaphore.acquire();
semaphore.release();

通过把1传递给构造函数,就告诉这个信号量它控制了一个单一的资源。使用信号量的优点是可以传递1以外的数字给构造函数,然后可以多次调用acquire()来获取大量的资源。
4)QWaitCondition即等待条件
它允许一个线程在一些条件满足时唤醒其他线程。它与互斥锁搭配使用,可以比只使用互斥锁提供更精确的控制。

以上的方法适用于多个线程访问相同的全局变量的情况。但是在一些多线程的应用程序中,需要一个在不同线程中保存不同数值的全局变量,这种变量通常称为线程本地存储。QThread<T>类提供了这样一种功能。

  1. 与主线程通信

当Qt应用程序开始执行的时候,只有主线程是在运行的。主线程创建QApplication或QCoreApplication对象,之后对创建的对象调用exec(),主线程进入事件循环状态。通过创建一些QThread子类的对象,主线程可以开始一些新的线程。如果这些新的线程之间需要进行通信,可以使用含有互斥量、读-写锁、信号或者循环等待条件的共享变量。但在这些技术中没有一个可以用来与主线程进行通信,因为他们会锁住事件循环并且会冻结用户界面。在次线程和主线程之间通信的一个解决方案是线程之间使用信号-槽连接。
实现次线程时要谨慎对待,因为必须使用互斥量来保护成员变量,而且必须使用一个等待条件以在适当的时候停止或触发线程。

跨线程的信号和槽:
可以通过向connect()函数传递附加的参数来指定关联类型。Qt支持几种信号和槽的关联机制:
Auto Connection(默认) 。如果信号发射和信号接收的对象在同一个线程,那么执行方式与Direct Connection相同。否则,执行方式与Queued Connection相同。
Direct Connection。信号发射后,槽立即被调用。槽在信号发送者的线程中执行,而接收者并非必须在同一个线程。
Queued Connection。控制权返回接收者线程的事件循环后才调用槽。槽在接收者的线程中被执行。
Blocking Queued Connection。槽的调用与Queued Connection相同,不同的是当前线程会阻塞直到槽返回。注意:使用这种方式关联在相同线程中的对象时会引起死锁。
Unique Connection。执行方式与Auto Connection相同,只不过关联必须是唯一的。

  1. 可重入与线程安全

线程安全(thread-safe)的函数:一个线程安全的函数可以被多个线程调用,即使它们使用了共享数据
可重入(reentrant)的函数:一个可重入的函数可以同时被多个线程调用,但是只能在每个调用使用自己的数据的情况下
(一个线程安全的函数总是可重入的,但一个可重入的函数不总是线程安全的)
线程安全的类:如果即使所有的线程使用一个类的相同实例,该类的成员函数也可以被多个线程安全的调用,那么这个类被称为线程安全的
可重入的类:如果每个线程使用一个类的不同实例,则该类的成员函数可以被多个线程安全的调用,那么这个类被称为可重入的

(注意:如果一个函数没有被标记为线程安全或者可重入的,则它不应被多个线程使用;如果一个类没有标记为线程安全的或者可重入的,则该类的一个特定的实例不应该被多个线程访问)

原子操作:就是一个不会被其他线程中断的操作

  1. QObjects的可重入性

QObjects是可重入的。它的大多数非GUI子类,例如:QTimer、QProcess等也都是可重入的。对于GUI类,尤其是QWidget及其所有子类,是不可重入的,它们只能在主线程中使用。QCoreApplication::exec()也必须在主线程中调用。
QObject可重入有3个约束条件:

  • QObject的子对象必须在创建它的父对象的线程中创建。这意味着,永远不要将QThread对象(this)作为在该线程中创建的对象的父对象(因为QThread对象本身是在其他线程中创建的)
  • 事件驱动对象只能在单一线程中使用。这意味着,不能在对象所在的线程QObject::thread()以外的其他线程中启动一个定时器。
  • 必须确保删除QThread对象以前删除在该线程中创建的所有对象,可以通过在run()函数中的栈上创建对象来保证这一点。
  1. 每个线程的事件循环

每一个线程都可以有它自己的事件循环。
初始化线程使用QCoreApplication::exec()来开启它的事件循环(对于独立的对话框界面程序也可以使用QDialog::exec()开启事件循环);其他的线程可以使用QThread::exec()来开启一个事件循环。
在一个线程中使用事件循环,使得该线程可以使用那些需要事件循环的非GUI类(如:QTimer、QProcess),也使得该线程可以关联任意一个线程的信号到一个指定线程的槽。
如果在一个线程中创建了一个QObject对象,那么这个QObject对象被称为居住在该线程(live in the thread)。发往这个对象的事件由该线程的事件循环进行分派。如果没有运行事件循环,则事件将不会传送到对象。

上一篇:QT学习笔记(六)https://blog.csdn.net/weixin_44787158/article/details/99110713

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

QT学习笔记(七) 的相关文章

  • 向 Qt 样式表添加特异性时丢失样式

    这是我的代码 const QString STYLE SHEET background color rgba x x x y border 1px solid gray border radius 0px border top 1px so
  • 如何创建用于 QML 的通用对象模型?

    我想知道是否有任何宏或方法如何将 Qt 模型注册为 QObject 的属性 例如 我有AnimalModel http doc qt io qt 5 qtquick modelviewsdata cppmodels html qabstra
  • 如何在 Qt 中以编程方式制作一条水平线

    我想弄清楚如何在 Qt 中制作一条水平线 这很容易在设计器中创建 但我想以编程方式创建一个 我已经做了一些谷歌搜索并查看了 ui 文件中的 xml 但无法弄清楚任何内容 ui 文件中的 xml 如下所示
  • 如何获取 QTableView 的标题列表?

    我有一个QTableView我的对话框中的对象 我需要访问该表的水平标题并将它们放入QStringList object 尽管进行了大量搜索 但我在 Qt 文档中找不到如何获取此标头列表 编辑 我发现的最接近的地方是this https w
  • 使用 QtWebEngine 将 C++ 对象暴露给 Qt 中的 Javascript

    使用 QtWebkit 可以通过以下方式将 C 对象公开给 JavascriptQWebFrame addToJavaScriptWindowObject如中所述https stackoverflow com a 20685002 5959
  • 将 gnuplot 嵌入现有 QtWidget 中

    我正在用 C 创建一个 伪 实时绘图应用程序 使用 gnuplot 作为绘图后端 我的要求之一是绘图必须位于现有窗口内 而不是有一个单独的绘图窗口 gnuplot 默认为 Gnuplot 有一个选项可以指定 Qt 小部件 ID 这似乎适合我
  • Qt - 设置不可编辑的QComboBox的显示文本

    我想将 QComboBox 的文本设置为某些自定义文本 不在 QComboBox 的列表中 而不将此文本添加为 QComboBox 的项目 此行为可以在可编辑的 QComboBox 上实现QComboBox setEditText cons
  • Qt moc 在头文件中实现?

    是否可以告诉 Qt MOC 我想声明该类并在单个文件中实现它 而不是将它们拆分为 h 和 cpp 文件 如果要在 cpp 文件中声明并实现 QObject 子类 则必须手动包含 moc 文件 例如 文件main cpp struct Sub
  • 如何将 zlib 添加到现有的 qt 安装中

    如何将 zlib 添加到 Qt 的现有安装中 我对此很陌生 所以请给我详细的描述 提前感谢您的帮助 zlib 包含在 Qt 核心库中 如果你想在 Qt 程序中使用 zlib 函数 你只需要包含 src 3rdparty zlib 中的 zl
  • 如何消除 QTableWidget 中的空白?

    How do I get rid of the whitespace in my application 我想摆脱 QTableWidget 中的空白 蓝色箭头 我该怎么做 这是我的应用程序的代码 gridLayout QGridLayou
  • QWidget::showMinimized() 不起作用

    在 Ubuntu 13 04 上 如果使用QWidget showMinimized 为了最小化窗口 我发现通过单击系统任务栏上的应用程序图标恢复它后 调用QWidget showMinimized 无法工作 connect minimum
  • 使用 Qt 的网络服务

    我正在寻找使用 Qt 服务器端 实现 Web 服务的代码 如果您有任何信息 我将不胜感激 Regards 您可以使用libqxt http libqxt bitbucket org doc 0 6 qxtweb html实现服务器端Web服
  • 当从 html 文件读取 Unicode 内容时,为什么 Unicode 字体在 QTextBrowser 中无法正确显示?

    我正在读一本html文件 该文件基本上包含Unicode案文如下 b akko sati kru akkh ti khy abbahati b h b But the QText浏览器不解释Unicode字体 所以QText浏览器显示如下
  • QFileInfo::isWritable() 在 Windows 7 上具有完全权限时返回 false

    QFile file filePath QFileInfo fileInfo file file open QIODevice ReadWrite or WriteOnly if fileInfo isWritable Log error
  • 扩展 TabViewStyle styleData

    我目前正在尝试找到一种更好的方法来执行此操作 将图标添加到选项卡 现在 我正在放弃 styleData title 以包含图标源 但如果能够扩展 styleData 就更好了 这样我就可以包含其他自定义属性 这是我当前的黑客 Tab tit
  • Qt 图表和数据可视化小部件

    我已经安装了 Qt 5 7 来尝试 Qt 图表和 Qt 数据可视化 但我在 Qt Designer 和 Qt Creator 中都找不到新的小部件 有什么建议我应该做什么才能让新的小部件出现在设计器中 我今天遇到了完全相同的问题 默认情况下
  • 如何从 Qt 应用程序通过 ODBC 连接到 MySQL 数据库?

    我有一个新安装的 MySQL 服务器 它监听 localhost 3306 从 Qt 应用程序连接到它的正确方法是什么 原来我需要将MySQL添加到ODBC数据源 我在遵循这个视频教程后做到了这一点 https youtu be K3GZi
  • wkhtmltopdf 修补了 qt 吗?

    我正在尝试将多个 URL 转换为 PDF 但是 当我编译 wkhtmltopdf 或运行时apt get install wkhtmltopdf并尝试一下 它说 错误 此版本的 wkhtmltopdf 是针对未修补的 QT 版本构建的 并且
  • Qt 编译器标志顺序

    我的目标是消除某些类型的编译器警告 我发现可以通过在 pro 文件中添加编译器标志来做到这一点 QMAKE CXXFLAGS Wno unused variable Wno reorder 问题是它们被添加在 Qt 构建系统生成的标志之前
  • 将 C++ 代码(本机客户端)移植到浏览器(Web 应用程序)

    我有一个使用 Qt creator SDK 编写的 C 模块 我想将此代码移植到任何网页上运行 而不会对最终用户损害源代码 用户应该能够在任何浏览器 Chrome Firefox Safari Explorer 上看到此模块的输出 而无需安

随机推荐

  • Android平台生成二维码(by google.zxing)

    查了大部分的资料 发现android平台下生成二维码的例子都是使用谷歌的zxing类 因此仿照某一个帖子编写了一个demo进行测试 仿照的帖子 https blog csdn net myname kk article details 77
  • 使用 Hexo 搭建静态个人博客与绑定个人域名

    1 安装Git 下载并安装Git 可以选择淘宝 Git for Windows 镜像 https npm taobao org mirrors git for windows 2 安装Node js 下载安装Node js Node js
  • SpringMVC关于Validform实时校验身份证的作为账户的问题

    此地址上有相关案例 http validform rjboy cn 看不懂别怪我 前端代码 例如 div class f fl item ifo item sfz div
  • C#知识结构

    对于一个工作多年的程序员而言 接口 反射 索引器 事件 委托这些耳熟能详的词汇 提起来别说多简单了 但是让老司机坐在那一个人拿起一支笔 把脑海中对C 知识结构进行梳理一下 大抵是写不了多内容的 原因是什么呢 是遗忘 当然不是 每天面对代码的
  • mkdir函数-linux

    mkdir函数 头文件库 include
  • Heron 编译错误:no such package ‘@org_apache_thrift_libthrift//jar’

    错误 ERROR heron heron metricsmgr src java BUILD 5 1 no such package org apache thrift libthrift jar Failed to fetch Maven
  • The 19th ZCPC -G. Easy Glide

    Grammy is playing a boring racing game named Easy Gliding The game s main content is to reach the destination as fast as
  • 安全工具杂烩

    20201103 本来想单独列出来一个文章来记录每个工具 但是发现并没有那么多精力 这里仅仅记录一下看到的一些不错的工具 sdnewhop grinder 据其描述 这个是一个通过shodan或者censys来获取主机信息的工具 是不是跟一
  • 阿里云服务器一直提示安全事件如何解决

    介绍 这几天一直收到阿里云官方的短信和邮箱提示阿里云安全事件提醒 阿里云的官方的客服也打电话询问过我需不需要帮助 由于我的阿里云服务器没有用于商业用途 只是学习的时候使用 所有也就决定自己解决了 影响 由于最近比较忙 就没有怎么注意阿里云短
  • 433MHz工业级无线数传通信模块

    433MHz工业级无线数传通信模块 无线RS232 RS485透明传输 距离1 3000米 DTD465系列工业无线数传模块采用最先进的电子和无线通信技术 能为众多的工业与应用提供高性能 中等距离和可靠数据传输的低成本解决方案 它的工业级电
  • 计算机date时间和‘千年虫事件’

    目录 一 千年虫事件 1 千年虫事件 名词解析 2 应对2000年计算机问题的解决方法 二 Unix Linux 2038问题 Linux系统的几种时间 1 时间戳 date 2 UTC时间和本地时间 timedatectl 3 避免因时间
  • 日精注塑机联网

    不改造程序的话 日精支持输出CSV和txt数据作为其他软件的接口 改造后可以支持63协议 在软件层面日精也有专用的软件 可以看到其实设备厂家提供的软件功能已经非常丰富了 但这类软件最大的缺点是只能自己家的机器使用 要想其他家也兼容进来 既要
  • 【星海随笔】计组数学小课堂

    计算机组成原理 https www bilibili com video BV1ps4y1d73V p 8 16的负一次方既为1 16 16 1 16进制转换为10进制 例如 5 8 5 16 1 8 16 1 十进制转N进制 则除以N 然
  • Transformers中文本生成方法model.generate()参数解释

    本博客仅作为记录 参考 LLM 大语言模型 解码时是怎么生成文本的 爱码网
  • python字符串中所有符合条件的索引

    使用re库中的finditer import re s 1111ah11111ah test re finditer ah s print i for i in test
  • mvp关联activity生命周期_Android MVP架构从入门到精通-真枪实弹

    Android MVP架构从入门到精通 真枪实弹 一 前言 你是否遇到过Activity Fragment中成百上千行代码 完全无法维护 看着头疼 你是否遇到过因后台接口还未写而你不能先写代码逻辑的情况 你是否遇到过用MVC架构写的项目进行
  • VMware Workstation 16 Player 安装Centos 7

    环境准备 VMware Workstation 16 Player 官方下载 https www vmware com products workstation player workstation player evaluation ht
  • Cesium 源码解析 Model(一)

    Cesium中对于3DTiles会解析成Model 特别是3DTile中的B3DM 过程主要是对gltf在Cesium中是如何解析并生成绘制命令的 content model new Model gltf gltfView gltf数据 c
  • 全球数字治理白皮书 附下载

    当今世界 科技革命和产业变革日新月异 数字经济蓬勃发展 深刻改变着人类生产生活方式 对各国经济社会发展 全球治理体系 人类文明进程影响深远 在经济全球化遭遇逆流 保护主义 单边主 义上升的背景下 数字化驱动的新一轮全球化仍蓬勃发展 已成为助
  • QT学习笔记(七)

    第12章 输入与输出 Qt提供了读写字节块的设备类QIODevice QIODevice类是抽象的 无法被实例化 一般是使用它的子类 它包括如下子类 其中 QProcess QTcpSocket QUdpSocket QSslSocket都