Invalid use of non-static data member "ui"
-
Sorry if my terms are incorrect i come from a java background.
Im trying to create a util class to just make my project more organised but I'm having problems accessing my UI from an external class, at first in the header file the UI was private so i changed it to public but now its complaining with the error "Invalid use of non-static data member "ui"" Does anyone know how to fix this? Should I be making UI public or should I use another method? Here is my code, only the relevant parts of the classes//QUIZ.CPP //Creates "Quiz" widget Quiz::Quiz(QWidget *parent) : QWidget(parent), ui( new Ui::Quiz) { ui->setupUi(this); ui->console->append("Type \"start\" to go"); } //Destroys widget on exit Quiz::~Quiz() { delete ui; } //QUIZ.H namespace Ui { class Quiz; } class Quiz : public QWidget { Q_OBJECT public: explicit Quiz(QWidget *parent = 0); ~Quiz(); private slots: void on_button_clicked(); void on_input_returnPressed(); public: Ui::Quiz *ui; }; #endif // QUIZ_H //UTIL.CPP void appendConsole(QString string) { Quiz::ui->console->append(string); } void appendInput(QString string) { Quiz::ui->input->setText(string); } QString getInput() { return Quiz::ui->input->text(); }
-
Hi
Welcome to C++ then :)
It complains because the syntax used
Quiz::ui->input->setText(string);
should be
ui->input->setText(string);The syntax
Quiz::
is for calling a static method in a class.
but ui is not static. Its just a private class.
So compilers whines. :)But here comes the bummer. UI is private so you cannot
say ui->input->setText(string); from external classSo the options are:
1: use public function to setData without exposing to exernal class what kind
of widget that does the real job.
void appendConsole(QString string) {
QuizInstance->SetConsoleText(string);
}
2:
Use signals and slot
http://doc.qt.io/qt-5/signalsandslots.html
here you would define a new signal and slot say
SetConsoleText(QString Text);
and connect signal to slot
and u can then
emit SetConsoleText("logtext");Since you seem to be using normal non class members functions in UTILS.cpp
then public function seems to be the way to go.Also since this is C++, you can make UI public and directly access it but
that is considered bad practice as you then expose the widgets to rest of program. -
The reason i had it as Quiz::ui is because its not in the same cpp file its in a seperate file called util.cpp, this is for organisation reasons, if i do not do this it throws the error "Use of undeclared 'ui'" so i assumed i needed to mention the class name similar to java
-
The reason i had it as Quiz::ui is because its not in the same cpp file its in a seperate file called util.cpp, this is for organisation reasons, if i do not do this it throws the error "Use of undeclared 'ui'" so i assumed i needed to mention the class name similar to java
@Hamish
Hi
The ClassName::Member syntax is used to call static functions in c++.
THats is, to call a function without a class instance.UI is not static so even if not private it would not work.
Even if UI was public, you would still need a instance to call it
Quiz myInstance;
myInstance.ui->consolexxxHope it make sense :)
-
Hmm so the only real way to fix my problem is to add the methods involving the ui back into the Quiz.cpp class. So there is no way to hook the ui object in any way?
Hi what you mean hook ?
As long as you have not created an instance of the class
the UI elements are not live.so UTILS.cpp must have an instance anyway. EVEN is UI was public.
void appendConsole(QString string) {
QuizPtr->ui->console->append(string);
}EDIT:
Oh. u did change ui to public..
Then u just need an instance to allow this.. -
hmm now i get this problem:
QWidget: Must construct a QApplication before a QWidget
The program has unexpectedly finished.although the Application is instantiated in the main class before everything else...
-
@Hamish
Well, if you make global Widgets variables, this can happen.
As globals are created first. Before main is run. -
@Hamish
Yes, often you can
Say you have this global widget
Quiz MyQuiz;If you do
Quiz *MyQuiz;and then in main
MyQuiz=new Quiz;It would not complain as global is just a pointer now.
But normally we dont use globals at all. All lives in classes.
Like mainwindow.ps. remember to call delete MyQuiz; at program end.
-
The reason i had it as Quiz::ui is because its not in the same cpp file its in a seperate file called util.cpp, this is for organisation reasons, if i do not do this it throws the error "Use of undeclared 'ui'" so i assumed i needed to mention the class name similar to java
The reason i had it as Quiz::ui is because its not in the same cpp file its in a seperate file called util.cpp, this is for organisation reasons, if i do not do this it throws the error "Use of undeclared 'ui'" so i assumed i needed to mention the class name similar to java
I often say "C++ is not Java", but mostly is in different context - memory management. Funnily, here it's even more applicable. In Java you are supposed to put every (public) class in it's own file (if I remember correctly), C++ doesn't care, it also doesn't care how you name your files . You can put the declaration in a header and then put the definitions in any cpp you want (as long as you don't duplicate the class/method names). It also doesn't care how many classes (exported or otherwise) you declare in a header file.
Well, if you make global Widgets variables, this can happen. As globals are created first. Before main is run.
Can i fix this?
You shouldn't create anything that's
QObject
derived before theQCoreApplication
constructor has run. The firstQObject
you create should be the application object. My advice, forget global variables, especially since you appear to not have much experience with C++. In Java they are mostly okay, but with C++ they are a real pain and lead to all sorts of complications. Do as @mrjj suggested and put your objects as members of classes.PS.
void appendInput(QString string) { Quiz::ui->input->setText(string); }
These functions are global functions, and not class members, you should convert them to methods instead and in these methods you can operate your
ui
object.Kind regards.