QT5开发笔记(七)--读写注册表及INI配置文件


INI文件读写操作:

# include <QSettings>

QString str;
// 打开INI配置文件(指定为IniFormat格式)
QSettings iniTest("E:\\test.ini",QSettings::IniFormat);

添加修改键值: 如果键值/节点不存在则添加,/后第一个值表示结点名称

iniTest.setValue("/IP/ipv4","192.168.10.150");
[IP]
ipv4=192.168.10.150

删除键值: 当结点下的最后一个键值对被删除后,结点也会被删除

iniTest.remove("/IP/ipv4");

读键值: 直接指定路径,如果不存在,则返回默认值(可省略)

iniTest.Value("/IP/ipv4", "Error").toString();

遍历读键值

// 获取节点列表
QStringList groupList = iniTest.childGroups();
    
// 遍历节点
foreach(QString group,groupList)
{
    iniTest.beginGroup(group);
    
    ui->textBrowser->append(group);
    
    // 获取当前结点下的键值列表
    QStringList keyList = iniTest.childKeys();
    // 遍历列表
    foreach(QString key,keyList)
    {
        // 读取键值
        str = key + "="+tr(iniTest.value(key).toString().toStdString().c_str());
        ui->textBrowser->append(str);
    }
    iniTest.endGroup();
}

注册表操作

打开注册表(指定为NativeFormat格式)

QSettings reg("HKEY_LOCAL_MACHINE\\HARDWARE\\DEVICEMAP",QSettings::NativeFormat);

获取当前路径下的项目列表:

// 获取当前路径下的项目列表
QStringList groupsList=reg.childGroups();
// 遍历列表
foreach(QString group,groupsList)
{
    ui->comboBox->addItem(group);
    reg.beginGroup(group);            // 开始操作本项目(切换路径)
    // 在此插入其他操作
    reg.endGroup();                   // 离开当前项目,返回上级
}

获取当前路径下的键值列表:*

// 获取当前路径下的键值列表(不包含子项)
QStringList keyList = reg.childKeys();
// 获取当前路径下的键值列表(包含子项)
// QStringList keyList = reg.allKeys();

foreach(QString key,keyList)
{
    ui->textBrowser->append(key + " = " + reg.value(key).toString());
}

foreach(QString group,groupsList)
{
    ui->comboBox->addItem(group);
}

删除键值: 需要以管理员身份运行

reg.remove("Serial1");

注意事项:

QT5不支持带/的键名操作(可以读出键名,但不能通过键名取键值),需要通过WinAPI来实现;
只支持字符串,32bit及64bit类型的值,其他类型读出为空,WinAPI可以读出所有类型。

WinAPI示例:

#include <qt_windows.h>

QSettings reg("HKEY_LOCAL_MACHINE\\HARDWARE\\DEVICEMAP\\SERIALCOMM",QSettings::NativeFormat);

HKEY  hKey;
//打开启动项Key
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"HARDWARE\\DEVICEMAP\\SERIALCOMM", 0, KEY_READ, &hKey) != ERROR_SUCCESS)
{
    qDebug() << "windows api read reg failed!";
}
else{
    qDebug() << "windows api read reg success";
}

//for(int i = 0; i < reg.childKeys().size(); ++i)
//{
//    QString key = reg.childKeys().at(i);

QStringList keyList = reg.childKeys();
foreach(QString key , keyList)
{
    DWORD dwSize = 1024;      
    DWORD dwType = REG_DWORD;
    WCHAR buf[1024];
    
    QString backslash_key = key.replace(QChar('/'), QChar('\\'));
    //char * 转换为 wchar_t * 类型
    const wchar_t * w_key = reinterpret_cast<const wchar_t *>(backslash_key.utf16());

    DWORD dwRet  = RegQueryValueEx(hKey, w_key, NULL, &dwType, (LPBYTE)(&buf), &dwSize);

    if (ERROR_SUCCESS != dwRet)
    {
         qDebug() << "RegQueryValueEx failed " << dwRet;
         break;
    }
    else
    {
         if(dwType == REG_SZ)  //字符串类型
         {
              QString strMessage = QString::fromUtf16(reinterpret_cast<const ushort *>(buf), dwSize/2 - 1);
              qDebug() << "dwSize is: " << dwSize << "value is: " << strMessage;
         }

         else if(dwType == REG_BINARY)
         {
            qDebug() << "REG_BINARY dwSize is" << dwSize;
         }

         else if(dwType == REG_QWORD)
         {
             qDebug() << "REG_DWORD  value = " << reinterpret_cast<const qint32 *>(buf);
         }
         else if(dwType == REG_QWORD)
         {
             qDebug() << "REG_QWORD  value = " << reinterpret_cast<const qint64 *>(buf);
         }
         else
         {
             qDebug() << "dwType ==" << dwType << "dwSize = " << dwSize;
             // 通过dwSize获取数据长度,数据全在buf里
         }
    }
}

RegCloseKey(hKey);

1.reinterpret_cast<const qint32 > 用于强制转换,相当于(qint32*),但直接用指针强制转换的话,qt5编译器会抱怨。
2.部分文档要求在工程文件中加入LIBS += -lAdvapi32静态库,实际测试不加入也可以正常编译运行,如果有问题就加上去。
3.WinAPI会造成系统依赖,但是....., 除了Windows,还有谁会用到注册表呢?


- 阅读全文 -

QT5开发笔记(六)--串口通信


修改.pro工程文件,添加串口支持

QT += serialport

#include <QSerialPort>

QSerialPort *serial;
    
serial = new QSerialPort();
connect(serial, SIGNAL(readyRead()),this,SLOT(serial_received_data()));

打开/关闭串口

void MainWindow::on_SerialButton_clicked()
{
    if(serial->isOpen())
    {
       serial->close();
       ui->textBrowser->append("关闭" + serial->portName());
       ui->SerialButton->setText("打开串口");
    }
    else
    {
        serial->setPortName(ui->comboBox->currentText());   // 设置端口
        serial->setBaudRate(QSerialPort::Baud115200);       // 设置波特率
        serial->setDataBits(QSerialPort::Data8);            // 8位数据位
        serial->setFlowControl(QSerialPort::NoFlowControl); // 无流控制
        serial->setParity(QSerialPort::NoParity);           // 无校验位
        serial->setStopBits(QSerialPort::OneStop);          // 1位停止位
        if(serial->open(QIODevice::ReadWrite))
        {
            ui->textBrowser->append("打开" + serial->portName() + "成功");
            ui->SerialButton->setText("关闭串口");
        }
        else
        {
            ui->textBrowser->append("打开" + serial->portName() + "失败");
        }
    }
}

发送数据:

if(serial->isOpen())
{
    serial->write("Hello World\r\n", 12);
}

接收数据:

void MainWindow::serial_received_data()
{
    QByteArray bytes;
    bytes = serial->read(100);
    ui->textBrowser->append(bytes);
 }

查找可用串口列表:

#include <QSerialPortInfo>

foreach (QSerialPortInfo info, QSerialPortInfo::availablePorts())
{
    ui->comboBox->addItem(info.portName());
}

- 阅读全文 -

QT5开发笔记(五)--常见问题分析及解决办法


编译无问题,但在运行时显示No matching signal for xxx,而且并不影响运行结果。

QMetaObject::connectSlotsByName: No matching signal for on_tcp_disconnect()

原因分析:
Qt中按空间名称关联槽的方式进行关联,对应的函数必须写成“on_控件名信号名”的格式,
如果采用显式connect的方法将信号和槽关联,又将槽函数的名字起成了“on
控件名_信号名”的格式,
那么就会在运行时弹出找不到匹配信号的警告了!

修改方法:
1.直接无视,反正没有任何影响;
2.对于有强迫症的人,将手动关联的槽函数,不命名为on_控件名_信号名格式即可。


- 阅读全文 -

QT5开发笔记(四)--数据类型及转换


QString(Unicode-->GBK)

QByteArray bytes = ui->lineEdit->text().toLocal8Bit();
// bytes.data(), bytes.length()

数值转换成字符串:

QString str;

// 支持进制,浮点等
str.setNum(10);
str.setNum(10, 16)
str.setNum(99.99)

// 或者采用sprintf方法更为灵活
str.sprintf("%d", num);

字符串转换成数值:

QString str;

str = "123456";

str.toInt()

// 16进制转换
str.toInt(&bOK, 16)

str.toFloat();

- 阅读全文 -

QT5开发笔记(三)--网络编程


1.修改.pro文件,添加网络支持

QT += network

重要,否则编译出错


2.UDP通信

#include <QUdpSocket>

QUdpSocket *udp = new QUdpSocket();
// 绑定本地端口(可选项)
udp->bind(7777);
// 连接远程端口(配合write使用,一般不用)
udp->connectToHost("192.168.10.150",8888);
// 数据接收回调函数
connect(udp, SIGNAL(readyRead()),this, SLOT(UdpReceivedData()))

UDP发送:

// 指定目标地址及端口发送
QHostAddress addr = QHostAddress("192.168.10.150");
udp->writeDatagram("HelloWorld\r\n", 12, addr, 8888);

UDP接收:

void MainWindow::on_udp_received()
{
    char buff[1024];
    QHostAddress addr; // 发送方IP地址
    quint16 port;      // 发送方端口
    
    memset(buff,0,1024);
    udp->readDatagram(buff,1023,&addr,&port);

    QString str;
    QString ipstr;
    // 转换IP地址(addr。toString转换的结果有问题)
    ipstr.sprintf("%d.%d.%d.%d:%d",
                 (addr.toIPv4Address() >> 24)&0xFF,
                 (addr.toIPv4Address() >> 16)&0xFF,
                 (addr.toIPv4Address() >> 8)&0xFF,
                 (addr.toIPv4Address())&0xFF,
                 port);
    str  = "recv from " + ipstr + "\r\n";
    str += buff;
    ui->textBrowser->append(str);
}

3.TCP客户端:

#include <QTcpSocket>

QTcpSocket *tcp = new QTcpSocket();
// 数据接收信号
connect(tcp, SIGNAL(readyRead()),this,SLOT(on_tcp_received()));
// 连接断开信号
connect(tcp, SIGNAL(disconnected()),this,SLOT(on_tcp_disconnect()))
//  连接服务器
void MainWindow::on_pushButton2_clicked()
{
    tcp->connectToHost("192.168.10.150",9999);
}
// 断开连接
void MainWindow::on_pushButton3_clicked()
{
    tcp->disconnectFromHost();
}    
// 发送数据
void MainWindow::on_pushButton4_clicked()
{
    tcp->write("HelloWorld\r\n",12);
}

TCP数据接收:

void MainWindow::on_tcp_received()
{
    QByteArray bytes;
    bytes = tcp->read(1000);
    ui->textBrowser->append(bytes);

    //char rxbuff[1024];
    //int ret;
    //memset(rxbuff, 0, 1024);
    //ret = tcp->read(rxbuff, 1023);
    //if(ret > 0)
    //{
    //
    //}
}

// TCP断开连接槽函数
void MainWindow::on_tcp_disconnect()
{
    ui->textBrowser->append("disconnect");
}

4.TCP服务器:

#include <QTcpServer>
QTcpServer *server;
QTcpSocket *client;

server = new QTcpServer();
server->listen(QHostAddress::AnyIPv4, 6666);
connect(server, SIGNAL(newConnection()),this,SLOT(on_client_connected()));

客户端建立连接:

void MainWindow::on_client_connected()
{
    ui->textBrowser->append("client connected");
    client = server->nextPendingConnection();
    connect(client, SIGNAL(disconnected()), this, SLOT(on_client_disconnected()));
    connect(client, SIGNAL(readyRead()),this,SLOT(received_form_client()));

    ui->textBrowser->append(client->peerAddress().toString());
}

客户端断开连接:

void MainWindow::on_client_disconnected()
{
    ui->textBrowser->append("client disconnected");
    delete client;
}

接收到客户端数据:

void MainWindow::received_form_client()
{
    char rxbuf[1024];
    memset(rxbuf,0,1024);
    client->read(rxbuf, 1023);
    ui->textBrowser->append(rxbuf);
}

发送数据到客户端:

client->write("HelloWorld\r\n", 12);

- 阅读全文 -


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