1. Let’s talk about the answer first
Q_OBJECT does not need to be compiled in the .cpp file. It needs to be compiled in .h.
2. I recently moved the C# project to Linux, so I started reading Qt. Even a small problem can cause it to get stuck for several days. Post the first qt test program:
This is used to combine Qt with the front end.
This resource is required:
mainwindow.h
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include <QtWebEngineWidgets/QtWebEngineWidgets> #include <QtWebChannel/qwebchannel.h> QT_BEGIN_NAMESPACE namespace Ui {<!-- --> class MainWindow; } QT_END_NAMESPACE class MainWindow : public QMainWindow {<!-- --> Q_OBJECT public: MainWindow(QWidget *parent = nullptr); ~MainWindow(); QWebEngineView* m_view; QWebChannel* m_channel; private: Ui::MainWindow *ui; }; class MyClassOne : public QObject {<!-- --> //Q_OBJECT must be added Q_OBJECT public slots: Q_INVOKABLE void add(){<!-- --> QMessageBox::information(NULL, "class1", "class1"); } Q_INVOKABLE void showMsgBox(const QString & amp; message) {<!-- --> qDebug() << "Received message:" << message; } }; class MyClassTwo : public QObject {<!-- --> Q_OBJECT public slots: Q_INVOKABLE void add(){<!-- --> QMessageBox::information(NULL, "class2", "class2"); } }; #endif // MAINWINDOW_H
main.cpp
#include "mainwindow.h" #include <QApplication> int main(int argc, char *argv[]) {<!-- --> QApplication a(argc, argv); MainWindow w; w.show(); return a.exec(); }
mainwindow.cpp
#include "mainwindow.h" #include "./ui_mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) {<!-- --> ui->setupUi(this); m_view = new QWebEngineView(this); setCentralWidget(m_view); m_channel = new QWebChannel(this); MyClassOne *myclassone = new MyClassOne(); MyClassTwo *myclasstwo = new MyClassTwo(); m_channel->registerObject(QStringLiteral("myclassone"), (QObject*)myclassone); m_channel->registerObject(QStringLiteral("myclasstwo"), (QObject*)myclasstwo); m_view->page()->setWebChannel(m_channel); QString htmlPath = "D://Desktop/calculator_h5/calculator.html"; m_view->page()->load(htmlPath); connect(m_view->page(), & amp;QWebEnginePage::loadFinished, this, [this]() {<!-- --> //Execute JavaScript code m_view->page()->runJavaScript("js_func()"); }); // QMessageBox::information(nullptr, "title", "open the door"); } MainWindow::~MainWindow() {<!-- --> delete ui; }
CMakeLists.txt
cmake_minimum_required(VERSION 3.5) project(testQWebEngine VERSION 0.1 LANGUAGES CXX) set(CMAKE_AUTOUIC ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets) find_package(Qt${<!-- -->QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets) find_package(Qt5 REQUIRED COMPONENTS WebEngineWidgets) find_package(Qt5 REQUIRED COMPONENTS Core) find_package(Qt5 REQUIRED COMPONENTS WebChannel) set(PROJECT_SOURCES main.cpp mainwindow.cpp mainwindow.h mainwindow.ui ) if(${<!-- -->QT_VERSION_MAJOR} GREATER_EQUAL 6) qt_add_executable(testQWebEngine MANUAL_FINALIZATION ${<!-- -->PROJECT_SOURCES} ) # Define target properties for Android with Qt 6 as: # set_property(TARGET testQWebEngine APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR # ${<!-- -->CMAKE_CURRENT_SOURCE_DIR}/android) # For more information, see https://doc.qt.io/qt-6/qt-add-executable.html#target-creation else() if(ANDROID) add_library(testQWebEngine SHARED ${<!-- -->PROJECT_SOURCES} ) # Define properties for Android with Qt 5 after find_package() calls as: # set(ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android") else() add_executable(testQWebEngine ${<!-- -->PROJECT_SOURCES} ) endif() endif() target_link_libraries(testQWebEngine PRIVATE Qt${<!-- -->QT_VERSION_MAJOR}::Widgets) target_link_libraries(testQWebEngine PRIVATE Qt5::WebEngineWidgets) target_link_libraries(testQWebEngine PRIVATE Qt5::Core) # Qt for iOS sets MACOSX_BUNDLE_GUI_IDENTIFIER automatically since Qt 6.1. # If you are developing for iOS or macOS you should consider setting an # explicit, fixed bundle identifier manually though. if(${<!-- -->QT_VERSION} VERSION_LESS 6.1.0) set(BUNDLE_ID_OPTION MACOSX_BUNDLE_GUI_IDENTIFIER com.example.testQWebEngine) endif() set_target_properties(testQWebEngine PROPERTIES ${<!-- -->BUNDLE_ID_OPTION} MACOSX_BUNDLE_BUNDLE_VERSION ${<!-- -->PROJECT_VERSION} MACOSX_BUNDLE_SHORT_VERSION_STRING ${<!-- -->PROJECT_VERSION_MAJOR}.${<!-- -->PROJECT_VERSION_MINOR} MACOSX_BUNDLE TRUE WIN32_EXECUTABLE TRUE ) include(GNUInstallDirs) install(TARGETS testQWebEngine BUNDLE DESTINATION. LIBRARY DESTINATION ${<!-- -->CMAKE_INSTALL_LIBDIR} RUNTIME DESTINATION ${<!-- -->CMAKE_INSTALL_BINDIR} ) if(QT_VERSION_MAJOR EQUAL 6) qt_finalize_executable(testQWebEngine) endif()
html
<!DOCTYPE html> <h1>Hello, world!</h1> <head> <title></title> </head> <body> <div> <input value="class1" type="button" onclick="button_1();" /> <input value="class2" type="button" onclick="button_2();" /> </div> \t <script src="./qwebchannel.js"></script> <script type="text/javascript"> var myclass; var showMsgBox; //Perform initialization after the page is loaded document.addEventListener("DOMContentLoaded", function() {<!-- --> new QWebChannel(qt.webChannelTransport, function(channel) {<!-- --> one = channel.objects.myclassone; two = channel.objects.myclasstwo; }); }); function button_1() {<!-- --> one.add(); } \t function button_2() {<!-- --> two.add(); } function js_func(){<!-- --> alert('This is a pop-up message'); } </script> </body> </html>
js is in the directory where qt is installed, mine is here D:\Qt\Examples\Qt-5.15.2\webchannel\shared
It’s so troublesome to write a test example on the Internet, why not keep it simple? Haha, I wrote the simplest one.