Calling C++ functions from JavaScript

In this recipe, we will learn how put our knowledge to use and create a functional login screen using Qt and MySQL.

How to do it…

Learn how to call C++ functions from JavaScript through the following steps:

  1. First, create a Qt Widgets Application project and, once you're done, open up the project file (.pro) and add the following modules to the project:
    QT += core gui webengine webenginewidgets
    
  2. Then, open up mainwindow.ui and delete the tool bar, menu bar, and status bar, as we don't need any of these in this example program.
  3. After that, add a vertical layout to the canvas, and then select the canvas and click on the Lay Out Vertically button on top of the canvas. Then, add a text label to the top of the vertical layout and set its text to Hello!. Also, make its font bigger by setting its stylesheet property:
    font: 75 26pt "MS Shell Dlg 2";
    How to do it…
  4. Next, go to File | New File or Project and create a resource file. Then, add an empty HTML file and all the JavaScript files, CSS files, font files, and so on belonging to jQuery, Boostrap, and Font Awesome to your project resources:
    How to do it…
  5. After that, open up your HTML file, which in this case is called test.html. First, link all the necessary JavaScript and CSS files to the HTML source code, between the <head> tags:
    <!DOCTYPE html>
    <html>
      <head>
        <script src="qrc:///qtwebchannel/qwebchannel.js"></script>
    
        <script src="js/jquery.min.js"></script>
        <script src="js/bootstrap.js"></script>
    
        <link rel="stylesheet" type="text/css"       href="css/bootstrap.css">
        <link rel="stylesheet" type="text/css" href="css/font-      awesome.css">
      </head>
      <body>
      </body>
    </html>
  6. Then, add the following JavaScript to the <head> element, wrapped between the <script> tags:
    <script>
      $(document).ready(function()
      {
        new QWebChannel(qt.webChannelTransport, function(channel)
          {
            mainWindow = channel.objects.mainWindow;
          });
    
          $("#login").click(function(e)
          {
            e.preventDefault();
    
            var user = $("#username").val();
            var pass = $("#password").val();
            mainWindow.showLoginInfo(user, pass);
          });
    
          $("#changeText").click(function(e)
          {
            e.preventDefault();
    
            mainWindow.changeQtText("Good bye!");
          });
      });
    </script>
  7. Then, add the following code to the <body> element:
    <div class="container-fluid">
      <form id="example-form" action="#" class="container-fluid">
        <div class="form-group">
          <div class="col-md-12"><h3>Call C++ Function from Javascript</h3></div>
    
          <div class="col-md-12"><div class="alert alert-info" role="alert"><i class="fa fa-info-circle"></i> <span id="infotext">Click "Login" to send username and password variables to C++.Click "Change Cpp Text" to change the text label on Qt GUI.</span></div></div>
    
          <div class="col-md-12">
            <label>Username:</label> <input id="username" type="text"><p />
          </div>
    
          <div class="col-md-12">
            <label>Password:</label> <input id="password" type="password"><p />
          </div>
    
          <div class="col-md-12">
            <button id="login" class="btn btn-success" type="button"><i class="fa fa-check"></i> Login</button> <button id="changeText" class="btn btn-primary" type="button"><i class="fa fa-pencil"></i> Change Cpp Text</button>
          </div>
        </div>
      </form>
    </div>
  8. Once you are done with that, let's open up mainwindow.h and add the following public functions to the MainWindow class:
    public:
      explicit MainWindow(QWidget *parent = 0);
      ~MainWindow();
    
      Q_INVOKABLE void changeQtText(QString newText);
      Q_INVOKABLE void showLoginInfo(QString user, QString pass);
    
  9. After that, open up mainwindow.cpp and add the following headers to the top of the source code:
    #include <QtWebEngineWidgets/QWebEngineView>
    #include <QtWebChannel/QWebChannel>
    #include <QMessageBox>
  10. Then, add the following code to the MainWindow constructor:
    MainWindow::MainWindow(QWidget *parent) :
      QMainWindow(parent),
      ui(new Ui::MainWindow)
    {
      qputenv("QTWEBENGINE_REMOTE_DEBUGGING", "1234");
    
      ui->setupUi(this);
    
      QWebEngineView* webview = new QWebEngineView();
      ui->verticalLayout->addWidget(webview);
    
      QWebChannel* webChannel = new QWebChannel();
      webChannel->registerObject("mainWindow", this);
      webview->page()->setWebChannel(webChannel);
    
      webview->page()->load(QUrl("qrc:///html/test.html"));
    }
  11. After that, we will declare what happens when changeQtText() and showLoginInfo() are called:
    void MainWindow::changeQtText(QString newText)
    {
      ui->label->setText(newText);
    }
    
    void MainWindow::showLoginInfo(QString user, QString pass)
    {
      QMessageBox::information(this, "Login info", "Username is " + user + " and password is " + pass);
    }
  12. Let's compile and run the program now; you should see something similar to the following screenshot. If you click on the Change Cpp Text button, the word Hello! at the top will change to Goodbye! If you click on the Login button, a message box will appear and show you exactly what you typed in the Username and Password input fields:
    How to do it…

How it works…

In this example, we used two JavaScript libraries, jQuery and Boostrap. We also used an iconic font package called Font Awesome. These third-party add-ons were used to make the HTML user interface more interesting and responsive to different screen resolutions. We also used jQuery to detect the document's ready status, as well as to obtain the values of the input fields. You can download jQuery from https://jquery.com/download, Bootstrap from http://getbootstrap.com/getting-started/#download, and Font Awesome from http://fontawesome.io.

Qt's WebEngine uses a mechanism called Web Channel that enables peer-to-peer communication between the C++ program and the HTML page. The WebEngine module provides a JavaScript library that makes the integration a lot easier. The JavaScript is embedded in your project's resource by default, so you don't need to import it into your project manually. You just have to include it in your HTML page by calling the following:

<script src="qrc:///qtwebchannel/qwebchannel.js"></script>

Once you have included qwebchannel.js, you can initialize the QWebChannel class and assign the Qt object we registered earlier in C++ to a JavaScript variable.

In C++, it as follows:

QWebChannel* webChannel = new QWebChannel();
webChannel->registerObject("mainWindow", this);
webview->page()->setWebChannel(webChannel);

Then in JavaScript, it is as follows:

new QWebChannel(qt.webChannelTransport, function(channel)
{
  mainWindow = channel.objects.mainWindow;
});

You may be wondering what this line means:

qputenv("QTWEBENGINE_REMOTE_DEBUGGING", "1234");

Qt's web engine uses the remote debugging method to check for JavaScript errors and other problems. The number 1234 defines the port number you want to use for remote debugging. Once you have enabled remote debugging, you can access the debugging page by opening up a Chromium-based web browser, such as Google Chrome (this will not work in Firefox and other browsers) and typing in http://127.0.0.1:1234. You will then see a page that look like this:

How it works…

The first page will display all the HTML pages that are currently running in your program, which in this case is test.html. Click on the page link and it will take you to another page for inspection. You can use this to check for CSS errors, JavaScript errors, missing files, and so on. Note that you should disable remote debugging once your program is bug-free and ready for deployment. This is because remote debugging takes time to initiate and it will increase your program's startup time.

If you want to call a C++ function from JavaScript, you must place the Q_INVOKABLE macro in front the function's declaration; otherwise, it will not work:

Q_INVOKABLE void changeQtText(QString newText);
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.222.185