QT good global Variable / Object handling - c++

I'm still new to QT and don't really know how to deal with global variables here.
I want to load a file in main() and store the data in Objects / Variables which I then need to access via functions like ::on_Button_clicked().
What are the best ways to have access to the Objects / Variables I set in the main function from the slots?

In your header file you can declare them like this:
class frmMain : public QMainWindow
{
Q_OBJECT
public:
explicit frmMain(QWidget *parent = 0);
~frmMain();
private slots:
void on_lineEdit_returnPressed();
private:
Ui::frmMain *ui; // <--
QComboBox *comboBox; // <--
QDialog *dialog; // <--
QString test; // <--
};
And then define them in your .cpp and use them within the class:
void frmMain::on_lineEdit_returnPressed()
{
comboBox = new QComboBox( );
test = "Hello";
comboBox->addItem( test );
}
On top of that declaring variables outside any scope still makes them global like you know it from basic c++.

Related

Qt and C++: Overwrite or Expand Class

I want to add some properties (like an ID) to a QPushButton. Therefore, I need to expand or overwrite the class Q_WIDGETS_EXPORT QPushButton : public QAbstractButton
How do I do that?
Thanks for the help.
you dont need to extend the class to just put an id in it ... instead make use of the property system.
as specified in the official doc here:
A property can be read and written using the generic functions QObject::property() and QObject::setProperty(), without knowing anything about the owning class except the property's name.
you just have to do:
ui->myButton->setProperty("Id", 123456);
can also be another object e.g a string (or even your own class if you define it to do that)
ui->myButton->setProperty("_name", "123456");
to read the property is the method property() there for you but read the doc because you get a QVariant as return example:
QVariant(int, 123456)
It really depends on the use case. There is no problem (and often the intended way) in inheriting from Qt-(Widget) Classes (correct me, if I am wrong).
So you could do:
class MyQPushButton : public QPushButton
{
Q_OBJECT
public:
MyQPushButton() : QPushButton(...) {}
private:
int ID = -1;
}
Qt has a very good documentation and you can look at the sources to see what to override.
You could also extend a new class with QPushButton, but than you always have to deal with the QPushButton reference in your class, if you want e.g. connect something. In the inherited class you can connect the slots and so on. But for example you could do this:
class MyQPushButton
{
public:
MyQPushButton() {}
const QPushButton& const GetQPushButton() { return pushButton; }
const QPushButton* const GetQPushButtonPtr() { return &pushButton; }
private:
QPushButton pushButton;
int ID = -1;
}
There is no right and wrong. But I would use the inheritance for Qt-classes.

how to create static QLabel in Qt

Is it possible to create some static QLabels in one class, and other classes can access its QLabels variable and apply changes to the QLabels without creating its object?
I found some answers online like if you want to access one class variables without creating its object in another class, you have to make its data static.
So basically what I am trying to do here is accessing and changing one class variables, for me it is QLabels, in another class without creating its object.
I know how to create static variables, but when comes to declare a staic QLabel, I found it difficult to achieve it.
I think you may just make the label accessible, i.e. expose it as a public member. Say you have a Form class, and a label QLabel in its ui. Add this method to the class:
public:
QLabel * label();
the implementation is just:
QLabel *Form::label()
{
return ui->label;
}
If all you need to expose is the label text property, just add these two accessors methods:
public:
QString labelText();
void setLabelText(QString & text);
in implementation file:
QString Form::labelText()
{
return ui->label->text();
}
void Form::setLabelText(QString &text)
{
ui->label->setText(text);
}
These last strategy fits encapsulation better.
About having it static: what if you have more than one instance of the Form class? Which label is supposed to be pointed to by the static member? If you are 100% sure you will have only one instance of the widget, you can add a static public QLabel * member:
public:
static QLabel * label;
in implementation file, on top:
QLabel *Form::label = 0;
in Form constructor:
ui->setupUi(this);
if(label == 0)
{
label = ui->label;
}
Again, this makes sense if you have one Form instance only. Otherwise, the static pointer will point forever to the label of the widget which was created first (and, dangerously, to nothing when that instance gets destroyed).

Does QScopedPointer hide multiple inheritance

I'm having trouble accessing the private part of a PIMPL design. "Of course!", you say! you're supposed to be!
Well, I'm writing some functional tests, so I don't care that I'm accessing private members, ok? :-)
To get to the point, I have the public class set up with a QScopedPointer to the private implementation as follows;
class CV {
...
private:
QScopedPointer<PrivateCV> const _d_ptr;
PrivateChartView * d();
const PrivateChartView *d() const;
};
PrivateCV * CV::d()
{
return _d_ptr.data();
}
const PrivateCV* CV::d() const
{
return _d_ptr.data();
}
and the private bit looks like this:
class PrivateCV : public QObject, public Ui_CVForm
{
Q_OBJECT
friend class MyTestClass;
public:
...
public slots:
void do_something();
}
It seems that MyTestClass can access the do_something() member function of PrivateCV, which it obtains as follows (pseudocode, obvs):
CV *cv = MyApp::get_a_cv();
PrivateCV *pcv = cv->d();
i.e. it will call this fine:
pcv->do_something();
but I can't access anything that is on the Ui_CVForm (the generated UI class from uic).
Ui_CVForm is (in part) as follows:
class Ui_CVForm
{
public:
QGridLayout *gridLayout_2;
QGroupBox *groupBox;
QLineEdit *lineEdit;
};
Is this something to do with the const-ness of the function d(), or the QScopedPointer perhaps?
When I'm inside CV, I can access the ui form elements of the PrivateCV with no problems..
void CV::and_another_thing()
{
d()->lineEdit->setText("wtfa");
}
any pointers (pun intended) most welcome!
OK this turned out to be due to some idiot (me) using the same filename for two different classes in different libraries.
The test library was picking up one header for Ui_CVForm which didn't contain items like the lineEdit above, while PrivateCV was using another... hence no complaints about not seeing the header at compile time.

How to make a constant or variable accessible in entire program

I would like to have access to constant/variable of desktop width and height in entire program.
This is how I do it - add this code to every .h file of my program and then use it normally.
#include <QDesktopWidget>
QDesktopWidget desktop;
int desktopHeight = desktop.geometry().height();
int desktopWidth = desktop.geometry().width();
I know it is not a good way how to do it. I tried to make one special desktopSize.h and then include to required parts of my program. But I was not successful.
What should be in header file like this one which I need?
You really do not want to use that particular approach and include that code in all translation units. If you did each one would include two variables named desktopWidth and desktopHeight causing duplicate symbol errors during link time. It will also make it difficult to manage updating them if the size of the desktop changes after the application starts. If you really want to provide global variables holding the size of the desktop you should place them in a single .cpp file and place extern declarations in a single header file that is included when needed.
Header file (GlobalDesktopInfo.h)
#ifndef GLOBALDESKTOPINFO_H
#define GLOBALDESKTOPINFO_H
extern int desktopHeight;
extern int desktopWidth;
#endif GLOBALDESKTOPINFO_H
Source file (GlobalDesktopInfo.cpp)
#include "GlobalDesktopInfo.h"
int desktopHeight = 0;
int desktopWidth = 0;
You will also need to initialize it at the earlier point reasonably possible. I suggest doing this in your main() function.
#include "GlobalDesktopInfo.h"
// other includes
int main()
{
QApplication app;
QDesktopWidget desktop;
desktopHeight = desktop.geometry().height();
desktopWidth = desktop.geometry().width();
// other code and initialization
}
I think it's better to have some slots in a class which return the desired values and use Qt's Signal/slot mechanism to access them from other classes.
Just make a signal in the target class, connect it to a slot in the class containing the slots and make a connection between two objects of the classes. This way you can access them in every class you like by connecting a signal to a slot returning that value and just emitting the signal and getting the returned value.
For example you can have a class like :
class DesktopInformation
{
Q_OBJECT
public:
DesktopInformation(QObject *parent = 0);
~DesktopInformation();
QDesktopWidget desktop;
public slots:
int getWidth()
{
return desktop.geometry().width();
}
int getHeight()
{
return desktop.geometry().height();
}
};
And access the desktop information from any other class like :
class SomeClass: public QObject
{
Q_OBJECT
public:
SomeClass(QObject *parent = 0);
~SomeClass();
signals:
int getWidth();
int getHeight();
private:
void someFunction()
{
int width = getWidth();
int heigth = getHeight();
...
}
};
And connect the signal from an object of SomeClass to the slot in an object of DesktopInformation :
connect(someClass, SIGNAL(getWidth()), desktopInformation, SLOT(getWidth()));
In class someClass you can access the value returned from getWidth slot in desktopInformation by just calling the signal and using the returned value.
Note that the two objects should be in the same thread for this to work. If they are in different threads then the connection type should be of type Qt::BlockingQueuedConnection :
connect(someClass, SIGNAL(getWidth()), desktopInformation, SLOT(getWidth()), Qt::BlockingQueuedConnection);
Another way is two use static member functions but it is not recommended unless you have a good reason to do it :
class desktopInformation {
public:
static QDesktopWidget desktop;
static int getWidth()
{
return desktop.geometry().width();
}
static int getHeight()
{
return desktop.geometry().height();
}
};
class someClass {
public:
void do_something();
};
You can access desktopInformation's static member function from someClass like this:
void someClass::do_something()
{
int width = A::getWidth();
...
};

access wxFrame(s) & wxDialog(s) globally

I'm new to C++ and new to codelite and also new to wxCrafter. I'm trying to build some GUI apps, but I'm messed up about object passthrough in C++. I spent a few hours and I just understand a little bit of that. First, to pass variables between wxFrame/wxDialog, I should create a instance of that class.
in frameA.cpp
void frameA::buttonAClicked() {
frameB * frameB1 = new frameB(NULL);
frameB1->connect(this);
}
in frameB.cpp
void frameB::connect(frameA *upper) {
//now I can access frameA via upper
}
But for a more complex case(e.g. 10 frames), values entered by user need to be shared between frames. I think it's better to make the frames/dialogs to be handle by a parent. Since all classes were triggered by main.cpp, so I think MainApp() will be good idea. So I tried to do this:
main.cpp:
class MainApp : public wxApp {
public:
frameA * frameA1;
frameB * frameB1
//frameC, frameD, frameE etc.
MainApp() {}
virtual ~MainApp() {}
virtual bool OnInit() {
frameA1 = new frameA(NULL);
frameB1 = new frameB(NULL);
frameA1->connect(this);
frameB1->connect(this);
SetTopWindow(frameA);
return GetTopWindow()->Show();
}
};
in both frameA.cpp and frameB.cpp:
frameA::connect(wxApp *par) {
this->parent = par;
}
Now I'm able to access MainApp via parent, but the two member objects(one is itself) was not found. Am I missed something? I'm really new to C++. Is that any better way (or a formal way) to do?
There is convenient way to make kind of global data in wxWidgets application. Create file ApplicationData.h:
#pragma once // replace with #ifndef ... if not supported by your compiler
class frameA;
// place here required forward declarations
// ...
struct ApplicationData
{
frameA* frameA1;
// any other data you need
};
Include this file to application class h-file:
#include "ApplicationData.h"
class MainApp: public wxApp
{
public:
ApplicationData applicationData; // or may it private with get/set functions
...
};
Finally, you can access applicationData from any place of wxWidgets application:
ApplicationData* pData = &wxGetApp().applicationData;
// Set/read global data members here:
// pData->...
See also: wxGetApp function definition in wxWidgets reference: http://docs.wxwidgets.org/2.6/wx_appinifunctions.html Note that you must add IMPLEMENT_APP and DECLARE_APP macros to make it working.