Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt
  • Unsolved
Collapse
qtws26_logo

The Qt Event of the Year: Qt World Summit 2026

Save Your Spot >
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Calling c++ object functions through QWebChannel
Qt 6.12 LTS is out! See what's new in the release blog

Calling c++ object functions through QWebChannel

Scheduled Pinned Locked Moved Solved General and Desktop
6 Posts 3 Posters 925 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.
  • M Offline
    M Offline
    MyNameIsQt
    wrote on last edited by MyNameIsQt
    #1

    I made canvas.html like this: There are four buttons here. Each of these buttons triggers an event, and we want to connect this to the canvasViewer object's method and event. But it doesn't work.

    js: Uncaught TypeError: wpubEditor.buttonClicked is not a function
    

    The following code is part of canvas.html.

    <body>
          <div id="wrapper">
              <canvas id="myCanvas"></canvas>
              <div class="gradient-effect"></div>
              <div class="bottomControl">
                <div class="controlWrapper">
                    <div class="screen-controller left"></div>
                    <div class="screen-controller center">
                            <button class="ctnBtn" data-action="begin">Begin</button>
                            <button class="ctnBtn" data-action="prev">Previous</button>
                            <button class="ctnBtn" data-action="next">Next</button>
                            <button class="ctnBtn" data-action="end">End</button>
                            <div id="result"></div> 
                    </div>
                </div>
          </div>
      </body>
      <script src="qrc:///qtwebchannel/qwebchannel.js"></script>
    
      <script>
    
        if (typeof QWebChannel !== 'undefined') {
            new QWebChannel(qt.webChannelTransport, function (channel) {
                var canvasViewer = channel.objects.canvasViewer;
                console.error('canvasViewer:', canvasViewer);
    
                var buttons = document.getElementsByClassName("ctnBtn");
                for (var i = 0; i < buttons.length; i++) {
                  buttons[i].addEventListener("click", function () {
                    var action = this.getAttribute("data-action");
                    canvasViewer.buttonClicked(action);
                  });
                }
    
                var canvas = document.getElementById("myCanvas");
                var context = canvas.getContext("2d");
    
                context.drawImage(wpubEditor.imageObject, 0, 0);
            });
        } else {
              console.error("QWebChannel is not defined. Make sure qwebchannel.js is properly loaded.");
        }
    
        canvas.addEventListener('mouseenter', function() {
            gradientEffect.style.opacity = '0';
        });
    
        canvas.addEventListener('mouseleave', function() {
            gradientEffect.style.opacity = '0.5';
        });
      </script>
    

    The following code is part of htmlViewer object

    #include <QWebEngineView>
    #include <QWebChannel>
    ....
    class canvasViewer : public QMainWindow
    {
    Q_OBJECT
        ....
    
    public:
        canvasViewer(QWidget *parent = nullptr);
        ~canvasViewer();
    private slots:
        void buttonClicked(const QString& action);
    private:
        QWebEngineView *webView;
        QWebChannel *channel;
    }
    
    // .cpp
    canvasViewer::canvasViewer(QWidget *parent)
        : QMainWindow(parent)
         ...
        , webView(nullptr)
        , channel(nullptr)
    {
       ... 
    ui->setupUi(this);
    
        webView = new QWebEngineView(this); 
        setCentralWidget(webView);
    
        QString htmlPath = QFileInfo(__FILE__).dir().absolutePath() + "/canvas.html";
    
        QFile file(htmlPath);
        if (file.exists()) {
            webView->load(QUrl::fromLocalFile(htmlPath));
        } else {
            qDebug() << "Failed to load canvas.html. File not found.";
        }
    
        channel = new QWebChannel(webView->page());
        webView->page()->setWebChannel(channel);
        channel->registerObject("canvasViewer", this);
    }
    ....
    void canvasViewer::buttonClicked(const QString& action)
    {
        if (action == "begin") {
            qDebug() << "begin";
        } else if (action == "prev") {
            qDebug() << "prev";
        } else if (action == "next") {
            qDebug() << "next";
        } else if (action == "end") {
            qDebug() << "end";
        }
    }
    

    How can I fix this to solve it?

    B 1 Reply Last reply
    0
    • M MyNameIsQt

      I made canvas.html like this: There are four buttons here. Each of these buttons triggers an event, and we want to connect this to the canvasViewer object's method and event. But it doesn't work.

      js: Uncaught TypeError: wpubEditor.buttonClicked is not a function
      

      The following code is part of canvas.html.

      <body>
            <div id="wrapper">
                <canvas id="myCanvas"></canvas>
                <div class="gradient-effect"></div>
                <div class="bottomControl">
                  <div class="controlWrapper">
                      <div class="screen-controller left"></div>
                      <div class="screen-controller center">
                              <button class="ctnBtn" data-action="begin">Begin</button>
                              <button class="ctnBtn" data-action="prev">Previous</button>
                              <button class="ctnBtn" data-action="next">Next</button>
                              <button class="ctnBtn" data-action="end">End</button>
                              <div id="result"></div> 
                      </div>
                  </div>
            </div>
        </body>
        <script src="qrc:///qtwebchannel/qwebchannel.js"></script>
      
        <script>
      
          if (typeof QWebChannel !== 'undefined') {
              new QWebChannel(qt.webChannelTransport, function (channel) {
                  var canvasViewer = channel.objects.canvasViewer;
                  console.error('canvasViewer:', canvasViewer);
      
                  var buttons = document.getElementsByClassName("ctnBtn");
                  for (var i = 0; i < buttons.length; i++) {
                    buttons[i].addEventListener("click", function () {
                      var action = this.getAttribute("data-action");
                      canvasViewer.buttonClicked(action);
                    });
                  }
      
                  var canvas = document.getElementById("myCanvas");
                  var context = canvas.getContext("2d");
      
                  context.drawImage(wpubEditor.imageObject, 0, 0);
              });
          } else {
                console.error("QWebChannel is not defined. Make sure qwebchannel.js is properly loaded.");
          }
      
          canvas.addEventListener('mouseenter', function() {
              gradientEffect.style.opacity = '0';
          });
      
          canvas.addEventListener('mouseleave', function() {
              gradientEffect.style.opacity = '0.5';
          });
        </script>
      

      The following code is part of htmlViewer object

      #include <QWebEngineView>
      #include <QWebChannel>
      ....
      class canvasViewer : public QMainWindow
      {
      Q_OBJECT
          ....
      
      public:
          canvasViewer(QWidget *parent = nullptr);
          ~canvasViewer();
      private slots:
          void buttonClicked(const QString& action);
      private:
          QWebEngineView *webView;
          QWebChannel *channel;
      }
      
      // .cpp
      canvasViewer::canvasViewer(QWidget *parent)
          : QMainWindow(parent)
           ...
          , webView(nullptr)
          , channel(nullptr)
      {
         ... 
      ui->setupUi(this);
      
          webView = new QWebEngineView(this); 
          setCentralWidget(webView);
      
          QString htmlPath = QFileInfo(__FILE__).dir().absolutePath() + "/canvas.html";
      
          QFile file(htmlPath);
          if (file.exists()) {
              webView->load(QUrl::fromLocalFile(htmlPath));
          } else {
              qDebug() << "Failed to load canvas.html. File not found.";
          }
      
          channel = new QWebChannel(webView->page());
          webView->page()->setWebChannel(channel);
          channel->registerObject("canvasViewer", this);
      }
      ....
      void canvasViewer::buttonClicked(const QString& action)
      {
          if (action == "begin") {
              qDebug() << "begin";
          } else if (action == "prev") {
              qDebug() << "prev";
          } else if (action == "next") {
              qDebug() << "next";
          } else if (action == "end") {
              qDebug() << "end";
          }
      }
      

      How can I fix this to solve it?

      B Offline
      B Offline
      Bonnie
      wrote on last edited by
      #2

      @MyNameIsQt I haven't fully read your code, just to mention that a c++ object function called by webchannel needs to be declared as a slot function.

      M 1 Reply Last reply
      0
      • B Bonnie

        @MyNameIsQt I haven't fully read your code, just to mention that a c++ object function called by webchannel needs to be declared as a slot function.

        M Offline
        M Offline
        MyNameIsQt
        wrote on last edited by MyNameIsQt
        #3

        @Bonnie Oh, I made a really big mistake. I should have done it with public slots, but I made a mistake. thank you Now it works.

        public slots:
            void buttonClicked(const QString& action);
        
        B JonBJ 2 Replies Last reply
        0
        • M MyNameIsQt

          @Bonnie Oh, I made a really big mistake. I should have done it with public slots, but I made a mistake. thank you Now it works.

          public slots:
              void buttonClicked(const QString& action);
          
          B Offline
          B Offline
          Bonnie
          wrote on last edited by Bonnie
          #4

          @MyNameIsQt How about a public slot?
          BTW, where is wpubEditor (in the error message) come from? Cannot see that from your code.

          1 Reply Last reply
          0
          • M MyNameIsQt has marked this topic as solved on
          • M MyNameIsQt has marked this topic as solved on
          • M MyNameIsQt

            @Bonnie Oh, I made a really big mistake. I should have done it with public slots, but I made a mistake. thank you Now it works.

            public slots:
                void buttonClicked(const QString& action);
            
            JonBJ Offline
            JonBJ Offline
            JonB
            wrote on last edited by
            #5

            @MyNameIsQt
            I know nothing about WebChannel etc., but since you call canvasViewer.buttonClicked(action) how can that work if it's a private slot?

            M 1 Reply Last reply
            1
            • JonBJ JonB

              @MyNameIsQt
              I know nothing about WebChannel etc., but since you call canvasViewer.buttonClicked(action) how can that work if it's a private slot?

              M Offline
              M Offline
              MyNameIsQt
              wrote on last edited by
              #6

              @JonB I made a stupid mistake

              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
              • Unsolved