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

[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.
  • jsulmJ Offline
    jsulmJ Offline
    jsulm
    Lifetime Qt Champion
    wrote on 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
    • JohanSoloJ JohanSolo

      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 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
      • JohanSoloJ Offline
        JohanSoloJ Offline
        JohanSolo
        wrote on 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 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?

          JohanSoloJ 1 Reply Last reply
          0
          • T TheHawk

            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?

            JohanSoloJ Offline
            JohanSoloJ Offline
            JohanSolo
            wrote on 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 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
              • JohanSoloJ Offline
                JohanSoloJ Offline
                JohanSolo
                wrote on 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 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
                  • JohanSoloJ Offline
                    JohanSoloJ Offline
                    JohanSolo
                    wrote on 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
                    1
                    • JohanSoloJ JohanSolo

                      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 last edited by
                      #12

                      @JohanSolo

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

                      Thanks :)

                      1 Reply Last reply
                      0
                      • JohanSoloJ Offline
                        JohanSoloJ Offline
                        JohanSolo
                        wrote on 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
                        1
                        • JohanSoloJ JohanSolo

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

                          T Offline
                          T Offline
                          TheHawk
                          wrote on 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
                          • JohanSoloJ Offline
                            JohanSoloJ Offline
                            JohanSolo
                            wrote on 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 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

                              • Login

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