Mas Bagol
Mas Bagol

Reputation: 4627

How to do QtCreator's steps in compiling qt project manually?

I'm new in Qt and trying to do a text editor example from Qt 5. But, I'm doing that without QtCreator. Of course I have QtCreator installed, I just want to try doing that example without QtCreator. My steps in doing this are:

  1. Write main.cpp, notepad.cpp and notepad.h exactly like in the example. (Except for include preprocessor, I write the complete path like:

    #include <qt/QtWidgets/QMainWindow>
    

    not just:

    #include <QMainWindow>
    
  2. Create notepad.ui file with QtDesigner.

  3. Generate ui_notepad.h file with uic-qt5 notepad.ui > ui_notepad.h command.
  4. Generate notepad.pro file with qmake-qt5 -project command.
  5. Add these lines in notepad.pro file:

    QT += core gui
    greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
    
  6. Generate Makefile with qmake command.

  7. Do make command.

Those step is what I can understand on how QtCreator doing the task automatically. And then, make complaints about incomplete type and forward declaration. But, If I'm doing this with QtCreator, the project is compiled just fine.

What did I miss there?

These are the error messages that I get:

notepad.cpp: In constructor ‘Notepad::Notepad(QWidget*)’:
notepad.cpp:4:72: error: invalid use of incomplete type ‘class Ui::Notepad’
 Notepad::Notepad (QWidget* parent) : QMainWindow (parent), ui (new Ui::Notepad) {
                                                                    ^
In file included from notepad.cpp:1:0:
notepad.h:4:8: error: forward declaration of ‘class Ui::Notepad’
  class Notepad;
    ^
notepad.cpp:5:4: error: invalid use of incomplete type ‘class Ui::Notepad’
  ui->setupUi (this);
    ^
In file included from notepad.cpp:1:0:
notepad.h:4:8: error: forward declaration of ‘class Ui::Notepad’
  class Notepad;
    ^
notepad.cpp: In destructor ‘virtual Notepad::~Notepad()’:
notepad.cpp:9:9: warning: possible problem detected in invocation of delete operator: [-Wdelete-incomplete]
  delete ui;
     ^
notepad.cpp:9:9: warning: invalid use of incomplete type ‘class Ui::Notepad’
In file included from notepad.cpp:1:0:
notepad.h:4:8: warning: forward declaration of ‘class Ui::Notepad’
  class Notepad;
    ^
notepad.cpp:9:9: note: neither the destructor nor the class-specific operator delete will be called, even if they are declared when the class is defined
  delete ui;
     ^
Makefile:660: recipe for target 'notepad.o' failed
make: *** [notepad.o] Error 1

Update

ui_notepad.h file:

/********************************************************************************
** Form generated from reading UI file 'notepad.ui'
**
** Created by: Qt User Interface Compiler version 5.4.1
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/

#ifndef UI_NOTEPAD_H
#define UI_NOTEPAD_H

#include <QtCore/QVariant>
#include <QtWidgets/QAction>
#include <QtWidgets/QApplication>
#include <QtWidgets/QButtonGroup>
#include <QtWidgets/QHeaderView>
#include <QtWidgets/QMainWindow>
#include <QtWidgets/QMenuBar>
#include <QtWidgets/QPushButton>
#include <QtWidgets/QStatusBar>
#include <QtWidgets/QTextEdit>
#include <QtWidgets/QVBoxLayout>
#include <QtWidgets/QWidget>

QT_BEGIN_NAMESPACE

class Ui_MainWindow
{
public:
    QWidget *centralwidget;
    QVBoxLayout *verticalLayout_2;
    QVBoxLayout *verticalLayout;
    QTextEdit *textEdit;
    QPushButton *quitButton;
    QMenuBar *menubar;
    QStatusBar *statusbar;

    void setupUi(QMainWindow *MainWindow)
    {
    if (MainWindow->objectName().isEmpty())
        MainWindow->setObjectName(QStringLiteral("MainWindow"));
    MainWindow->resize(800, 600);
    centralwidget = new QWidget(MainWindow);
    centralwidget->setObjectName(QStringLiteral("centralwidget"));
    verticalLayout_2 = new QVBoxLayout(centralwidget);
    verticalLayout_2->setObjectName(QStringLiteral("verticalLayout_2"));
    verticalLayout = new QVBoxLayout();
    verticalLayout->setObjectName(QStringLiteral("verticalLayout"));
    textEdit = new QTextEdit(centralwidget);
    textEdit->setObjectName(QStringLiteral("textEdit"));

    verticalLayout->addWidget(textEdit);

    quitButton = new QPushButton(centralwidget);
    quitButton->setObjectName(QStringLiteral("quitButton"));

    verticalLayout->addWidget(quitButton);


    verticalLayout_2->addLayout(verticalLayout);

    MainWindow->setCentralWidget(centralwidget);
    textEdit->raise();
    quitButton->raise();
    menubar = new QMenuBar(MainWindow);
    menubar->setObjectName(QStringLiteral("menubar"));
    menubar->setGeometry(QRect(0, 0, 800, 27));
    MainWindow->setMenuBar(menubar);
    statusbar = new QStatusBar(MainWindow);
    statusbar->setObjectName(QStringLiteral("statusbar"));
    MainWindow->setStatusBar(statusbar);

    retranslateUi(MainWindow);

    QMetaObject::connectSlotsByName(MainWindow);
    } // setupUi

    void retranslateUi(QMainWindow *MainWindow)
    {
    MainWindow->setWindowTitle(QApplication::translate("MainWindow", "MainWindow", 0));
    quitButton->setText(QApplication::translate("MainWindow", "Quit", 0));
    } // retranslateUi

};

namespace Ui {
    class MainWindow: public Ui_MainWindow {};
} // namespace Ui

QT_END_NAMESPACE

#endif // UI_NOTEPAD_H

notepad.ui file:

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>800</width>
    <height>600</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <layout class="QVBoxLayout" name="verticalLayout_2">
    <item>
     <layout class="QVBoxLayout" name="verticalLayout">
      <item>
       <widget class="QTextEdit" name="textEdit"/>
      </item>
      <item>
       <widget class="QPushButton" name="quitButton">
    <property name="text">
     <string>Quit</string>
    </property>
       </widget>
      </item>
     </layout>
    </item>
   </layout>
   <zorder>textEdit</zorder>
   <zorder>quitButton</zorder>
  </widget>
  <widget class="QMenuBar" name="menubar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>800</width>
     <height>27</height>
    </rect>
   </property>
  </widget>
  <widget class="QStatusBar" name="statusbar"/>
 </widget>
 <resources/>
 <connections/>
</ui>

Upvotes: 1

Views: 369

Answers (1)

user2836797
user2836797

Reputation:

Classes namespaced in Ui:: are automatically generated by the Qt UIC metacompiler after compiling .ui files. Your code expects Ui::Notepad to be generated and automatically linked into the project with qmake/uic.

After looking at the XML of the .ui file that QtDesigner creates, you can see the following line:

<class>MainWindow</class>

That means that the class Ui::MainWindow is generated. If you wanted to generate Ui::Notepad instead, open the .ui form in QtDesigner and rename the top level widget from MainWindow to Notepad. Then Ui::Notepad would appear in your project.

It would cause the XML to look like <class>Notepad</class> which would make Ui::Notepad available in your code

Upvotes: 1

Related Questions