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();
    }
    

  • Qt Champions 2016

    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 class

    So 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


  • Qt Champions 2016

    @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->consolexxx

    Hope 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?


  • Qt Champions 2016

    @Hamish

    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...


  • Qt Champions 2016

    @Hamish
    Well, if you make global Widgets variables, this can happen.
    As globals are created first. Before main is run.



  • @mrjj Can i fix this?


  • Qt Champions 2016

    @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.


  • Qt Champions 2016

    @Hamish

    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 the QCoreApplication constructor has run. The first QObject 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.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.