QT5开发笔记(十二)--文件及磁盘操作


相关类说明:
QT提供了QFile类用于进行文件操作的读写接口,可以读写文本文件、二进制文件等,
文本文件用QTextStream;
二进制文件用QDataStream;
目录文件用QDir类;
文件信息采用QFileInfo;
监视文件和目录变化使用QFileSystemWatcher;
临时文件使用QTempporaryFile类。


示例文件:

QFile file("./rain.wav");
if(!file.open(QIODevice::ReadWrite))
{
    return;    // 打开文件失败
}

// 创建读写二进制文件流
QDataStream *inhnld= new QDataStream(&file);
// 读二进制数据
ret  = inhnld->readRawData(buff, 1024);

// 关闭文件
file.close();

打开文件对话框:

/// 多种文件类型用;;分割
QString filename = QFileDialog::getOpenFileName(this, 
                    "打开视频",
                    QDir::homePath(),
                    tr("wmv(*.wmv|*.mp4);;AVI(*.avi);;MP4(*.mp4)"));

qDebug() << filename;

打开保存对话框:

/// 多种文件类型用;;分割
QString filename = QFileDialog::getSaveFileName(this, 
                    "打开视频",
                    QDir::homePath(),
                    tr("wmv(*.wmv|*.mp4);;AVI(*.avi);;MP4(*.mp4)"));

qDebug() << filename;

打开路径对话框:

QString path = QFileDialog::getExistingDirectory(this, "保存路径", QDir::homePath());


获取路径:

QString path = QFileInfo(filename).absolutePath();

获取文件名:

file_name = info.fileName();    
fileName = fileName.split(".",QString::SkipEmptyParts).at(0); /// 去除扩展名
file.suffix();    /// 扩展名

删除指定扩展名的文件:

QDir dir("./");
foreach(QFileInfo file, dir.entryInfoList())
{
    if(file.isFile() && file.suffix() == "png")
    {
        dir.remove(file.fileName());
    }
}

递归删除指定目录:

QDir dir("./png");
dir.removeRecursively();

获取应用程序的路径:

QString cfg_path = qApp->applicationDirPath();
QString app_file = qApp->applicationFilePath()

判断文件或目录是否存在:

QDir d;
if(d.exists(cfg_path))
{
}

QFileInfo f;
if(f.exists(file))
{
}

- 阅读全文 -

QT5开发笔记(十一)--USB相关



注册插拔事件: 基于WinAPI编程都差不多

DEV_BROADCAST_DEVICEINTERFACE DevInterface;
ZeroMemory(&DevInterface,sizeof(DEV_BROADCAST_DEVICEINTERFACE));
DevInterface.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
// 指定设备类型及GUID(重要)
DevInterface.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
DevInterface.dbcc_classguid  = {0x4D1E55B2,0xF16F,0x11CF,{0x88,0xCB,0x00,0x11,0x11,0x00,0x00,0x30}};
RegisterDeviceNotification((HANDLE)this->winId(),&DevInterface,DEVICE_NOTIFY_WINDOW_HANDLE);

classguid与devguid.h中定义的不一致:
HidD_GetGuid查出来的是:{0x4D1E55B2,0xF16F,0x11CF,{0x88,0xCB,0x00,0x11,0x11,0x00,0x00,0x30}};
另外查到的一个是:{0xa5dcbf10,0x6530,0x11d2,{0x90,0x1f,0x00,0xc0,0x4f,0xb9,0x51,0xed}};
HKEY_LOCAL_MACHINE-->SYSTEM-->CurrentControlSet-->DeviceClasses

重载nativeEvent函数:

bool MainWindow::nativeEvent(const QByteArray &eventType, void *message, long *result)
{
    MSG* msg = reinterpret_cast<MSG*>(message);
    int msgType = msg->message;
    (void)eventType;
    (void)result;
    if(msgType==WM_DEVICECHANGE)
    {
        // 设备变化
        PDEV_BROADCAST_HDR lpdb = (PDEV_BROADCAST_HDR)msg->lParam;
        switch (msg->wParam) {
        case DBT_DEVICEARRIVAL:    // 设备进场
            if(lpdb->dbch_devicetype == DBT_DEVTYP_VOLUME)
            {
                // 容量设备(U盘等)
                PDEV_BROADCAST_VOLUME lpdbv = (PDEV_BROADCAST_VOLUME)lpdb;
                if(lpdbv->dbcv_flags ==0)
                {
                    //QString USBDisk = QString(this->FirstDriveFromMask(lpdbv ->dbcv_unitmask));
                    //qDebug() << "USB_Arrived and The USBDisk is: "<<USBDisk ;    
                }
            }
            else if(lpdb->dbch_devicetype = DBT_DEVTYP_DEVICEINTERFACE)
            {
                // 设备接口(HID)
            }
            else
            {

            }
            break;

        case DBT_DEVICEREMOVECOMPLETE:    // 设备移除完成
            if(lpdb->dbch_devicetype == DBT_DEVTYP_VOLUME)
            {
            }
            else if(lpdb->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
            {
               //PDEV_BROADCAST_DEVICEINTERFACE pDevInf  = (PDEV_BROADCAST_DEVICEINTERFACE)lpdb;
               //QString strname = QString::fromWCharArray(pDevInf->dbcc_name,pDevInf->dbcc_size);
               qDebug() << "移除设备接口";
            }
            else
            {
            }
            break;
        }
    }
    return false;
}

- 阅读全文 -

QT5开发笔记(十)--数据库


操作系统: Windows10/raspbian
软件版本: Qt5.12
数 据 库: mariadb 10/sqlite
远程地址: 192.168.11.191


修改工程文件: .pro项目文件中添加

QT += sql

相关头文件:

#include <QSqlDatabase>
#include <QSqlQuery>
#include <QSqlError>

查看支持的数据库驱动:

QList<QString> list = QSqlDatabase::drivers();
foreach(QString str, list)
{
    qDebug() << str;
}

打开/创建本直数据库:

/// 打开数据库(如果数据库不存在,则先创建再打开)
QSqlDatabase db;
db = QSqlDatabase::addDatabase("QSQLITE");  /// 指定数据库类型
db.setDatabaseName(filename);               /// 指定数据名称
db.setUserName("user");                     /// 用户名:可选项,也可以在open时指定
db.setPassword("123456");                   /// 密码: 可选项
if (!db.open())
{
    qDebug() << "Error: 创建/打开数据库失败." << db.lastError();
}
else
{
    qDebug() << "创建/打开数据库成功." ;
}

执行SQL语句:

QSqlQuery query(db);

// 创建数据表
QString sql_str = "create table users(id int primary key, username varchar(20), password varchar(20))";
sql_query.prepare(sql_str);
if(!sql_query.exec())
{
    qDebug() << sql_query.lastError();
} 

// 插入操作(也可以直接调用query.exec时直接附带SQL语句)
query.exec(" insert into users (username,password) values('shower','555555')");

 // 查询操作
query.exec("select * from users");
while(query.next())
{
    /// 查询的结果要转换成对应的类型
    qDebug()<<query.value("username").toString()<<query.value("password").toString();
}

// 删除操作
query.exec("delete from users where username='shower'");

关闭数据库:

db.close();

QSqlTableModel模式: 待补充



连接远程MySQL数据库:

void connect_mysql()
{
    QSqlDatabase db=QSqlDatabase::addDatabase("QMYSQL");  // 数据库类型:MySQL
    db.setHostName("192.168.11.191");    // 连接数据库主机名
    db.setPort(3306);                    // 连接数据库端口号
    db.setDatabaseName("db_test");       // 连接数据库名
    db.setUserName("root");              // 数据库用户名
    db.setPassword("123456");            // 数据库密码
    db.open();
    if(!db.open())
    {
        qDebug()<<"connect to mysql error: "<<db.lastError().text();
        return ;
    }
    else
    {
        qDebug()<<"connect to mysql successful.";
    }
}

添加MySQL支持:
如果在运行时提示: QSqlDatabase: QMYSQL driver not loaded,原因是未能正确加载MySQL相关驱动API,需要添加相关支持。

Linux: 比较简单,直接安装相关软件即可

$ sudo apt-get install libqt5sql5-mysql

Windows 10: 将需要编译生成相关的库文件,复制至Qt5编译器的bin目录下。

下载安装MySQL客户端:

https://dev.mysql.com/downloads/file/?id=450611
https://cdn.mysql.com//archives/mysql-connector-c/mysql-connector-c-6.1.3-win32.zip
https://dev.mysql.com/get/Downloads/Connector-C++/mysql-connector-c++-8.0.23-win32.zip
https://cdn.mysql.com//Downloads/Connector-C++/mysql-connector-c++-8.0.23-winx64.zip

将解压后的libmysql.lib及libmysql.dll文件复制到编译器bin目录下:
Qt\Qt5.12.9\5.12.9\mingw73_32\bin


获取数据库中的表

QSqlQuery sql_query(db);
QStringList tables = db.tables();    // 表名列表
qDebug() << "tables.count = " << tables.count(); // 打印表的个数

查看数据表字段:

    QString str = "PRAGMA table_info(" + tableNmae + ")";
    sql_query.prepare(str);
    if (sql_query.exec())
    {
        while (sql_query.next())
        {
            qDebug() << QString("%1: 字段名称:%2 字段类型:%3").arg(sql_query.value(0).toString()).arg(sql_query.value(1).toString()).arg(sql_query.value(2).toString());
        }
    }

- 阅读全文 -

QT5开发笔记(九)--线程


新建基于QThread的类:

#include <QString>
#include <QThread>

class MyThread : public QThread
{
public:
    MyThread(QString s);
private:
    QString name;
protected:
    void run();
};

重载run函数:

void MyThread::run()
{
    int i = 0;
    while(1)
    {
        qDebug()<<name.toStdString().c_str()<<":"<<i++;
        sleep(1);    // 线程休眠
    }
}

创建线程:

MyThread *t1 = new MyThread("ThreadA");
MyThread *t2 = new MyThread("ThreadB");

线程启动:

t1->start();                                     // 默认优先级InheritPriority
t2->start(QThread::Priority::NormalPriority);    // 指定优先级

线程终止:

t1->terminate();

线程信号:

void started(QPrivateSignal);
void finished(QPrivateSignal);
connect(t1, SIGNAL(started()),  this, SLOT(on_thread_started()));
connect(t1, SIGNAL(finished()), this, SLOT(on_thread_finished()));

线程休眠: 由线程自己调用,不建议在主程序中调用(否则调用程序会阻塞)

sleep(5);        // 单位为秒
msleep(500);     // 毫秒级休眠
usleep(10000);   // 微

问题解决:

QThread: Destroyed while thread is still running

在析构函数中结束线程:

t1->terminate();

- 阅读全文 -

QT5开发笔记(八)--静态/动态链接库调用


显示调用动态库

#include <QLibrary>

// 定义函数指针
typedef char* (*pcfun)(void);

QLibrary dll("usbrd32.dll");   // 声明所用到的dll文件

// 加载动态库
if (dll.load())
{
    ui->textBrowser->append("load successful");
}
else
{
    ui->textBrowser->append("load failed");
}

// 通过函数名称载入函数
pcfun file_info =(pcfun)dll.resolve("file_info");
if (file_info)
{
     file_info();    // 执行函数
}
else
{
    ui->textBrowser->append("resolve failed");
}

显式调用仅需要usbrd32.dll一个文件复制到生成目录中即可;
显式调用需要显式的导出每个函数,使用起来太麻烦,所以还是用隐式调用。


动态链接库隐式调用: 隐式调用需要h文件及lib文件

将usbrd32.lib,usbrd32.h文件复制到工程源文件目录中;

将usbrd32.dll文件复制到生成目录;

修改工程文件(.pro),添加一行

# -l指定的库不带lib扩展名
# -L指定lib文件所在的目录
LIBS+= -L E:\code\qt\HelloWorld -lusbrd32

直接调用即可:

dll_version();

注意事项:

软件发布时,不会自动复制用户的dll文件,需要手动复制至发布目录中;
lib文件与VC格式相同,VC编译时自动生成的就可以直接用(与C++Builder不同);
头文件里要用extern "C"{}圈起来(也可以在文件中圈)


从动态链接库里导出lib文件: 需要VS支持(VS6)

导出函数列表:

dumpbin /exports usbrd32.dll > usbrd32.def

内容如下:

Microsoft (R) COFF Binary File Dumper Version 6.00.8168
Copyright (C) Microsoft Corp 1992-1998. All rights reserved.  

Dump of file usbrd32.dll

File Type: DLL

  Section contains the following exports for usbrd32.dll

           0 characteristics
    54D07173 time date stamp Tue Feb 03 14:57:55 2015
        0.00 version
           1 ordinal base
          61 number of functions
          61 number of names

    ordinal hint RVA      name

          1    0 00002720 active_card
          2    1 00001FE0 close_device
          3    2 00002230 connect_device
          此处省略干行 ......................

Summary

        3000 .data
        2000 .rdata
        1000 .reloc
        7000 .text

修改def文件如下:(建议用脚本修改)

LIBRARY export

EXPORTS
active_card        @1
close_device       @2
connect_device     @3

通过def文件生成lib文件:仅用于动态链接库的隐式调用

lib /def:usbrd32.def /machine:i386 /out:usbrd32.lib

创建C++静态库:
新建项目-->Library-->C++ Library
Details-->Type-->Statically Linked Library(静态链接库)

修改.h文件,在类中加入public方法,并在cpp文件中实现该方法;

#include "untitledlib.h"

Untitledlib::Untitledlib()
{
    // 构造函数在载入时自动调用
}
int Untitledlib::add(int x, int y)
{
    return x + y;
}

构建Release生成库文件libuntitledlib.a(生成的库文件自动添加了lib前缀


C++静态库调用:

添加静态库:
新建测试项目
修改.pro文件,添加内容:不带lib前缀

LIBS += -L $$PWD/  -luntitledlib

也可以通过添加库-->外部库的方法来添加。

调用:

Untitledlib lib;
qDebug("%d",lib->add(100,99));

注意事项: MinWG与MSVC创建的静态库,不能相互调用,否则会产生错误

error: undefined reference to `__imp__ZN7mysqlpp10ConnectionC1Eb'。 

- 阅读全文 -


Copyright©2024 春天花会开, All Rights Reserved. Email: webmaster@oroct.com