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.
  • T Offline
    T Offline
    TheHawk
    wrote on 17 Sept 2015, 11:13 last edited by TheHawk
    #1

    Hi,

    Sorry for this very simple question but I am failing horribly at it.

    So I have a function in my MainWindow.cpp; void test().

    void MainWindow::test()
    {
        progressBar->setEnabled(true);
        progressBar->setVisible(true);
        progressBar->setValue(50);
        ui->dockWidget->setWindowTitle("TEST");
    }
    

    The function is declared in mainwindow.h

    In jsfunctions.cpp I have mainwindow.h included and I try to call test(); . However, I have to make an object because otherwise I cant call it. The result of this is that the changes in UI that are made in the test() function are not visible, they are in a new object. I do not want this, I want to change the current UI that is visible (and I would like to avoid creating a new UI). I tried static (which gave errors) and tried to make signal/slot connections.

    I am sure its something very simple, but I just don't see it. Help would be greatly appreciated.

    1 Reply Last reply
    0
    • 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

                                  10/16

                                  18 Sept 2015, 09:46

                                  • Login

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