Qt avoiding circular dependency - c++

I have a Qt application with a main class GUIApplication which inherits from QMainWindow as shown below. The GUI has a start button, stop button and a QGraphicsScene.
My application will read data from the serial port and other stuff and draw on the QGraphicsScene according to what is received.
My main GUI class knows about my serial port class as it must initialse it on press of the start button etc. That is fine. My serial port class however must also must be able to communicate with my GUI class as it must update the QGraphicsScene on reception of data and other stuff.
My question is , is it a bad design for my serial port class to know about the GUI class also. Isn't this a form of circular dependency between the two classes? I plan to have a member of my serial port class a pointer to the GUI class. Is this the only way to do it , or should I register a callback in the serial port class instead, to decouple the classes? Any help is appreciated thanks.
// GUI class
#include "MySerial.h "
class GUIApplication : public QMainWindow
{
Q_OBJECT
public:
//.........
o_o
// Serial port class
#include "GUIApp.h "
class MySerial
{
public:
//..............
//write something on GUI`

It is a bad design. Your serial port class has nothing to do with GUI by nature and as such should be separated from it - apart from circular dependencies, you make it much less flexible that way and limit its usability. One day you might want to use it in a console application and if you wrote the class in such a way that it must be aware of the GUI class, you would have to modify it just to make it work with console and either have two versions that would differ only regarding UI, which doesn't make much sense, or add Qt as dependency even though you would not need it in console app if you wouldn't want to break the compatibility, which doesn't make much sense either.
Much better solution is sending some signal from your serial port class or some meaningful return code after the data is received, and then make the GUI class catch this value and update QGraphicsScene itself. That way you also get rid off the circular dependency.

Related

Synchronizing between a local and remote GUI

Consider the following GUI:
when the user press the + button the value is incremented to 6.
However on another computer another user is running the same GUI.
The two GUIs have to stay in sync.
If one of the users press the + button the value should be updated for both GUIs.
The remote GUI, the client, communicate with the local server via a simple protocol.
The communication takes the form of a cmd sent from the client and a response sent from the server. There are two commands:
1. cmd:"GET_VALUE", response: "5"
2. cmd: "INCREMENT", response: "OK"
Unfortunately the client has to poll GET_VALUE to be notified,
but the protocol albeit flawed can not be changed.
How can I implement this in Qt, C++?
So far I have come up with the following classes (rough outline):
class Model {
public:
std::atomic<int> m_value;
};
class Widget : public QWidget {
public slots:
void incrementClickedLocally(); // must update Model::m_value somehow
void valueChangedFromModel(int value); // will update the QLineEdit
};
// Reads synchronously from TCP/IP using WinSocket and works on the Model
class RemoteHandler : public QThread {
private:
void run override();
};
I would like to use signals/slots to communicate across the threads.
However it seems that the RemoteHandler can not use signal/slots to get the Model::m_value since slots can not have return types?
Further it would be convenient to emit a valueChanged signal from Model to notify Widget. However in order to do that Model must be a QObject.
It seems that when Model becomes a QObject there are many potential thread problems I have to look out for?
As it is Model is threadsafe. I can therefore request Model::m_value directly from the non main thread in RemoteHandler while the Widget may be accessing the same variable simultaneously from the main thread.
It cannot work with those commands.
The logic is well-known from the design of multi-core CPU's. You need Compare-and-Swap (CAS), Load-Link/Store Conditional (LL/SC) or something equally powerful. With the weak protocol you have, it can be proven that the race conditions are unsolvable.

Preferred way to design application arhitecture in Qt

I have application which has MainWindow that is divided in three main parts:
Thing is, all three parts need to communicate between themselves. For example, there is a QListView in left section where you select items, and depending on the selected item options change in the right section.
I have come up with three solutions:
draw everything within the MainWindow which would make MainWindow one big superclass:
This solution solves all problems with communication between widgets because all of them are part of MainWindow::ui but then I get one big (potentially messy) class.
put each section in it's own class and make MainWindow a singleton:
This solution is... well a singleton. And I don't really like singletons. I will have access to MainWindow from everywhere (essentially I am creating a global variable) and I would still have to expose MainWindow::ui (and ::uis of other sections) via getter which would mean that everything will have access to ::uis.
put each section in it's own class and connect everything via signals and slots:
This would probably be the best solution but with this solution I need to create getter for each widget from EachSection::ui (to be able to connect it in MainWindow with it's counterparts), I would need a lot of calls to connect() and I also have a problem if two slots react to same signal but they need to react in specific order.
So what would be the best approach?
The best approach would be to define messaging (protocol) between views, so that views is not tightly coupled (all views isolated and dont know about each other) one instance class (main window) know all three and connects them. Imagine a button line edit and label, when you press button label gets value of line edit, button implementation does not depend on lineedit implementation, lineedit does not depend on label and so on, all three classes can be extended or changed and it doesnot affect two other, so you can focus on one of them at the time.

Several windows as a single taskbar icon

Currently I am writing a C++ Qt GUI standard (i.e. via Qt Creator) application.
Basically, what I am trying to do is an application, which operates the following singleton classes:
a MainWindow class, which is responsible for the core logic;
a ServerWindow class, which is responsible for the server connection;
a User class, which is returned (in form of a pointer) by the ServerWindow class after successfull authentication;
a Data class, which is initialized with the data, recieved via ServerWindow upon user authentication.
The algorithm is:
Construct a MainWindow and create a Data class; it also holds a pointer (nullptr at this step) at the current user.
When the constructor has finished, the ServerWindow (derived from QDialog) is executed (via Qt delayed connection). At this step the MainWindow is frozen and set invisible, untill the ServerWindow emits one of the signals (logged, fail). The ServerWindow has a modal mode flag set.
When the ServerWindow is done, a pointer to the current user is passed to the MainWindow. The ServerWindow also knows about the Data class and initializes it.
The main problem is that at step 2 the application icon in the taskbar (I use Windows OS) is not shown. When the MainWindow is "offline" (i.e., not shown, invisible via setVisibility(false)), there is no icon. It is highly annoying, especially if there is a bunch of other applications open. So that, my question is: what can I do to make ServerWindow create an application icon in the taskbar without MainWindow being shown?
The additional, by-the-way question is about possible application architecture remastering. I cannot find any books in my small library about similar applications designing. Frankly, I cannot even figure out, which words I should pass to the Google search line. Any advice?
Preliminary, thanks for any answers!

Concept for changing Console Application in Qt Gui Application [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
having implemented a c++ class "quiz" that exchanges information with the player via console in/output, I want to replace the console by a Gui.
Therefore I implemented an appropriate class "MainWindow" (with QCheckboxes, QButtonGroup,...) as subclass of QWindow.
Now, I doubt about the relation of these two classes:
In my opinion, "quiz" HAS A "MainWindow" (like its element of type "quiz_content"). In consequence I enlarged "quiz" by a pointer to a QApplication and a pointer to "MainWindow". The constructor of "quiz" creates the corresponding elements on the heap and starts the exec() routine. However, a signal (like buttonClicked()) would have to call a method belonging to "quiz" (which does not have slots as pure c++).
Next try: "MainWindow" HAS A "quiz". So I can start the QApplication within main as shown by all beginners' examples. I can't give strong arguments why I don't like this relationship. In fact, it seems to lead to bigger modification of quiz.play(), a method, that manages the game.
Question: what is the usual way to combine traditional code with Qt application? Are there multiple possibilities? Which is the most efficient one regarding re-implementation of "quiz"?
Thanks for answering to my greenhorn question!
Further explanation: Thank you for responding so quickly! Sorry, that my question has not been formulated clearly.
As you mentioned I attached some code (from different .h/.cpp files, so
don't pay attention to errors due to declaration order. )
#Vlad: TU means Technical university, though, as you can see, I'm not studying computer science.
FIRST TRY:
class quiz{
public:
quiz(int& argc, char** argv,const char* file);
void play(int N=3)const;
protected:
quiz_content qc;
QApplication* pa;
MainWindow* pw;
};
quiz::quiz(int& argc, char** argv, const char* file):qc(file){
// starting Application with Welcome Window
pa=new QApplication(argc, argv);
pw=new MainWindow();
pw->show();
pa->exec();}
class MainWindow : public QMainWindow{
Q_OBJECT
public:
MainWindow(QWidget *parent = 0);
~MainWindow();
protected:
QLabel* qlf, *qls;
QVector<QCheckBox*> qla;
QButtonGroup* qba;};
MainWindow::MainWindow( QWidget *parent): QMainWindow(parent),qla(3)
{ // Welcome Wondow with checkboxes for desired level of game...
// everything works fine, but...
// to start quiz with desired level: can method from quiz be a slot for MainWindow?
// and if so, how will it be mentioned properly?
connect(qba,SIGNAL(buttonClicked(int)), this, SLOT(quiz::play(int)));
...}`
NEXT TRY the other way round with QApplication in main:
class quiz{
public:
quiz(const char* file);
// how can method play of element q influence the other elements of the
// MainWindow Object for displaying text, etc.?
void play(int N=3)const;
protected:
quiz_content qc;};
class MainWindow : public QMainWindow{
Q_OBJECT
public:
MainWindow(QWidget *parent = 0);
~MainWindow();
protected:
QLabel* qlf, *qls;
QVector<QCheckBox*> qla;
QButtonGroup* qba;
quiz q;};
Thanks, Murphy, you understood perfectly right :-)
I will pursue the suggestion you made in the last section. However, this means, that quiz has to be more modular. Instead of one big method quiz::play, that rules the whole game, quiz has to provide methods like QString quiz::nextQuestion(),unsigned int quiz::updateScore(), etc.
So my conclusions are:
If I want to develop code that shall use GUI features later on,
already when implementing it as console application I have to think
about modules appropriate for exchanging information with the GUI
object(s).
The logic is part of the GUI object, not vice versa.
I'm impressed by the numerous immediate and helpful reactions to my first question ever posted in a forum. Thank you!
I'm not sure I understand your approach and your question completely, but I'll give it a try. Unfortunately your code samples are far from complete, but I'll focus on the bigger image. I just wonder if what you've build so far works at all, as I'm missing main() and a couple of other things.
As mentioned a GUI is event oriented (and events are often, but not always, triggered by the user), and usually the UI classes take a central place and function which control the user interaction: what the user sees and what she can do. If I understand your architecture correctly the class quiz is what I would call the business logic, which contains the current state of the proceeding quiz and implements how actions manipulate the stored data, affecting what information and possibilities the UI provides at a given time. Simple applications implement the business logic in the UI class(es), but it is indeed good practice to move the logic into a separate class/module, which is called from the UI classes.
Enter Qt: In main() you usually instantiate a QApplication and the main window, QApplication::exec() yields control to the event loop of Qt, which enables the window(s) to listen to user interaction and process the events. E. g. pressing a button would call a connected slot (which is nothing else but a method that reacts accordingly to the event). So you have a main window object handling the user interaction, and some business logic to do calculations and telling the UI what to show next.
And now back to your specific question, as far as I understood it: Your second try seems closer to the architecture outlined above and what I would apply at a first try: Instantiating a main window object which holds an instance of the business logic in a member variable, calling its methods to trigger the progress of the quiz and use the return values to control what the UI is providing to the user.

How to call QMessageBox Static API outside of a QWidget Sub-Class

I have a utility class in my Qt GUI application. However, in my convenience class I wanted to call a QMessageBox::critical(), warning(), etc. The class isn't a QWidget, and therefore I cannot pass this as the parent. My class is subclassed from QObject, however, so it can run things such as signals and slots. So to work around this--if it's possible to--should I maybe look at the property API instead of using the Static API?
Class declaration:
class NetworkManager : public QObject
And here's an example of a Static API call that fails:
QMessageBox::critical(this, tr("Network"), tr("Unable to connect to host.\n"),
QMessageBox::Ok | QMessageBox::Discard);
So, if I were to build a Property based API message box, would it be possible to call it in a QObject somehow? I haven't really used the Property Based API, but I understand from the documentation that it seems to use an event loop (i.e. exec()).
Just pass NULL for the first parameter:
QMessageBox::critical(NULL, QObject::tr("Error"), QObject::tr("..."));
A better way than passing nullptr is to use the qobject tree you are already using (assuming that the parent of the NetworkManager instance is a QWidget; adjust the number of parents according to whatever your qobject tree looks like)
QMessageBox::critical(qobject_cast<QWidget *> (parent()), "Title", "Message");
We use a qobject_cast<> instead of a C or C++ style cast is because it adds a little protection and will return 0 if it can't cast upward to the QWidget *.
If you use nullptr the QMessageBox will appear as centered over the topmost window (QWidget) rather than the window that actually appeared higher up in the qobject tree of your NetworkManager class. This really annoys people who have multiple monitors, lots of windows open, multiple windows from a single application spanning multiple monitors, etc.