QT 에서 하드웨어 펌웨어 프로 토 콜 에 대한 테스트 소결 및 몇 개의 QT 가 직면 한 문제 해결

9607 단어 qtjson
더 읽 기
네트워크 udp 통신 을 기반 으로 하 는 펌웨어 프로 토 콜 을 테스트 하기 위해 QT 로 테스트 도 구 를 작성 합 니 다.그 사이 에 몇 가지 문제 에 부 딪 혀 하나씩 해결 되 었 다.여기 있 습 니 다.
1. 네트워크 프로 토 콜 을 기반 으로 하기 때문에 IP 를 가 져 와 UDP 데 이 터 를 편리 하 게 보 내 고 받 아야 합 니 다.다만 가상 랜 카드 등 으로 IP 를 선별 해 야 한다.
 
    QHostAddress addr;
    QList list = QNetworkInterface::allAddresses();
    foreach (addr, list)
    {
       if(addr.protocol() == QAbstractSocket::IPv4Protocol){
           if (addr.toString().contains("192.168")){
               address = QHostAddress(addr.toString());
           }
       }
    }

명령 을 보 낼 때 방송 으로 보 내 면 어떤 카드 로 방송 을 할 지 고려 해 야 한다.그래서 ip 을 먼저 연결 해 야 합 니 다.
udpCMDSocket = new QUdpSocket(this);
udpCMDSocket->bind(QHostAddress(ip));
udpCMDSocket->writeDatagram(cmd.toLocal8Bit(), HubAddr, port);

 
2. 홈 UI 에서 while 순환 과 같은 높 은 점용 작업 이 임시로 필요 할 때 Qapplication:: processEvents () 를 사용 하여 인터페이스 에 있 는 처리 할 이벤트 에 응답 할 수 있 습 니 다.
 
while (!binFile.atEnd() {
                QByteArray byte = binFile.read(len);
                。。。
                sendCMD2Port(cmd, HubAddr, port);
                Sleep(interval);
                QApplication::processEvents();
            }

 3. 파일 을 열 고 경로 가 있 으 면 기 존 경 로 를 표시 합 니 다.
    QString tmpBinfile;
    if (BinFilePath.size() == 0)
        tmpBinfile = QFileDialog::getOpenFileName(this, tr("Open Bin File"), ".", tr("Bin File(*.bin)"));
    else
        tmpBinfile = QFileDialog::getOpenFileName(this, tr("Open Bin File"), BinFilePath, tr("Bin File(*.bin)"));

 4. 파일 읽 기, QListWidget 생 성, 정렬
bool CaseInsSort(const QString &info1, const QString &info2)
{
    return info1.toLower() < info2.toLower();
}

void loadCases()
{
    QFile file(filename);
    if (file.open(QFile::ReadWrite|QIODevice::Text)){
        QTextStream data(&file);
        QStringList fonts;
        QString line1;
        QString line2;
        while (!data.atEnd()){
            line1 = data.readLine();
            line2 = data.readLine();
            fonts<addItems(fonts);//      listwidget
        file.close();
    }
}

 5. QListWidgetItem 이름 변경
void renameCase()
{
    QListWidgetItem *caseItem = caseList->currentItem();
    if (caseItem){
        caseList->openPersistentEditor(caseItem);
    }
}

 6. UDP 명령 발송
void sendCMD2Port(QString cmd, QHostAddress HubAddr, int port)
{
    udpCMDSocket = new QUdpSocket(this);
    udpCMDSocket->writeDatagram(cmd.toLocal8Bit(), HubAddr, port);
    udpCMDSocket->close();
}

 7. 감청 스 레 드 는 주 스 레 드 에 독립 되 어 있 으 며 감청 데이터 처 리 를 모두 run 에 포함 합 니 다.
void listenPortThread::run()
{
    QUdpSocket udpListenSocket;
    bool result = udpListenSocket.bind(address, port,QUdpSocket::ShareAddress);//         
    if(!result)//      ,      
    {
        udpListenSocket.close();
        stop();
        return;
    }
    islisten = true;
    m_bStop = false;
    while(!m_bStop)
    {
        QByteArray array;
        QHostAddress address;
        quint16 port;
        if (islisten){
            while (udpListenSocket.hasPendingDatagrams()) {
                array.resize(udpListenSocket.pendingDatagramSize());//             
                udpListenSocket.readDatagram(array.data(),array.size(),&address,&port); //    
                QString str = array;
                。。。

 8. 1 차 타이머 로 제어 하여 시한 내 에 답장 을 받 았 는 지 판단 한다.시간 이 되면 timeout 함수 에서 판단 합 니 다.
       QTimer::singleShot(1500,this,SLOT(timeout()));
        sendCMD2Port(cmd, HubAddr, port);

 9. 받 은 제 이 슨 의 답장 을 분석 하고 키 워드 를 통 해 결 과 를 조회 합 니 다.
bool listenPortThread::parseJson(QByteArray array, QString *sendID, QString *result, QString key){
    QJsonParseError jsonError;
    QJsonDocument doucment = QJsonDocument::fromJson(array, &jsonError);  //     JSON   
    if (!doucment.isNull() && (jsonError.error == QJsonParseError::NoError)) {  //        
        if (doucment.isObject()) { // JSON      
            QJsonObject object = doucment.object();  //      
            if (!key.isEmpty() && object.contains(key)){
                QJsonValue Jvalue = object.value(key);
                if (Jvalue.isString()) { 
                    QString strvalue = Jvalue.toString();
                    *result = strvalue;
                }
            }

 10. 돌아 오 는 json 데 이 터 는 base 64 데 이 터 를 포함 하여 디 코딩 하고 float 로 복원 합 니 다.
QJsonValue Jdata = object1.value("data");
if (Jdata.isString()) {  
    QString strdata = Jdata.toString();
    QByteArray Hex = QByteArray::fromBase64(strdata.toLatin1()).toHex();
    QString calidata = "";
    for (int i=0; i<12; i++){
        QString str =Hex.mid(i*8+6,2)+Hex.mid(i*8+4,2)+Hex.mid(i*8+2,2)+Hex.mid(i*8,2); //     
        int iHex = str.toUInt(0,16);
        float fHex = *(float*)&iHex ;
        calidata += QString("%1, ").arg(fHex);
    }
    *result = calidata;
}

11. pro 파일 에서 VERSION 을 통 해 APP 버 전 번 호 를 설정 하고 프로그램 에서 APP 버 전 번 호 를 가 져 옵 니 다.
쓰다
In the YourApp.pro:
VERSION = 0.0.0.1
DEFINES += APP_VERSION=\\\"$$VERSION\\\"
In the main.cpp:
#include
QCoreApplication::setApplicationVersion(QString(APP_VERSION));
Wherever else in your sources, e.g. in the imaginary controller.cpp:
#include
QString yourAppVersion = QCoreApplication::applicationVersion();
 
12. 릴 리 스 버 전 프로그램 을 발표 하고 QT 에 필요 한 동적 라 이브 러 리 를 자동 으로 압축 합 니 다.
쓰다
Qt 공식 개발 환경 은 기본적으로 동적 링크 라 이브 러 리 방식 을 사용 합 니 다. 생 성 된 실행 가능 한 프로그램 을 발표 할 때 우 리 는 많은 동적 라 이브 러 리 를 복사 해 야 합 니 다. 만약 에 동적 라 이브 러 리 를 복사 하면 이것저것 잃 어 버 려 서 다른 컴퓨터 에서 프로그램 이 정상적으로 작 동 하지 못 할 수도 있 습 니 다.따라서 Qt 공식 개발 환경 에서 개발 자 들 이 대부분의 의존 라 이브 러 리 를 자동 으로 복사 할 수 있 도록 배치 도 구 를 가 져 왔 습 니 다.
Windows 개발 환경 에서 windeployqt 도구 (Qt 의 bin 디 렉 터 리 를 PATH 환경 에 추가 했다 면 명령 행 에서 windeployqt 호출 을 직접 사용 할 수 있 습 니 다.)우선 프로젝트 의 release 파일 에 있 는 실행 가능 한 파일 을 새 폴 더 에 복사 합 니 다. 예 를 들 어 procject. exe 는 Qt 자체 적 으로 필요 한 dll 파일 을 만 드 는 프로그램 windeployqt 로 필요 한 동적 라 이브 러 리 를 이 폴 더 에 복사 하고 명령 행 을 열 어 windeployqtproject. exe 를 입력 합 니 다. 이때 대부분의 dll 파일 은 자동 으로 복사 되 었 습 니 다.그러나 프로젝트 에 OpenCV, Chartdir 51 등 다른 SDK 를 사용 했다 면 필요 한 dll 을 수 동 으로 복사 해 야 합 니 다. 어떤 소프트웨어 가 더 필요 한 지 모 르 면 Dependency Walker 로 어떤 dll 파일 이 부족 한 지 확인 할 수 있 습 니 다.
메모: 발 표 된 응용 프로그램 이 Qt Quick Application 응용 프로그램 이 라면 명령 행 에 QML 설치 디 렉 터 리 를 추가 해 야 합 니 다.명령 의 D: \ \ Qt \ \ Qt 5.5.1 \ \ qml 는 qml 설치 디 렉 터 리 입 니 다. qml 설치 디 렉 터 리 로 바 꿔 주세요!!!!
windeployqt hello.exe --qmldir D:\Qt\Qt5.5.1\qml
그 다음 에 높 은 친 구 는 Enigma VirtualBox 소프트웨어 가상 화 도구 로 여러 개의 파일 을 응용 프로그램의 메 인 파일 에 밀봉 하여 단일 실행 파일 로 만 드 는 녹색 소프트웨어 를 만 들 수 있다.
 
13. 다 국어 버 전 만 들 기, QT linguist 로 언어 팩 만 들 기
쓰다
1. pro 파일 에 TRANSLATIONS + = filename 추가CN.ts
2. 도구 -- > 외부 -- > linguist -- > 업데이트 로 ts 파일 을 생 성 합 니 다.그러나 직접 사용 하면 qt 가 잘못 보고 할 수 있 습 니 다.VS 를 찾 을 환경 이 없어 서 요.그래서.
a. Create a translate.bat with the following single-line content:
"%programfiles(x86)%\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat" & lupdate.exe %1
and put it under %{CurrentProject:QT_INSTALL_BINS} (in my case C:\Qt\Qt5.9.1\5.9.1\msvc2017_64\bin). Make sure that the translate.bat contains the correct path to vcvars64.bat on your machine. You may as well put another version of vcvars if you need.
b. In Qt Creator select Tools/Options/Environment/External Tools and then Add Tool under Linguist category. Name it something like Create/Update TS files. Setup the fields for this entry as follows:
Executable: %{CurrentProject:QT_INSTALL_BINS}\translate.bat,
Arguments: %{CurrentProject:FilePath},
Working directory: %{CurrentProject:QT_INSTALL_BINS},
as shown here: External Tools, then apply the changes and close the Options window.
c. Go to Tools/External/Linguist, select Create/Update TS files and now it should do the job as usual.
3. linguist 에서 ts 파일 을 편집 하고 언어 번역 을 추가 합 니 다.
4. linguist 에서 직접 발표 하거나 qt 의 도구 -- > 외부 -- > linguist -- > 로 발표 하여 ts 파일 로 qm 파일 을 생 성 합 니 다.
5. 메 인 프로그램 에서
     QApplication app(argc, argv);
     QTranslator translator;
     bool ok=translator.load(":/qm/filename_CN.qm");
     app.installTranslator(&translator);
 
14. qt 전역 매크로 변수
쓰다
pro 에 다음 매크로 정의 코드 를 추가 합 니 다:
     DEFINES += HELLO=\\\"$$PWD/\\\"
     DEFINES += SUCCESS=\\\"string\\\"
. cpp 에서 테스트 코드 는 다음 과 같 습 니 다.
     #ifdef HELLO
     qDebug()<     #else
     qDebug()<     #endif

좋은 웹페이지 즐겨찾기