devwiki:cpp_qt

Differences

This shows you the differences between two versions of the page.


Previous revision
devwiki:cpp_qt [2022/08/16 08:52] (current) – [Get Start on C++ Qt Combo Developemnt] ying
Line 1: Line 1:
 +====== Get Start on C++ Qt Combo Developemnt ======
 +
 +  * Cross platform GUI library + common base c++ library start steps:
 +    - download Qt library for host platform (QtCreator normally included)
 +      * offline installer link: (no need admin right, more like unpacker): https://www.qt.io/download-open-source/#section-2
 +        * note: the QtCreator is like a IDE with compiler built-in
 +      * update offline install, go Qt Creator: https://www.qt.io/offline-installers
 +        * now, when ask login, change clock to 2019, it wont ask for login
 +      * note: All you actually need is the Qt library, you can command line build cpp with the bin tool inside and your text editor.
 +    - read my guide note below 
 +      * **Important Note: __to better learning Qt, I am not using the Designer UI builder to create the .ui file, and instead I use C++ code to create UI element for better learning and understanding__**
 +
 +
 +  * tutorial list:
 +    * https://www.youtube.com/watch?v=6KtOzh0StTc&list=PL2D1942A4688E9D63
 +    * http://www.alternative-computer-programming.com/cpp-tutorial-001-qt-creator-introduction.html
 +    * https://www.devbean.net/category/qt-study-road-2/
 +====== Problems and Solutions ======
 +
 +__Problem: **QtCreator debug works but release not work**__
 +
 +  * Problem analysis:
 +    * normally when you doing PyQt like development, you have multiple Qt library in your environment path, and the release doesn't which Qt library to use when compile. in contrast, the debug uses library with "d" subfix, (like Qt5Cored.dll instead of Qt5Core.dll), thus debug works while release works
 +  * Solution:
 +    - under Tool menu > Option > Build and Run : Qt Version tab, make sure only your correct Qt library path is listed there. then save and close QtCreator
 +    - delete user config file (*.pro.user in same project folder) which still holds the old path value, to let QtCreator re-create correct config
 +    - then when you build release, it works fine
 +
 +__Problem: **QtCreator generated executable binary won't run on its own**__ 
 +
 +  * Problem analysis:
 +    * just like cx_Freeze python tool created standalone binary, it needs required Qt library next to the binary to use it (or in environment path); but for QtCreator case, it doesn't put a copy of required library component next to the binary
 +  * Solution:
 +    * copy common library component manually to its side, mostly Qt component and Target system component
 +      * target system component (example)
 +        * for Windows - MinGW compiler case: <code>
 +LIBWINPTHREAD-1.DLL
 +LIBGCC_S_DW2-1.DLL
 +LIBSTDC++-6.DLL
 +</code>
 +      * Qt component (example) <code>
 +QtCore (correct version)
 +QtGui (QtWidgets as well if version 5)
 +</code>
 +    * ref: 
 +      * http://doc.qt.io/qt-5/windows-deployment.html
 +      * http://wiki.qt.io/Deploy_an_Application_on_Windows
 +
 +
 +__Problem: **QtCreator build release error HostX86\x64\cl.exe" is used by qmake but HostX64\x64\cl.exe" is configured in the kit.**__
 +  * Solution: go Tool > Option > Kits : right side Kit option, make sure, if you build for 64bit, the compiler is using amd64 for both c and c++
 +
 +====== Get Start on Coding with C++ and Qt ======
 +
 +  * QtCreator and important directory location
 +    * Qt library location (Qt\version\compiler\bin): like \Qt\Qt5.7.1\5.7\mingw53_32\bin
 +      * qmake and other qt standalone tools are here
 +    * C++ compiler location (Qt\Tools\compiler\bin): like \Qt\Qt5.7.1\Tools\mingw530_32\bin
 +      * g++, make and other compiler related tools are here
 +    * QtCreator tool location (Qt\Tools\QtCreator\bin): like \Qt\Qt5.7.1\Tools\QtCreator\bin
 +
 +===== 1. Simple Start with QtCreator =====
 +
 +  - Create a new empty project, and delete everything in project list and only keep
 +    * ProjectName.pro : the project config file
 +    * Sources/main.cpp : the main program
 +  - simple code <code cpp main.cpp> 
 +#include "QApplication.h" // note: in for Qt stuff, you can also use #include <QApplication> format
 +#include "QLabel.h"
 +
 +//#include <QtWidgets> // note: use this in Qt5, <QtGui> in Qt4, with this, 
 +//with above line, you don't need include each single element, just like in Python
 +
 +int main(int argc, char *argv[])
 +{
 +    QApplication app(argc, argv);
 +    QLabel *info_label = new QLabel("Hello Qt!");
 +    info_label->show();
 +    return app.exec();
 +}
 +</code>
 +  - change Left panel : Build : into Release mode; that way, your output Executable binary should be only 10kb instead of 500kb big size. since Debug build mode will create bigger output.
 +  - after output binary, if you want to pass to your friend, you need put extra library next to it to run it standalone. (as mentioned in above "Problem and Solution" part)
 +
 +===== 1.1 Concept of Static and Dynamic linking =====
 +
 +  * static linked output binary means all extra library files is combined inside, no need put those library next to it when passing around; of course, the result binary will be big as well.
 +  * dynamic linked output binary means all extra library used in the binary will not be combined inside, and you need to put other library files next by or in system environment path.
 +    * For example, the default QtCreator output is dynamic linked.
 +
 +  * if you use g++ compile out (it can compile c and c++ and same flags), you may need to put "libwinpthread-1", and "libgcc_s_dw2-1" library file next to it for both compile and dynamic link<code bash>g++ -o Pure PureSrc.cpp</code>
 +  * static link output with g++ <code bash>g++ -o PureStatic -static PureSrc.cpp</code>
 +  * if you think the binary too big, optimize size flag <code bash>g++ -o PureStaticSmall -s -Os -static PureSrc.cpp</code>
 +
 +====== 2. Work like PyQt/PySide ======
 +
 +  * While python code is dynamically link to find those PyQt/PySide library files (so called Python module)
 +  * The C++ code is also dynamically link to Qt and System library nearby or in environment path
 +
 +**Python Example vs C++ Example**
 +  * Python file structure:
 +    * MyBox.py: contains GUI code and main function code
 +  * C++ file structure:
 +    * main.cpp: main function code
 +    * mybox.cpp: contains GUI code (which also can be combined into main.cpp)
 +    * mybox.h: contains internal variable, functions names 
 +
 +  * main difference based on code below
 +    * Python can just link to function to button
 +    * C++ need you to clearly state slot function in the .h file
 +  * in addition:
 +    * C++ need clearly state all public/private functions/property(pointer) and signal/slots in .h file
 +
 +  * source code 
 + 
 +| <code python MyBox.py>
 +from PyQt4 import QtGui, QtCore
 +import sys
 +
 +class MyBox(QtGui.QMainWindow):
 +
 +    def __init__(self, parent=None):
 +        QtGui.QMainWindow.__init__(self, parent)
 +        
 +        main_widget = QtGui.QWidget()
 +        self.setCentralWidget(main_widget)
 +        self.setWindowTitle("C++ Welcome!")
 +
 +        main_layout = QtGui.QHBoxLayout()
 +        main_widget.setLayout(main_layout)
 +
 +        info_label = QtGui.QLabel("Hello Qt!")
 +        quit_btn = QtGui.QPushButton("Click Me!")
 +        cust_btn = QtGui.QPushButton("Custom Print!")
 +        main_layout.addWidget(info_label)
 +        main_layout.addWidget(quit_btn)
 +        main_layout.addWidget(cust_btn)
 +
 +        # connection
 +        QtCore.QObject.connect( quit_btn, QtCore.SIGNAL("clicked()"), self.close )
 +        QtCore.QObject.connect( cust_btn, QtCore.SIGNAL("clicked()"), self.cust_action )
 +
 +    def cust_action(self):
 +        print("Hello C++ from Python")
 +
 +def main():
 +    app = QtGui.QApplication(sys.argv)
 +    mybox = MyBox()
 +    mybox.show()
 +    sys.exit(app.exec_())
 +
 +if __name__ == "__main__":
 +    main()
 +</code> | <code cpp mybox.cpp>
 +#include <QtWidgets>
 +#include "mybox.h"
 +
 +MyBox::MyBox(QWidget *parent)
 +    : QMainWindow(parent)
 +{
 +    QWidget *main_widget = new QWidget;
 +    this->setCentralWidget(main_widget);
 +    this->setWindowTitle("Python Welcome!");
 +
 +    QHBoxLayout *main_layout = new QHBoxLayout;
 +    main_widget->setLayout(main_layout);
 +
 +    QLabel *info_label = new QLabel("Hello Qt!");
 +    QPushButton *quit_btn = new QPushButton("Click Me!");
 +    QPushButton *cust_btn = new QPushButton("Custom Print!");
 +    main_layout->addWidget(info_label);
 +    main_layout->addWidget(quit_btn);
 +    main_layout->addWidget(cust_btn);
 +
 +    // connection
 +    QObject::connect(quit_btn, SIGNAL(clicked()), this, SLOT(close()));
 +    QObject::connect(cust_btn, SIGNAL(clicked()), this, SLOT(cust_action()));
 +
 +}
 +
 +MyBox::~MyBox()
 +{
 +
 +}
 +
 +void MyBox::cust_action(){
 +    qDebug() << "Hello C++";
 +}
 +</code> \\ <code cpp main.cpp>
 +#include "mybox.h"
 +#include <QApplication>
 +
 +int main(int argc, char *argv[])
 +{
 +    QApplication app(argc, argv);
 +    MyBox mybox;
 +    mybox.show();
 +
 +    return app.exec();
 +}
 +</code> \\ <code cpp mybox.h>
 +#ifndef MYBOX_H
 +#define MYBOX_H
 +
 +#include <QMainWindow>
 +
 +class MyBox : public QMainWindow
 +{
 +    Q_OBJECT
 +
 +public:
 +    MyBox(QWidget *parent = 0);
 +    ~MyBox();
 +
 +public slots:
 +    void cust_action();
 +};
 +
 +#endif // MYBOX_H
 +</code> |
 +
 +
 +====== 3. Manual and Portable Workflow with only Qt C++ Library and C++ Compiler ======
 +
 +**Intro to Portable**
 +  * QtCreator is a IDE with everything set ready for you, but if you want to go commandline and portable with only things needed, this section is for you.
 +
 +**Tools You Need**
 +  * as you read above, you only need Qt C++ library and C++ compiler to get everything from source to build
 +    - Qt C++ library and Qt Make tool for compiler config
 +      * (located at "Qt\version\compiler\bin": like \Qt\Qt5.7.1\5.7\mingw53_32\bin)
 +    - C++ make tool and C++ compiler
 +      * (located at "Qt\Tools\compiler\bin": like \Qt\Qt5.7.1\Tools\mingw530_32\bin)
 +
 +**Files You need**
 +  * .cpp files and .h files
 +  * .pro file <code cpp example.pro>
 +QT += core gui
 +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
 +
 +TEMPLATE = app
 +TARGET = MyBox
 +INCLUDEPATH += .
 +
 +# Input
 +HEADERS += mybox.h
 +SOURCES += main.cpp mybox.cpp
 +</code>
 +
 +**Environment setting You Need**
 +  * as you know, the default system environment Path is flooded with all kinds of application path and library path, most likely if you have Qt for Python as well, and all that unnecessary and likely duplicated library in the Path will mess up the command-line tools for its locations. (like search path)
 +    * ref: 
 +      * https://csl.name/post/qt-gcc/
 +      * https://wiki.qt.io/Getting_Started_on_the_Commandline
 +
 +  * run all the commands in a clean shell,
 +    * **windows example**, Only with 
 +      - Windows default **System path**
 +      - Your **Qt Path** and **Compiler Path** 
 +      - sample bat code to automate (**change ProjectName.bat to the same as your .pro filename**) <code dos ProjectName.bat>
 +set PATH=C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;
 +set PATH=%PATH%;D:\z_sys\App_Dev\Qt\Qt5.7.1\5.7\mingw53_32\bin;
 +set PATH=%PATH%;D:\z_sys\App_Dev\Qt\Qt5.7.1\Tools\mingw530_32\bin;
 +qmake %~n0.pro
 +mingw32-make
 +
 +pause
 +</code>
 +
 +**Check and Test Build result in release folder**
 +
 +  * as mentioned in above Problem and Solution section, you need those dynamically linked library to run the result binary executable.
 +  * instead of copying those linked file to every build folder, you can copy them to a common test folder, and add the folder in a custom test environment with command-line,
 +    * a example for windows platform (change AppName to your binary filename, and the "_Library_Qt" custom folder contains the common 5-6 library files mentioned before) <code dos AppName.bat>
 +set PATH=D:\Dev\CPP_Qt\_Library_Qt;%PATH%
 +%~n0.exe
 +</code>