error: invalid use of incomplete type ‘class Ui::Task’ ../TodoApp/Task.cpp: In constructor ‘Task::Task(const QString&, QWidget*)’: ../TodoApp/Task.cpp:8:16: error: invalid use of incomplete type ‘class Ui::Task’
-
Hello,
I have been learning Qt with C++ for a very short time. I am reading a book called Mastering Qt5.
When I try to build appear the following messages:
error: invalid use of incomplete type ‘class Ui::Task’
error: incomplete type ‘QPushButton’ used in nested name specifier
Member access into incomplete type 'Ui::Task'The project consists of the following files:
The only class that generates errors is the class Task.cpp:
#include "Task.h" #include <QInputDialog> #include <QDebug> Task::Task(const QString& name, QWidget *parent) : QWidget(parent), ui(new Ui::Task) { ui->setupUi(this); setName(name); connect(ui->editButton, &QPushButton::clicked, this, &Task::rename); connect(ui->removeButton, &QPushButton::clicked, [this] { emit removed(this); }); connect(ui->checkbox, &QCheckBox::toggled, this, &Task::checked); } Task::~Task() { qDebug() << "~Task() called"; delete ui; } void Task::setName(const QString& name) { ui->checkbox->setText(name); } QString Task::name() const { return ui->checkbox->text(); } bool Task::isCompleted() const { return ui->checkbox->isChecked(); } void Task::rename() { bool ok; QString value = QInputDialog::getText(this, tr("Edit task"), tr("Task name"), QLineEdit::Normal, this->name(), &ok); if (ok && !value.isEmpty()) { setName(value); } } void Task::checked(bool checked) { QFont font(ui->checkbox->font()); font.setStrikeOut(checked); ui->checkbox->setFont(font); emit statusChanged(this); }
I am going to attach the rest of the files...
Task.h
#ifndef TASK_H #define TASK_H #include <QWidget> #include <QString> namespace Ui { class Task; } class Task : public QWidget { Q_OBJECT public: explicit Task(const QString& name, QWidget *parent = 0); ~Task(); void setName(const QString& name); QString name() const; bool isCompleted() const; public slots: void rename(); signals: void removed(Task* task); void statusChanged(Task* task); private slots: void checked(bool checked); private: Ui::Task *ui; }; #endif // TASK_H
Mainwindow.h
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include <QVector> #include "Task.h" QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } QT_END_NAMESPACE class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr); ~MainWindow(); public slots: void addTask(); private: Ui::MainWindow *ui; QVector<Task*> mTasks; }; #endif // MAINWINDOW_H
Mainwindow.cpp
#include "Mainwindow.h" #include "ui_Mainwindow.h" #include <QDebug> #include <QInputDialog> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow), mTasks() { ui->setupUi(this); connect(ui->addTaskButton, &QPushButton::clicked, this, &MainWindow::addTask); } MainWindow::~MainWindow() { delete ui; } void MainWindow::addTask(){ bool ok; QString name = QInputDialog::getText(this, tr("Add task"), tr("Task name"), QLineEdit::Normal, tr("Untitled task"), &ok); if (ok && !name.isEmpty()){ qDebug() << "Adding a new task"; Task* task = new Task(name); mTasks.append(task); ui->horizontalLayout->addWidget(task); } }
main.cpp
#include "Mainwindow.h" #include <QApplication> int main(int argc, char *argv[]) { QApplication a(argc, argv); MainWindow w; w.show(); return a.exec(); }
QT += core gui greaterThan(QT_MAJOR_VERSION, 4): QT += widgets CONFIG += c++14 # You can make your code fail to compile if it uses deprecated APIs. # In order to do so, uncomment the following line. #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 SOURCES += \ Task.cpp \ main.cpp \ Mainwindow.cpp HEADERS += \ Mainwindow.h \ Task.h FORMS += \ Mainwindow.ui \ Task.ui
MainWindow.ui
<?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"> <widget class="QWidget" name="horizontalLayoutWidget"> <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>801</width> <height>80</height> </rect> </property> <layout class="QHBoxLayout" name="horizontalLayout"> <item> <widget class="QLabel" name="statusLabel"> <property name="text"> <string>Status: 0 todo / 0 done</string> </property> </widget> </item> <item> <spacer name="horizontalSpacer"> <property name="orientation"> <enum>Qt::Horizontal</enum> </property> <property name="sizeHint" stdset="0"> <size> <width>40</width> <height>20</height> </size> </property> </spacer> </item> <item> <widget class="QPushButton" name="addTaskButton"> <property name="text"> <string>Add Task</string> </property> </widget> </item> </layout> </widget> </widget> <widget class="QMenuBar" name="menubar"> <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>800</width> <height>26</height> </rect> </property> </widget> <widget class="QStatusBar" name="statusbar"/> </widget> <resources/> <connections/> </ui>
Task.ui
<?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"> <class>centralwidget</class> <widget class="QWidget" name="centralwidget"> <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>738</width> <height>253</height> </rect> </property> <property name="windowTitle"> <string>Form</string> </property> <layout class="QVBoxLayout" name="verticalLayout"> <item> <layout class="QHBoxLayout" name="horizontalLayout"> <item> <widget class="QCheckBox" name="checkbox"> <property name="text"> <string>Buy Milk</string> </property> </widget> </item> <item> <spacer name="horizontalSpacer"> <property name="orientation"> <enum>Qt::Horizontal</enum> </property> <property name="sizeHint" stdset="0"> <size> <width>40</width> <height>20</height> </size> </property> </spacer> </item> <item> <widget class="QPushButton" name="editButton"> <property name="text"> <string>Edit</string> </property> </widget> </item> <item> <widget class="QPushButton" name="removeButton"> <property name="text"> <string>Remove</string> </property> </widget> </item> </layout> </item> </layout> </widget> <resources/> <connections/> </ui>
Thanks in Advance
-
TL;DR; Add
#include "ui_Task.h"
in your Task.cpp file.Longer explanation - the
uic
tool takes the Task.ui file and generates ui_Task.h header, which contains the definition for theUi::Task
class. This header is to be included in your Task.cpp file so that you can use it to initialize your ui by first creating an instance of that class (it's thenew Ui::Task
line that gives you the error about incomplete type) and then callingui->setupUi(this)
on it.Compare that with the wizard generated code - see the
#include "ui_Mainwindow.h"
line in the Mainwindow.cpp file.