Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. [solved]Call class function in another cpp file
QtWS25 Last Chance

[solved]Call class function in another cpp file

Scheduled Pinned Locked Moved General and Desktop
classheadercppobjects
16 Posts 3 Posters 12.6k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • J Offline
    J Offline
    JohanSolo
    wrote on 17 Sept 2015, 11:24 last edited by
    #2

    Well, as you discovered, you need an object to call a method. Then the most obvious solution would be to give a pointer on your MainWindow object to the function which tries to call MainWindow::test().

    One solution would be to emit a signal in your jsfunction,cpp (about which you don't give information) which would trigger the call to MainWindow::test() (which would need to be a slot). But without knowing what the content of jsfunction.cpp it's hard to tell.

    Give us more information on how you want to call MainWindow::test() and we'll be able to help.

    `They did not know it was impossible, so they did it.'
    -- Mark Twain

    T 1 Reply Last reply 17 Sept 2015, 12:11
    0
    • J Offline
      J Offline
      jsulm
      Lifetime Qt Champion
      wrote on 17 Sept 2015, 11:26 last edited by
      #3

      You should not call MainWindow methods somewhere else. Your jsfunction should emit a signal instead of calling test(), you connect that signal to a slot in MainWindow. This way jsfunction do not need to know anything about MainWindow.

      https://forum.qt.io/topic/113070/qt-code-of-conduct

      1 Reply Last reply
      0
      • J JohanSolo
        17 Sept 2015, 11:24

        Well, as you discovered, you need an object to call a method. Then the most obvious solution would be to give a pointer on your MainWindow object to the function which tries to call MainWindow::test().

        One solution would be to emit a signal in your jsfunction,cpp (about which you don't give information) which would trigger the call to MainWindow::test() (which would need to be a slot). But without knowing what the content of jsfunction.cpp it's hard to tell.

        Give us more information on how you want to call MainWindow::test() and we'll be able to help.

        T Offline
        T Offline
        TheHawk
        wrote on 17 Sept 2015, 12:11 last edited by TheHawk
        #4

        @JohanSolo @jsulm

        Currently I am working in 2 windows. 1 window is the MainWindow, the application launches with only this. The second window opens when requested and gives the functionality to parse a script (using QJSEngine). This window is called CustomCode.

        In the script I want to call functions which I have in my project. Currently I am only trying to call test() to understand the principle and continue from that.

        According to this stackoverflow, I had to use QObjects. That is where jsfunctions came in, this is a QObject class which I integrate into the QJSEngine.

        So my QS Script looks like this: jsfunction.call_test();

        CustomCode.h:

        #ifndef CUSTOMCODE_H
        #define CUSTOMCODE_H
        
        #include <QMainWindow>
        
        namespace Ui {
        class CustomCode;
        }
        
        class CustomCode : public QMainWindow
        {
            Q_OBJECT
        
        public:
            explicit CustomCode(QWidget *parent = 0);
            ~CustomCode();
        
        private:
            Ui::CustomCode *ui;
        
        private slots:
            void on_button_clicked();
        };
        
        #endif // CUSTOMCODE_H
        

        CustomCode.cpp:

        #include "customcode.h"
        #include "ui_customcode.h"
        #include "jsfunctions.h"
        #include <QtWidgets>
        #include <QJSEngine>
        #include <QFile>
        
        CustomCode::CustomCode(QWidget *parent) :
            QMainWindow(parent),
            ui(new Ui::CustomCode)
        {
            ui->setupUi(this);
            QPushButton *button = new QPushButton("Test");
            ui->verticalLayout->addWidget(button);
            connect(button,SIGNAL(pressed()),SLOT(on_button_clicked()));
        
        }
        
        CustomCode::~CustomCode()
        {
            delete ui;
        }
        
        void CustomCode::on_button_clicked()
        {
            QLabel *tb = new QLabel;
            ui->verticalLayout->addWidget(tb);
            QJSEngine myEngine;
            QJSValue scripttb = myEngine.newQObject(tb);
            jsfunctions jsfunction;
            QJSValue jsfunctionObj = myEngine.newQObject(&jsfunction);
            myEngine.globalObject().setProperty("jsfunction",jsfunctionObj);
            myEngine.globalObject().setProperty("tb",scripttb);
        
            QString fileName = "customlogic.qs";
            QFile scriptFile(fileName);
            if (!scriptFile.open(QIODevice::ReadOnly))
            {
            }// handle error
        
            QTextStream stream(&scriptFile);
            QString contents = stream.readAll();
            scriptFile.close();
            QJSValue result = myEngine.evaluate(contents, fileName);
            //QJSValue result = myEngine.evaluate("jsfunction.call_test();");
            if (result.isError())
            {
                qDebug() << "result: " << result.property("lineNumber").toInt() << ":" << result.toString();
            }
        }
        

        jsfunctions.h:

        #ifndef JSFUNCTIONS_H
        #define JSFUNCTIONS_H
        
        #include <QObject>
        #include <QWidget>
        #include <mainwindow.h>
        
        class jsfunctions : public QObject
        {
            Q_OBJECT
        public:
            explicit jsfunctions(QObject *parent = 0);
            void call_test()
            {
                emit send_test();
            }
        
        
        signals:
            void send_test();
        
        public slots:
        
        };
        
        #endif // JSFUNCTIONS_H
        

        jsfunctions.cpp:

        #include "jsfunctions.h"
        #include "mainwindow.h"
        
        
        jsfunctions::jsfunctions(QObject *parent) : QObject(parent)
        {
        
        }
        

        MainWindow.h

        #ifndef MAINWINDOW_H
        #define MAINWINDOW_H
        
        #include <QMainWindow>
        #include <QtCore>
        #include <QtGui>
        #include <QProgressBar>
        #include <QGridLayout>
        #include <QScrollArea>
        #include "vprParam.h"
        #include "customcode.h"
        
        namespace Ui {
        class MainWindow;
        }
        
        class MainWindow : public QMainWindow
        {
            Q_OBJECT
        
        public:
            explicit MainWindow(QWidget *parent = 0);
            CustomCode *codewindow;
            ~MainWindow();
        
        public slots:
            void test();
        
        private:
            QStandardItemModel *model;
            QWidget *box;
            QGridLayout *grid;
            void build_UI(vprParam_Inst_t* pInst, std::string profile);
        
        private slots:
            void on_actionOpen_CSV_triggered();
            void on_actionIP_List_toggled(bool arg1);
        
            void on_treeView_doubleClicked(const QModelIndex &index);
        
            void on_actionSave_triggered();
        
            void on_profile_clicked(int index);
        
            void on_actionAdd_custom_logic_triggered();
        
        private:
            Ui::MainWindow *ui;
            QProgressBar *progressBar;
            QWidget *central;
            QGridLayout *layout;
        };
        
        void loadcsv(QString IP, QString SUBIP);
        void SetValueInDb(QString name, int value);
        
        #endif // MAINWINDOW_H
        

        mainwindow.cpp (only the relevant code)

        #include "mainwindow.h"
        #include "ui_mainwindow.h"
        #include "vprParam.h"
        #include <string>
        #include <vector>
        #include <QFileDialog>
        #include <QtWidgets>
        #include <QComboBox>
        #include <QLabel>
        #include "paramblock.h"
        
        struct readips
        {
        };
        
        struct create_db
        {
        };
        
        struct memory
        {
        }
        
        MainWindow::MainWindow(QWidget *parent) :
            QMainWindow(parent),
            ui(new Ui::MainWindow)
        {
            ui->setupUi(this);
            progressBar = new QProgressBar;
            ui->statusBar->addPermanentWidget(progressBar);
            progressBar->setVisible(false);
        }
        
        MainWindow::~MainWindow()
        {
            delete ui;
        }
        
        void MainWindow::on_actionOpen_CSV_triggered()
        {
        }
        
        
        void loadcsv(QString IP,QString SUBIP)
        {
        
        }
        
        void MainWindow::on_actionIP_List_toggled(bool arg1)
        {
        }
        
        
        void MainWindow::on_treeView_doubleClicked(const QModelIndex &index)
        {
            
        }
        
        void MainWindow::on_profile_clicked(int index)
        {
        }
        
        void MainWindow::build_UI(vprParam_Inst_t* pInst, std::string profile)
        {
        }
        
        void MainWindow::on_actionAdd_custom_logic_triggered()
        {
            codewindow = new CustomCode;
            codewindow->show();
        }
        
        void MainWindow::test()
        {
            progressBar->setEnabled(true);
            progressBar->setVisible(true);
            progressBar->setValue(50);
            ui->dockWidget->setWindowTitle("TEST");
        }
        

        I already tried to make it with signal/slots but I failed at this, I always ended up with having to create a new object for mainwindow, I would like to see how to do it properly.
        Also, sorry for any messy/confusing code, I am new to c++ and Qt and a rookie programmer overall.

        Thanks!

        1 Reply Last reply
        0
        • J Offline
          J Offline
          JohanSolo
          wrote on 17 Sept 2015, 12:52 last edited by
          #5

          OK, according to what I understood from your design, MainWindow spawns a CustomCode instance when requested. Therefore when constructing the CustomCode instance you know which MainWindow instance you have to connect to. If I were you I'd use the calling MainWindow instance as parent of the CustomCode instance. This would allow to connect the send_test() signal to the test() slot of your MainWindow instance.

          `They did not know it was impossible, so they did it.'
          -- Mark Twain

          1 Reply Last reply
          1
          • T Offline
            T Offline
            TheHawk
            wrote on 17 Sept 2015, 13:13 last edited by TheHawk
            #6

            How could I do that?

            If I do this in mainwindow.cpp:

                codewindow = new CustomCode;
                codewindow->setParent(this);
                connect(codewindow,SIGNAL(send_test()),SLOT(test()));
                codewindow->show();
            

            This makes it compile but instead of a seperate window the current mainwindow gets overwritten with the codewindow and the send_test() is in jsfunctions.h, not in CustomCode.h. Would I have to make a function that calls another function that calls the signal? Or am I missing it here? Sorry

            Edit:

            Succes!

            I used : (in mainwindow.cpp)

            void MainWindow::on_actionAdd_custom_logic_triggered()
            {
                codewindow = new CustomCode;
                QObject::connect(&jsfunction,SIGNAL(send_test()),this,SLOT(test()));
                codewindow->show();
            }
            

            added extern jsfunctions jsfunction; to mainwindow.h and customcode.h
            added jsfunctions jsfunction; in jsfunctions.cpp

            and changed jsfunctions.h to

            signals:
                void send_test();
            
            public slots:
                void call_test()
                {
                    emit send_test();
                }
            

            Now it works! test() gets properly called and my UI actually changes. Many thanks! :)

            PS: How do I change the topic to solved?

            J 1 Reply Last reply 18 Sept 2015, 04:26
            0
            • T TheHawk
              17 Sept 2015, 13:13

              How could I do that?

              If I do this in mainwindow.cpp:

                  codewindow = new CustomCode;
                  codewindow->setParent(this);
                  connect(codewindow,SIGNAL(send_test()),SLOT(test()));
                  codewindow->show();
              

              This makes it compile but instead of a seperate window the current mainwindow gets overwritten with the codewindow and the send_test() is in jsfunctions.h, not in CustomCode.h. Would I have to make a function that calls another function that calls the signal? Or am I missing it here? Sorry

              Edit:

              Succes!

              I used : (in mainwindow.cpp)

              void MainWindow::on_actionAdd_custom_logic_triggered()
              {
                  codewindow = new CustomCode;
                  QObject::connect(&jsfunction,SIGNAL(send_test()),this,SLOT(test()));
                  codewindow->show();
              }
              

              added extern jsfunctions jsfunction; to mainwindow.h and customcode.h
              added jsfunctions jsfunction; in jsfunctions.cpp

              and changed jsfunctions.h to

              signals:
                  void send_test();
              
              public slots:
                  void call_test()
                  {
                      emit send_test();
                  }
              

              Now it works! test() gets properly called and my UI actually changes. Many thanks! :)

              PS: How do I change the topic to solved?

              J Offline
              J Offline
              JohanSolo
              wrote on 18 Sept 2015, 04:26 last edited by
              #7

              I don't think it is necessary to have a static instance of jsfunctions to do this. Why did you add it? As far as I understand, the jsfunctions instance was meant to be used in the CustomCode instance? Assuming my hypothesis is correct, I would do the connect in the CustomCode, where both the MainWindow and jsfunctions instance are used:

              void MainWindow::on_actionAdd_custom_logic_triggered()
              {
                  codewindow = new CustomCode( this );
                  codewindow->show();
              }
              
              CustomCode::CustomCode( QObject* parent )
                  : QMainWindow(parent)
                  , ui(new Ui::CustomCode)
                  , jsfunction( new jsfunctions() )
              {
                  connect( jsfunction, SIGNAL( send_test() ), parent, SLOT( test() ) );
              }
              
              @TheHawk said:
              > PS: How do I change the topic to solved?
              
              You can simply edit the topic title (IIRC by editing your first post),

              `They did not know it was impossible, so they did it.'
              -- Mark Twain

              1 Reply Last reply
              1
              • T Offline
                T Offline
                TheHawk
                wrote on 18 Sept 2015, 09:17 last edited by
                #8

                I have no particular reason why I chose it to be static, I did it because after googling some errors it was suggested to use static.

                Anyhow, your code indeed works as well and your assumption was correct! :)
                I do have a little issue now. Calling codewindow = new CustomCode( this ); makes the new window always on top. I previously called codewindow = new CustomCode;, this made the 2 windows independant (if you clicked the one in the back it came to front). I don't really see an option how to fix this behavior besides using signals and slots at a click to bring a window up and lower the other one. Am I missing the obvious here?

                thanks!

                1 Reply Last reply
                0
                • J Offline
                  J Offline
                  JohanSolo
                  wrote on 18 Sept 2015, 09:20 last edited by JohanSolo
                  #9

                  I think you can tune this behaviour with the correct window flag, which is the second argument of the QMainWindow constructor.

                  Edit:
                  As another way to do it, you can pass a null pointer to the QMainWindow constructor in the CustomCode constructor, but still use the parent pointer in the connect statement.

                  `They did not know it was impossible, so they did it.'
                  -- Mark Twain

                  1 Reply Last reply
                  0
                  • T Offline
                    T Offline
                    TheHawk
                    wrote on 18 Sept 2015, 09:46 last edited by
                    #10

                    I tried all the window flag settings without succes, it always stays on top.

                    How would I pass a null pointer to the QMainWindow constructor in the CustomCode constructor? Can't really get my head around it. Changing the call to:
                    codewindow = new CustomCode(0); or codewindow = new CustomCode; creates the desired effect but makes me unable to call the function (since no parent exists I think?).

                    Am I even calling the windowflag correctly?

                    void MainWindow::on_actionAdd_custom_logic_triggered()
                    {
                        CustomCode *codewindow;
                        codewindow = new CustomCode(0);
                        //QObject::connect(&jsfunction,SIGNAL(send_test()),this,SLOT(test()));
                        codewindow->setWindowFlags(Qt::Window);
                        codewindow->show();
                    
                    }
                    
                    1 Reply Last reply
                    0
                    • J Offline
                      J Offline
                      JohanSolo
                      wrote on 18 Sept 2015, 09:47 last edited by
                      #11

                      I was thinking about

                      CustomCode::CustomCode( QObject* parent )
                          : QMainWindow( 0 )
                          , ui( new Ui::CustomCode )
                          , jsfunction( new jsfunctions() )
                      {
                          connect( jsfunction, SIGNAL( send_test() ), parent, SLOT( test() ) );
                      }
                      

                      `They did not know it was impossible, so they did it.'
                      -- Mark Twain

                      T 1 Reply Last reply 18 Sept 2015, 10:03
                      1
                      • J JohanSolo
                        18 Sept 2015, 09:47

                        I was thinking about

                        CustomCode::CustomCode( QObject* parent )
                            : QMainWindow( 0 )
                            , ui( new Ui::CustomCode )
                            , jsfunction( new jsfunctions() )
                        {
                            connect( jsfunction, SIGNAL( send_test() ), parent, SLOT( test() ) );
                        }
                        
                        T Offline
                        T Offline
                        TheHawk
                        wrote on 18 Sept 2015, 10:03 last edited by
                        #12

                        @JohanSolo

                        Ah yes, seems so obvious now. Works like a charm!

                        Thanks :)

                        1 Reply Last reply
                        0
                        • J Offline
                          J Offline
                          JohanSolo
                          wrote on 18 Sept 2015, 10:04 last edited by
                          #13

                          You're welcome! I'm glad I could help.

                          `They did not know it was impossible, so they did it.'
                          -- Mark Twain

                          T 1 Reply Last reply 18 Sept 2015, 11:34
                          1
                          • J JohanSolo
                            18 Sept 2015, 10:04

                            You're welcome! I'm glad I could help.

                            T Offline
                            T Offline
                            TheHawk
                            wrote on 18 Sept 2015, 11:34 last edited by
                            #14

                            @JohanSolo

                            I got a question though (kinda off-topic). Would it be possible to create a signal from the MainWindow to a slot (or function) inside the javascript script that I evaluate inside CustomCode? So for example:

                            I want to plot a graph using the javascript script. I want that graph to use actual, changing values from mainwindow. So I would like to create a signal that triggers upon a value change and then call a function inside the javascript script to update the graph with the new values.

                            1 Reply Last reply
                            0
                            • J Offline
                              J Offline
                              JohanSolo
                              wrote on 18 Sept 2015, 11:39 last edited by
                              #15

                              @TheHawk said:

                              I got a question though (kinda off-topic). Would it be possible to create a signal from the MainWindow to a slot (or function) inside the javascript script that I evaluate inside CustomCode? So for example:

                              Better ask a new question in a new thread, for the future, it helps when looking for a problem on the forum.

                              You are free to define any signal / slot you want, so the short answer is yes.
                              You can emit a signal in MainWindowwhen the data needs to be reprocessed by the js script managed by CustomCode.

                              `They did not know it was impossible, so they did it.'
                              -- Mark Twain

                              1 Reply Last reply
                              0
                              • T Offline
                                T Offline
                                TheHawk
                                wrote on 18 Sept 2015, 11:43 last edited by
                                #16

                                My apologies, I will create a new thread. Thanks for all your help! (and putting up with my stuff :) )

                                1 Reply Last reply
                                0

                                11/16

                                18 Sept 2015, 09:47

                                • Login

                                • Login or register to search.
                                11 out of 16
                                • First post
                                  11/16
                                  Last post
                                0
                                • Categories
                                • Recent
                                • Tags
                                • Popular
                                • Users
                                • Groups
                                • Search
                                • Get Qt Extensions
                                • Unsolved