Get rid of god object of QMainWindow - qt

I am making an application with three libraries ITK VTK and Qt. Since I want all functionality in the event loop and connection of signals and slots so I defined all functionality under QMainWindow definition. Now mainwindow object became bulky and I tried to make different classes for different functionality but then all things messing in main.cpp Idea of modularization is missing. Can you suggest how should be structure of a program?

I rarely have anything more in main.cpp than creating and showing my QMainWindow, then calling app.exec().
If your QMainWindow starts to become bulky, then it means you should probably organize this code into different coherent classes (instead of moving it to main.cpp). The basic idea is to change a code that looks like this:
class MainWindow : public QMainWindow
{
public:
void doSomething();
void foo1();
void foo2();
void foo3();
void bar1();
void bar2();
void bar3();
private:
// ...
}
To a code that looks like this:
class Foo:
{
public:
void doSomething1();
void doSomething2();
void doSomething3();
private:
// ...
}
class Bar:
{
public:
void doSomething1();
void doSomething2();
void doSomething3();
private:
// ...
}
class MainWindow : public QMainWindow
{
public:
void doSomething();
private:
Foo foo_;
Bar * bar_;
// ...
}
How do you choose the classes Foo and Bar and which members of MainWindow you transfer to these new classes depends of course of your context. But the idea is to organize your code smartly so that each class have a "responsibility", and then MainWindow can delegate each work to the class that is responsible for this work. Like in a house, there are electricians for managing electricity, plumbers for managing water, etc... and the responsibility of the house keeper is only to call the appropriate guys to do the appropriate job. In your case, you probably want a class to perform any work related to ITK, and a class to perform any work related to VTK, then if they become bulky also, subdivide these classes.

Related

Qt - QLineEdit does not emit textChanged/textEdited Signal while QTextEdit does

Currently i am learning Qt in C++ and have following issue:
Connecting "textChanged" or "textEdited" with a slot does not work.
Header file:
#include ...
class PersonalPreferences : public QWidget
{
Q_OBJECT
public:
PersonalPreferences(QWidget *parent = nullptr);
public slots:
void make_available();
private:
...
};
Code file:
PersonalPreferences::PersonalPreferences(QWidget *parent) {
// Configuring Layout
connect(line_edit_name, SIGNAL(textEdited()), this, SLOT(make_available()));
}
make_available function:
void PersonalPreferences::make_available() {
label_name->setText("wadwad");
group_box_pref->setEnabled(true);
push_button_ok->setEnabled(true);
push_button_close->setEnabled(true);
}
Please notice that i intentionally reduced the code to it's significant parts and didn't include the main file. I tried the same code with and without the parameter make_available(const QString &text). Yet it does not change the outcome.
I also tried this
connect(line_edit_name, &QLineEdit::textEdited, this, &PersonalPreferences::make_available);
and still it did not work out.
I noticed that using QTextEdit instead of QLineEdit works, but nevertheless i need help to solve this issue with QLineEdit.
Thanks in advance!
you need to study the details carefully)
In QLineEdit, the signal is
void textChanged ()
In QTextEdit, the signal is
void textChanged (const QString & text)
then you need to make such an amendment
void make_available()
change to
void make_available(const QString & text)
and call
connect(line_edit_name, &QLineEdit::textEdited, this, &PersonalPreferences::make_available);
or
connect(line_edit_name, SIGNAL(textEdited()), this, SLOT(make_available()));
change to
connect(line_edit_name, SIGNAL(textEdited(QString)), this, SLOT(make_available(QString)));

How to use Q_DECLARE_METATYPE on QGraphicsitem derived class?

I want to use my objects as QVariants and for queued connections. Therefore I want to use Q_DECLARE_METATYPE(My_Item) and from the documentation I learned that I need a public copy constructor. I tried to write one, but I failed. Than I did read this copy constructor of derived QT class and the answer by BЈовић. From there I understand that what I intended to do is not going to work. What do I have to do make my objects useable for the Metatypesystem?
My_Item is based on My_Super_Item, which look like this:
class My_Item: public My_Super_Item {
Q_OBJECT
Q_INTERFACES(QGraphicsItem)
public:
explicit My_Item(Application *a, QString astring);
...
}
and
class My_Super_Item : public QObject, public virtual QGraphicsItem {
Q_OBJECT
Q_INTERFACES(QGraphicsItem)
public:
My_Super_Item(My_Application *a, QString astring);
...
}

Qt Model and View - Link data from model to view, how?

I'm pretty new to the Model and View concept and I'm having trouble finding the right way to do this. So in my understanding the concept means, that I have one class that handles all the view (GUI) parts and an other class which handles the data processing.
The GUI I made has a few Display Widgets (LCDnumbers) which just have to get data from the other class and output it into the LCD.
So I made a function in the GUI class which can set a number into the LCD. And I've made a function which can change the value of the number in the data class.
Now I need something to connect those, for example when I change the number in the data class I want it to update in the GUI. I found somethings about Signals and Slots (and emitting a signal) but how does that work, while maintaining the Model and View concept?
It could be that this is answered somewhere else, if so, can you link me the source? I couldn't find anything to solve my problem.
Thanks for reading and I hope someone can help me.
Header file of the GUI:
#include <QMainWindow>
#include <QtCore>
namespace Ui {
class MainBoardView;
}
class MainBoardView : public QMainWindow
{
Q_OBJECT
public:
explicit MainBoardView(QWidget *parent = 0);
~MainBoardView();
void ChangeNumber(int value);
private:
Ui::MainBoardView *ui;
};
CPP file of the GUI:
#include "mainboardview.h"
#include "ui_mainboardview.h"
MainBoardView::MainBoardView(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainBoardView)
{
ui->setupUi(this);
}
MainBoardView::~MainBoardView()
{
delete ui;
}
void MainBoardView::ChangeNumber(int value)
{
ui->lcdNumber->display(value);
}
Code of the data class:
Header:
class MainBoard
{
public:
MainBoard();
void changeMoney(int value);
private:
int m_money;
}
CPP:
void MainBoard::ChangeMoney(int value)
{
m_money = value;
//emit a signal here with the value to the ChangeNumber function of the GUI?
//and how should I do this?
}
For applying model/view concept of Qt you should use at least one of a model classes. Such model classes provide unified interface for several types of data (string-list, trees, sql, etc.)
For displaying the data one would use either a view-class or widgets connected to the model via QDataWidgetMaper
In your case there is no use of model/view observable. MainBoard should be QObject for emitting the signal:
class MainBoard: public QObject
{
Q_OBJECT
public:
MainBoard();
void changeMoney(int value); //emit value with emit moneyChanged(value) in the implementation.
signals:
void moneyChanged(int)
private:
int m_money;
}

Unable to connect signal to slot in another class

I have 2 classes. Class A and Class B. I am emitting a signal from class A which I want the B to recieve.
I am doing it following way
In Listener File
Header File:
Class Listener:public DDSDataReaderListener
{
//Some code
public:
A m_objectSendData;
}
Implementation File:
void Listener::ondataavailable(DDSDataReader *reader)
{
m_objSendData.GetDDSData();
}
In Class A
Header File:
Class A:public QObject
{
Q_OBJECT
public:
void GetDDSData();
signals:
void Signal_Data();
}
.cpp File
A::A(QWidget *parent):QObject(parent)
{
}
void A::GetDDSData()
{
emit Signal_Data();
}
In Class B
Header File:
Class B:public QObject
{
Q_Object
public:
A objGetData;
public slots:
void getData();
}
Implementation File:
B::B(QWidget *parent):QObject(parent)
{
//Some part of code
connect(&objGetData,SIGNAL(Signal_Data()),this,SLOT(getData());
}
void B::getData()
{
//Watever is to be updated
}
I tried debugging. It is going till emit part correctly. However it is not reaching the slot.
Can someone please help me with this.
Thank You.
Without full code, it's quite difficult to identify the exact issue of the problem, so I'll outline a few important points to check.
To ensure you can use the signal and slots mechanism, you should ensure that your class is derived, from QObject or a class already derived from QObject in its hierarchy and your class must contain the Q_OBJECT macro, for example: -
class A : public QObject // derived from QObject
{
Q_OBJECT // your class must have this macro for signals and slots
public:
A();
};
Omitting the macro is probably the most common of mistakes.
To specify a slot, you add it to either the public or private slot section of your class: -
class B : public QObject // derived from QObject
{
Q_OBJECT // your class must have this macro for signals and slots
public:
B();
public slots:
void SlotB(); // slot declared public
private slots:
void SlotBPrivate(); // slot declared private.
};
Once a signal is declared in a class, a slot to receive the signal should match the arguments passed in and when you connect a signal to a slot, you must not add the function argument names.
Therefore: -
connect(&objectA, SIGNAL(SignalA(int in), this, SIGNAL(SlotA(int param)); //will fail due to the argument names
It should be: -
connect(&objectA, SIGNAL(SignalA(int), this, SIGNAL(SlotA(int));
Finally, if you're using Qt 5, you can use the new connection call, which doesn't require you to specify any argument, but instead takes the addresses of slot and signal functions.
connect(&objectA, &A::SignalA, this, &B::SlotA));
Since it references the address of a function, in actuality, the functions don't need to be classed as a slot and will still be called.
Hope that helps.
Actually I believe an answer is given in one of the comments.
One more thing, you didn't show enough code but I suspecting that you program leaves scope of objectA variable and your emitting object is just destroyed before it can emit any signal (objectA is local variable created on stack not on heap). – Marek R 1 hour ago
you allocate your Object on stack, so it gets destroyed as soon as it gets out of scope, together with destroy it gets disconnected from all signals/slots it has connections to.
So that's why you don't see any errors/warning messages because code itself is completely legit. You should new() your object to get it allocated in heap.

Qt: How to track Release or Change event for Phonon::SeekSlider?

I'm using Phonon::SeekSlider, it's a cool thing and I don't need to bother about synchronization between slider and MediaObject but now I need to track the moment when user releases the slider after moving it or when it's value is changed or when the current time of MediaObject is changed. I cannot find any public signals, I can see them in the slider's code but they are private. How could I inherit/implement/track whatever to track this event?
Thanks
You can create a class inherits SeekSlider
in the .h file :
#include <Phonon/SeekSlider>
using namespace Phonon;
class MySeekSlider : public SeekSlider
{
Q_OBJECT
public:
MySeekSlider(QWidget *parent = 0);
signals:
void release(qint64 pos);
protected:
virtual void mouseReleaseEvent(QMouseEvent *);
};
and in the.cpp
void MySeekSlider::mouseReleaseEvent(QMouseEvent *)
{
emit release(this->pos());
}
or use the tick signal of your MediaObject
void tick ( qint64 time )
You may connect to private signals same way as to any others.
QStaticMetaObject ignores visibility level of signals|slots. The only difference of private signals from normal (which has protected visibility level) - you cannot emit them when subclassing your Phonon::SeekSlider.
I suppose there is no way to do it but to create a new class inherited from QSlider, and add the whole functionality about MediaObject inside.

Resources