I am trying to write an application where I would have a generic dialog window and specific dialog windows that would inherit some basic functionalities from the generic one. I am not sure this is the best approach for this, but this is how I did it (The CGenericProject class was created from Dialog template in Qt Creator):
CGenericProject.h:
#include <QDialog>
namespace Ui {
class CGenericProject;
}
class CGenericProject : public QDialog
{
Q_OBJECT
public:
explicit CGenericProject(QWidget *parent = 0);
~CGenericProject();
protected:
Ui::CGenericProject *ui;
};
CGenericProject.cpp:
#include "cgenericproject.h"
#include "ui_cgenericproject.h"
CGenericProject::CGenericProject(QWidget *parent) :
QDialog(parent),
ui(new Ui::CGenericProject)
{
ui->setupUi(this);
}
CGenericProject::~CGenericProject()
{
delete ui;
}
CEisProject.h:
#include "cgenericproject.h"
class CEisProject : public CGenericProject
{
public:
CEisProject();
~CEisProject();
};
CEisProject.cpp:
#include "ceisproject.h"
CEisProject::CEisProject()
{
ui-> NO ACCESS
}
CEisProject::~CEisProject()
{
}
As you see in the CEisProject.cpp file, I have no access to the ui field inherited from CGenericProject, even though it is protected. I mean, I see ui itself, but I dont see its methods and members. Any other variable that I would define there, would be accessible. What's wrong? I would appreciate all help in this manner.
You have to add the line
#include "ui_cgenericproject.h"
to the CEisProject.cpp file.
The CGenericProject.h file is included in CEisProject.h, but CEisProject.h does not have access to CGenericProject.cpp. In the header of your base class you have a only forward declaration of Ui::CGenericProject, and you include its file in the .cpp. So CGenericProject.cpp knows the implementation of this class.
But CEisProject.cpp doesn't have access to that, so you have to include the file again in here.
NOTE
Your forward declaration is confusing, you should indent it properly. Also, add some comments to your code to add some clarity for who is reading it, you're using two different classes with the same name.
Related
I am a bit new to Qt C++ and I think there is a small thing I'm missing but can't figure what is it.
I am trying to make a simple Qt C++ application just to get familiar with it, but I face some problem, First, I have the votor class, which is the main application class, and another class which is called recorder, which will be used inside the main votor class. For simplicity, I omitted un-related parts,
Here are the files:
votor.h
#pragma once
#include <QtWidgets/QMainWindow>
#include "ui_votor.h"
#ifndef TSTRECORD_H
#define TSTRECORD_H
#endif
#include <QtCore/QVariant>
#include <QtWidgets/QApplication>
#include <QtWidgets/QMainWindow>
#include <QtWidgets/QMenuBar>
#include <QtWidgets/QPushButton>
#include <QtWidgets/QStatusBar>
#include <QtWidgets/QWidget>
#include "recorder.h"
class VOTor : public QMainWindow
{
Q_OBJECT
public:
VOTor(QWidget *parent = Q_NULLPTR);
recorder xs;
private:
Ui::VOTorClass ui;
};
votor.cpp
#include "votor.h"
VOTor::VOTor(QWidget *parent) : QMainWindow(parent), xs(parent)
{
ui.setupUi(this);
//xs = recorder();
}
recorder.h
#pragma once
#include <QDebug>
#include <QObject>
#include <QtCore/qbuffer.h>
#include <QtCore/qiodevice.h>
#include<QtMultimedia/qaudioformat.h>
#include<QtMultimedia/qaudiodeviceinfo.h>
#include<QtMultimedia/qaudioinput.h>
class recorder : public QObject
{
Q_OBJECT
public:
// recorder();
recorder(QObject *parent);
~recorder();
//Some functions related to recording omitted for more focus
private:
//omitted members for simplicity, just some integers, chars and qt objects not related to problem
recorder.cpp
#include "recorder.h"
recorder::recorder(QObject *parent) : QObject(parent)
{
//just initializing the omitted members normally
}
//recorder::recorder() {}
recorder::~recorder()
{
}
as you see, recorder object is a member inside votor class. Now, I need to call recorder constructor to initialize its parent. Now, I knew I can't just make (inside votor.h)
recorder xs(parent);
so,
1- is there a way I can call recorder constructor other than initialization list ?
I want another way as I was more convenient to use recorder xs(..) than initialization list, I feel (just feel) that using initialization list is heavy (not performance-wise but on readability ). I know also I can use dynamic allocation, but I don't want to use it without a good reason for.
2- I have decided to use initialization list to call recorder constructor and pass (Qobject* parent) to recorder. The code is built successfully, but when running, it gives access violation error which I can't figure why...
it gives:
"Access violation reading location 0x7C32F08D."
I think I am missing small thing.. I hope to know what is wrong.
Edit:
as #p-a-o-l-o suggested, the access violation was from the omitted code, So, I am posting it here as I don't know what is the problem in my code:
full version of recoder.h
class recorder : public QObject
{
Q_OBJECT
public:
recorder();
//recorder(QObject *parent);
~recorder();
void record();
void stop();
public slots:
void stateChanged(QAudio::State);
private:
unsigned char state;
QBuffer* voiceBuffer;
QAudioFormat* format;
QAudioDeviceInfo* info;
QAudioInput* audioIn;
unsigned char writeWav(QByteArray*);
};
and the part causes access violation according to debug mode, which is constructor of recorder class
recorder::recorder() : QObject(Q_NULLPTR)
{
state = 0;
voiceBuffer->open(QIODevice::WriteOnly);
format->setSampleRate(8000);
format->setChannelCount(1);
format->setSampleRate(16);
format->setByteOrder(QAudioFormat::LittleEndian);
format->setCodec("audio/pcm");
format->setSampleType(QAudioFormat::SignedInt);
*info = QAudioDeviceInfo::defaultInputDevice();
audioIn = &QAudioInput(*info, *format);
//audioIn->stateChanged.connect(stateChanged);
//connect(audioIn, &QAudioInput::stateChanged, stateChanged);
connect(audioIn, SIGNAL(stateChanged (QAudio::State) ), this, SLOT(stateChanged(QAudio::State)));
}
About question #1: as rightfully suggested in comments, a proper constructor for a QObject-derived class would have a nullptr default argument:
recorder(QObject *parent = Q_NULLPTR);
If you really need that parent object to initialize the other members in construction, you have no alternatives and must call that constructor, somehow.
Otherwise, have a no-arguments constructor and initialize the other members there:
recorder::recorder() : QObject(Q_NULLPTR)
{
//just initializing the omitted members normally
}
Such a constructor will be invoked automatically, no need of initialization list here.
If you still need a parent for the recorder object, give it one in the VOTor constructor:
VOTor::VOTor(QWidget *parent) : QMainWindow(parent)
{
ui.setupUi(this);
xs.setParent(parent);
}
About question #2: as far as I can see from the code you posted, the access violation have nothing to do with Qt parenting and must be related to the (omitted) code inside the recorder constructor.
Just to clear it out: parenting a member object is always safe, since it will go out of scope before ~QObject() gets called, so it will be removed from the children list before ~QObject() could possibly call delete on it.
Taking the OP code as an example, the sequence of destructors is the following:
~VOTor()
~recorder() ---> xs is removed from the children list
.
.
.
~QObject() ---> will call delete on all children, but ws is not in the list anymore
Qt documentation is quite clear about the order of construction/destruction of parents and children: in short, if the child is created on the stack everything will be fine until the child is created after the parent.
But, again, if the child happens to be a member of the parent class, it will be fine as well for the reasons mentioned above (even if its construction actually happens before its parent's).
In the code pieces below, there are //HERE tagged comments.
In this regions, you see the same namespace declarations. In the first declaration, ShapeChanging class is forward declared. And in the second part, ShapeChanging class is derived from another class. So, it is defined in a different form than its declaration form?
I did not know that language rule. Can anyone explain it?
First: Header file of my widget
#ifndef SHAPECHANGING_H
#define SHAPECHANGING_H
#include <QDialog>
//HERE
namespace Ui {
class ShapeChanging;
}
class ShapeChanging : public QDialog
{
Q_OBJECT
public:
explicit ShapeChanging(QWidget *parent = 0);
~ShapeChanging();
private:
Ui::ShapeChanging *ui;
};
#endif // SHAPECHANGING_H
Second: the file generated by uic
#ifndef UI_SHAPECHANGING_H
#define UI_SHAPECHANGING_H
#include <QtCore/QVariant>
...
QT_BEGIN_NAMESPACE
class Ui_ShapeChanging
{
public:
QVBoxLayout *verticalLayout_2;
QVBoxLayout *verticalLayout;
...
};
//HERE
namespace Ui {
class ShapeChanging: public Ui_ShapeChanging {};
} // namespace Ui
QT_END_NAMESPACE
#endif // UI_SHAPECHANGING_H
Thanks.
QT_BEGIN_NAMESPACE / QT_END_NAMESPACE is a macro that expands if Qt was compiled with custom namespace (which will not occur in case you downloaded it from Qt website). This option is useful if you are compiling Qt to be used with library that have name collisions with Qt - you can read more about it here: http://wiki.qt.io/Qt_In_Namespace.
For your second question, I think they just wanted to group all classes generated by UIC into single namespace (same thing is discussed here Qt Ui namespace). I'm not sure what is the rationale with two classes, maybe there are some historical reasons or it was easier to write generator template for it this way.
Only thing I can really thing about is that since Qt is been around forever it was also targeting compilers without proper namespace support so they wanted to have Ui namespace as optional thing that can be easily turned off.
This is about a Qt 5.3.2 project buildt using CMake.
I have designed a QMainWindow using the Qt Designer, leading
to main.ui.
CMakeLists.txt (the almost complete thing may be
found here where I already posted it for a different question:
Linking and UIC order in a CMake Qt project )
already takes care of calling UIC so I have my hands on ui_main.h.
ui_main.h offers the class Ui::MainWindow with the plain form information
where all the buttons and stuff should be and the method *void setupUi(QMainWindow MainWindow).
Now my workflow (is it even a feasible one?) goes like this:
I build a totally new header file Form_main.h:
// Form_main.h
[..]
class Form_main : public MainWindow, public QMainWindow
{
Q_OBJECT
privat slots:
void on_some_event();
[..]
};
The class uses said auto-generated MainWindow::setupUi(this) to 'get in shape' and QMainWindow to be, well, a QMainWindow with all that stands for.
But now I am in a dilemma: Either I remove the Q_OBJECT macro call leading to connect(..) no longer recognizing that Form_main has signal slots, or
I keep the Q_OBJECT leading to the infamous
undefined reference to `vtable for display::Form_main'
error while linking the project.
Now, there have been, in fact, people with similar issues.
Naming some links:
http://michael-stengel.com/blog/?p=103
Qt Linker Error: "undefined reference to vtable"
Undefined reference to vtable... Q_OBJECT macro
Qt vtable error
A hint I got from the last one: "MOC must generate code for ui_main.h and the generated code must be compiled and linked."
In any case, these answers all seem to boil down to 'running qmake again'. Well, I use CMake all the way wanting my project to configure and compile after exactly
cmake .
make
What I did try was deleting everything in and below the build directory
(including every auto-generated file) and then running cmake . && make;.
Sadly that did not help. I am afraid this is my second noob question today... would you bear with me once more?
=== AFTER TRYING GREENWAYS ANSWER I PROVIDE MORE DETAILS. ===
Here is the autogenerated ui_main.h
/********************************************************************************
** Form generated from reading UI file 'main.ui'
**
** Created by: Qt User Interface Compiler version 5.3.2
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
#ifndef UI_MAIN_H
#define UI_MAIN_H
#include <QtCore/QVariant>
#include <QtWidgets/QAction>
[.. more Widget Includes ..]
QT_BEGIN_NAMESPACE
class Ui_MainWindow
{
public:
QAction *action_exit;
[.. more sub widgets like that .. ]
void setupUi(QMainWindow *MainWindow)
{
[ .. Setting up the form. Harmless code. .. ]
} // setupUi
void retranslateUi(QMainWindow *MainWindow)
{
[ .. completely harmless .. ]
} // retranslateUi
};
namespace Ui {
class MainWindow: public Ui_MainWindow {};
} // namespace Ui
QT_END_NAMESPACE
#endif // UI_MAIN_H
Reading all this and incorporating your post right now I am at
// form_main.h
#ifndef MHK_FORM_MAIN_H
#define MHK_FORM_MAIN_H
#include <QMainWindow>
#include "ui_main.h"
[..]
namespace Ui { class MainWindow; }
namespace display
{
class Form_main : public QMainWindow
{
Q_OBJECT
private:
ostream* stdout;
ostream* stderr;
Ui::MainWindow* uiMainWindow;
/** Called by the constructor. Sets up event connections and other
* preliminary stuff the qt Designer is overtasked with. */
void setup_form();
[..]
public:
explicit Form_main(QWidget* parent = 0);
~Form_main();
private slots:
void exit_program();
};
}
#endif
And my cpp
// form_main.cpp
#include "ui_main.h"
#include "form_main.h"
[..]
using namespace Ui;
namespace display
{
void Form_main::setup_form()
{
QObject::connect(uiMainWindow->action_exit, SIGNAL(triggered()), this, SLOT(exit_program()));
[..]
}
Form_main::Form_main(QWidget* parent) : QMainWindow(parent)
{
uiMainWindow = new Ui::MainWindow();
uiMainWindow->setupUi(this);
[..]
#if defined(Q_OS_SYMBIAN)
this->showMaximized();
#else
this->show();
#endif
}
Form_main::~Form_main()
{
delete uiMainWindow;
}
[..]
Form_main::exit_program()
{
this->close();
(*stdout) << "Thanks for playing " << getProgramName() << endl;
}
}
Ok. I see (partly) the problem. Just create a widget class like this:
.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
.cpp
#include "MainWindow.h"
#include "ui_MainWindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
This is how the QtCreator creates ui-Widgets. "ui_MainWindow.h" is your generated .h file.
Thanks for all your help! However, the problem was in CMakeLists.txt after all. The comment of Chris Morlier on Undefined reference to vtable pointed me to the solution.
The pertinent passage goes:
For Qt users: you can get this same error if you forget to moc a header
I simply had to add the header form_main.h into this line:
QT5_WRAP_CPP(qt_H_MOC ${qt_H} "${DIR_SRC}/include/form_main.h")
I have wrote an app which mainly is an equivalent to mac osx finder. When copying file into a folder, I'm checking if a file of the same name already exist. In case it exist, I'm asking the user if he want to cancel, overwrite or not overwrite.
The Dialog box for the overwrite has been created with QT designer and generate a dialogoverwrite.ui, .cpp and .h.
User Interface
dialogoverwrite.cpp
#include <QDialogButtonBox>
#include "dialogoverwrite.h"
#include "ui_dialogoverwrite.h"
DialogOverwrite::DialogOverwrite(QWidget *parent) :
QDialog(parent),
ui(new Ui::DialogOverwrite)
{
ui->setupUi(this);
}
DialogOverwrite::~DialogOverwrite()
{
delete ui;
}
dialogoverwrite.h
#include <QDialog>
#include <QDialogButtonBox>
namespace Ui {
class DialogOverwrite;
}
class DialogOverwrite : public QDialog
{
Q_OBJECT
public:
explicit DialogOverwrite(QWidget *parent = 0);
~DialogOverwrite();
private:
Ui::DialogOverwrite *ui;
};
I'm using this class in My TreeWidget application as shown below, I will only add the required code
DialogOverwrite *OverwriteDialog = new DialogOverwrite;
OverwriteDialog->exec();
A kind of OverwriteDialog.button.value could be perfect for me.
the exec will show the dialog and wait for a user action. How can I easily catch the return value : Cancel, Yes, YesToAll, No, NoToAll
I'm looking for an easy to get it. I would like to avoid any additional method in the dialogoverwrite class with signal/connecT. I really just need the button value to react.
Thanks a lot
Call QDialog::done(int r) with a value that represents one of the closing buttons. This value is returned by exec().
Default values are provided by QDialog::DialogCode enum.
I'm developing an application with Qt, a framework with which I'm not at all familiar, and I'm attempting to hide and show a DockWidget that I created using designer.
Unlike many of the seemingly similar questions about hiding and showing dockwidgets in Qt is that I made my widget entirely with Qt Designer, so I don't know how to link much of the code I've found in these questions' answers. Essentially, I have no mention of a dockwidget in my *.cpp files, but I do in my .ui file.
How can I incorporate this Designer-created dockwidget into my code to make it visible and invisible?
Sorry for such a nooby question.
Thanks,
erip
Wenn you build your application, qmake generates h from your ui files. So for instance ui_dlg_about.ui is translated into a ui_dlg_about.h automatically. Usually in a folder calles GeneratedFiles or something like that. You can then create an acutal customisable dialog class which you use in your application by creating something along the following:
dlg_about.h
#include "ui_dlg_about.h"
#include <QDialog>
class dlg_about : public QDialog, protected Ui::ui_dlg_about
{
Q_OBJECT
public:
dlg_about(QWidget* = 0);
public slots:
void toggle_dockwidget();
};
dlg_about.cpp
#include "dlg_about.h"
dlg_about::dlg_about(QWidget* parent) : QDialog(parent)
{
setupUi(this);
QObject::connect(this->somebutton, SIGNAL(clicked()), this, SLOT(toggle_dockwidget()));
}
void dlg_about::toggle_dockwidget()
{
if(something){
this->dockwidget->setVisible(true);
}else{
this->dockwidget->setVisible(false);
}
}
It is also possible for your dialog to not be derived from ui_dlg_about but having it as a member:
dlg_about.h
#include "ui_dlg_about.h"
#include <QDialog>
class dlg_about : public QDialog
{
Q_OBJECT
public:
dlg_about(QWidget* = 0);
public slots:
void toggle_dockwidget();
protected:
Ui::ui_dlg_about ui;
};
dlg_about.cpp
#include "dlg_about.h"
dlg_about::dlg_about(QWidget* parent) : QDialog(parent)
{
setupUi(this->ui);
QObject::connect(this->ui.somebutton, SIGNAL(clicked()), this, SLOT(toggle_dockwidget()));
}
....