PDA

View Full Version : Qt GUI print global variables



jonagf
26th April 2017, 22:42
Hi!

I'm very new at Qt and c++ programming, and I created a Qt GUI and have some global variables that I change when my callbacks are called.
I would like to print those global variables in my terminal, so I wrote in my main.cpp the following:


#include "ros/ros.h"

#include "mainwindow.h"
#include <QApplication>
#include "globals.h"
#include "qtgui/GUIDados.h"

using namespace std;

namespace global2
{
int numberOfMotors;
int intensidade[16];
int local[16];
}

int main(int argc, char *argv[])
{

QApplication a(argc, argv); //creates a QApplication object
MainWindow w; //creates the main window object
w.show();

cout << "test: " << global2::numberOfMotors << endl;
return a.exec(); //enter its event loop

}


However, I always get test 0 and nothing else. In my mainwindow.cpp I am able to write those global variables in a label in my gui, like for example:
(this is just an excerpt of my mainwindow.cpp code)


#include "ros/ros.h"

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QtGui/QPushButton>
#include "globals.h"
#include <QString>
#include <string>
#include <sstream>
#include "QMessageBox"


namespace global
{
int numberOfMotors;
int intensidade[16];
int local[16];
}

using namespace std;

void MainWindow::on_sendButton_clicked()
{
QMessageBox::information(this,tr("Titulo"),tr("escolheu: %1").arg( global::intensidade[0]));
ui->label1->setText(QString::number(global::numberOfMotors));
}


Can you explain me what I'm doing wrong?

jefftee
27th April 2017, 00:02
Your main window's event loop isn't started until line 25 is executed in your main routine, so events are not processed until after you've already executed line 24 and printed out the value. BTW, global variables are evil and should be avoided at all costs... :)

d_stranz
27th April 2017, 00:12
If this is your actual code and you really are declaring the variables in the global2 namespace twice, then the ones declared in main.cpp are not the same as the ones in MainWindow.cpp and so are never initialized. That the call to cout prints "0" and not gibberish is probably the result of a friendly compiler that initializes variables to zero in release mode for you.

Time to read up on your basic C++ on variables and scoping. Here's a start. (https://stackoverflow.com/questions/9702053/how-to-declare-a-global-variable-in-c)

@jefftee: This has nothing to do with the event loop or event processing. cout is plain old C++. And unfortunately, Arduino and RasPi coding books have brought back the evil global variable with a vengeance. From the names of the variables, this seems to be what this is about.

jefftee
27th April 2017, 00:59
@jefftee: This has nothing to do with the event loop or event processing. cout is plain old C++. And unfortunately, Arduino and RasPi coding books have brought back the evil global variable with a vengeance. From the names of the variables, this seems to be what this is about.
Thanks, I jumped to the wrong conclusion... :) I still feel that global variables are an indication that you have poorly designed your classes/interfaces and a crutch used by too many people just to make it work... :)

Edit: after reviewing the code, he's creating the same variable names in two different namespaces (global and global2) so they are indeed different variables and I don't see where they are ever initialized either.

d_stranz
27th April 2017, 03:31
he's creating the same variable names in two different namespaces (global and global2)

Ah, and I missed that detail. Even if he does initialize the variables in the "global" namespace, the variables in "global2" remain uninitialized.

And I agree about global variables also. The closest I ever come are static const variables in cpp module scope or singleton classes that can only have one instance. But as I said, pick up any Arduino or Raspberry Pi coding book and they are in every example. It might be the most straightforward way to teach coding for single board computers, but it teaches bad habits that don't scale well when used in real-world applications.

jonagf
27th April 2017, 09:58
Hi jefftee, d_stranz,

Yes, the main goal of this program is to send this variables via message (ROS) to Arduino.

I'm sorry, I forgot to post my globals.h file, that's where I initialize my global variables:


#ifndef GLOBALS_H
#define GLOBALS_H

extern int numberOfMotors;
extern int intensidade[16];
extern int local[16];

#endif // GLOBALS_H

As you can imagine I am very new in this C++ thing, I've only used arduino and C, so that's why I jumped right away to the global variables.

I declared another namespace (global2) because when i tried to use the global namespace that I created in the other window it said that that namespace was already used (or something like that :( ). I thought I didnt even need to create that namespace because the variables should already be declared in the globals.h, however, if I only do numberOfMotors = 5 for example (I'm sorry if I'm saying something stupid), then I get an error saying that numberOfMotors doesnt name a type.

Instead of using global variables should I try to use classes? The reason I tried to escape from it is that I'm not very sure how the all classes thing work, and I didn't want to mess things up even more than they already are.

Thank you for the answers!! ;)

Added after 14 minutes:

Yup, I'm very very noob on this.
Turns out I only needed to initialize in my mainwindow.cpp the following

int numberOfMotors;
int intensidade[16];
int local[16]; and


MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
numberOfMotors =5;
}

and in my main.cpp I just did
cout << "exp " << numberOfMotors << endl; without initializing anything and it printed 5.

Now the thing is, it only prints once and i wanted it to constantly print it everytime I update something. I guess now it has to do with what jefftee said first..

d_stranz
27th April 2017, 19:43
I'm sorry, I forgot to post my globals.h file, that's where I initialize my global variables:

No, this is not initializing, it is telling the compiler that somewhere in the program there are variables named "numberOfMotors", etc. that have global visibility. Initializing means assigning an initial value to those variables. If you don't initialize them, then the compile can choose to (a) do nothing (in which case your program starts with the variables having whatever random value the memory happened to contain prior to that), (b) zero them out (i.e. set the memory to all zero bits), or (c) set them to some "known" value that you can recognize in the debugger as a default value for an uninitialized variable. It looks like your compiler might be doing option (b).


Turns out I only needed to initialize in my mainwindow.cpp the following

So, in globals.h you are telling the compiler that these variables are declared somewhere in the program. In these lines in mainwindow.cpp you are actually declaring them. Declararing is not initializing. In line 5 of your MainWindow constructor is where you are assigning a value to "numberOfMotors". Technically speaking, this is not initialization, since someone could access that variable prior to constructing the MainWindow instance and the variable would be uninitialized at that point. Your other two array variables are still uninitialized after the MainWindow constructor exits.

The reason your cout statement in main.cpp works (i.e. prints "5") is because you placed the cout statement after the MainWindow instance "w" is declared (and constructed). If you put it before that statement, it would print "0" (or some random, uninitialized value).