Get Start on C++ Qt Combo Developemnt

  • Cross platform GUI library + common base c++ library start steps:
    1. 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
      • note: All you actually need is the Qt library, you can command line build cpp with the bin tool inside and your text editor.
    2. 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

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:
    1. 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
    2. delete user config file (*.pro.user in same project folder) which still holds the old path value, to let QtCreator re-create correct config
    3. 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:

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. 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
  2. simple code
    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();
    }
  3. 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.
  4. 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)
  • 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
    g++ -o Pure PureSrc.cpp
  • static link output with g++
    g++ -o PureStatic -static PureSrc.cpp
  • if you think the binary too big, optimize size flag
    g++ -o PureStaticSmall -s -Os -static PureSrc.cpp

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
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()
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++";
}


main.cpp
#include "mybox.h"
#include <QApplication>
 
int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    MyBox mybox;
    mybox.show();
 
    return app.exec();
}


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

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
    1. 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)
    2. 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
    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

Environment setting You Need

  • run all the commands in a clean shell,
    • windows example, Only with
      1. Windows default System path
      2. Your Qt Path and Compiler Path
      3. sample bat code to automate (change ProjectName.bat to the same as your .pro filename)
        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

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)
      AppName.bat
      set PATH=D:\Dev\CPP_Qt\_Library_Qt;%PATH%
      %~n0.exe