Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Qt for WebAssembly
  4. Failed to show GUI in WASM after JavaScript call
QtWS25 Last Chance

Failed to show GUI in WASM after JavaScript call

Scheduled Pinned Locked Moved Solved Qt for WebAssembly
8 Posts 2 Posters 592 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.
  • 8Observer88 Offline
    8Observer88 Offline
    8Observer8
    wrote on last edited by
    #1

    Hi,

    I made a minimal example to demonstrate a problem. I try to call alert() before showing GUI (one QLabel with "Hello" text). I see the alert() call but I don't see a QLabel. But if I comment this line: call_alert(); I see the QLabel. Is it a bug?

    #include <QtWidgets/QApplication>
    #include <QtWidgets/QLabel>
    #include <QtWidgets/QVBoxLayout>
    #include <QtWidgets/QWidget>
    #include <emscripten.h>
    
    EM_JS(void, call_alert, (),
          {
              alert("hello");
              throw "all done";
          })
    
    class Widget : public QWidget
    {
        Q_OBJECT
    
    public:
        Widget()
        {
            call_alert();
            QLabel *label = new QLabel("Hello");
            QVBoxLayout *layout = new QVBoxLayout();
            layout->addWidget(label);
            layout->addStretch();
            setLayout(layout);
        }
    };
    
    #include "main.moc"
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        Widget w;
        w.show();
        return a.exec();
    }
    
    JonBJ 1 Reply Last reply
    0
    • 8Observer88 8Observer8

      Hi,

      I made a minimal example to demonstrate a problem. I try to call alert() before showing GUI (one QLabel with "Hello" text). I see the alert() call but I don't see a QLabel. But if I comment this line: call_alert(); I see the QLabel. Is it a bug?

      #include <QtWidgets/QApplication>
      #include <QtWidgets/QLabel>
      #include <QtWidgets/QVBoxLayout>
      #include <QtWidgets/QWidget>
      #include <emscripten.h>
      
      EM_JS(void, call_alert, (),
            {
                alert("hello");
                throw "all done";
            })
      
      class Widget : public QWidget
      {
          Q_OBJECT
      
      public:
          Widget()
          {
              call_alert();
              QLabel *label = new QLabel("Hello");
              QVBoxLayout *layout = new QVBoxLayout();
              layout->addWidget(label);
              layout->addStretch();
              setLayout(layout);
          }
      };
      
      #include "main.moc"
      
      int main(int argc, char *argv[])
      {
          QApplication a(argc, argv);
          Widget w;
          w.show();
          return a.exec();
      }
      
      JonBJ Offline
      JonBJ Offline
      JonB
      wrote on last edited by
      #2

      @8Observer8
      You don't see the label at all, or you mean you don't see it till after you have dismissed the alert()?
      Are you wanting to test throw, or can that be removed from your example?

      8Observer88 2 Replies Last reply
      1
      • JonBJ JonB

        @8Observer8
        You don't see the label at all, or you mean you don't see it till after you have dismissed the alert()?
        Are you wanting to test throw, or can that be removed from your example?

        8Observer88 Offline
        8Observer88 Offline
        8Observer8
        wrote on last edited by
        #3

        @JonB said in Failed to show GUI in WASM after JavaScript call:

        You don't see the label at all

        Yes. I can see a label only if I comment this line call_alert(); It is not a problem with dismissing alert(). I replaced alert() with console.log(). I don't see a label but I see "hello" in the console:

        EM_JS(void, call_alert, (),
              {
                  console.log("hello");
                  throw "all done";
              })
        

        5a8b1763-dad5-48c1-8af7-04269b377311-image.png

        But if I comment call_alert(); like this:

            Widget()
            {
                // call_alert();
                QLabel *label = new QLabel("Hello");
                QVBoxLayout *layout = new QVBoxLayout();
                layout->addWidget(label);
                layout->addStretch();
                setLayout(layout);
            }
        

        I see the label:

        355462aa-7782-426e-b12a-4d62db3a0949-image.png

        1 Reply Last reply
        0
        • JonBJ JonB

          @8Observer8
          You don't see the label at all, or you mean you don't see it till after you have dismissed the alert()?
          Are you wanting to test throw, or can that be removed from your example?

          8Observer88 Offline
          8Observer88 Offline
          8Observer8
          wrote on last edited by
          #4

          @JonB said in Failed to show GUI in WASM after JavaScript call:

          Are you wanting to test throw, or can that be removed from your example?

          I don't know why I should call throw "all done"; I found it in the Emscripten docs. I tried to comment it:

          EM_JS(void, call_alert, (),
                {
                    console.log("hello");
                    // throw "all done";
                })
          

          I see a label now:

          71707517-c339-4d2e-bddf-0e2c65d82aa0-image.png

          It solved. Thank you very much!

          JonBJ 1 Reply Last reply
          0
          • 8Observer88 8Observer8 has marked this topic as solved on
          • 8Observer88 8Observer8

            @JonB said in Failed to show GUI in WASM after JavaScript call:

            Are you wanting to test throw, or can that be removed from your example?

            I don't know why I should call throw "all done"; I found it in the Emscripten docs. I tried to comment it:

            EM_JS(void, call_alert, (),
                  {
                      console.log("hello");
                      // throw "all done";
                  })
            

            I see a label now:

            71707517-c339-4d2e-bddf-0e2c65d82aa0-image.png

            It solved. Thank you very much!

            JonBJ Offline
            JonBJ Offline
            JonB
            wrote on last edited by JonB
            #5

            @8Observer8
            Well, that's why I asked about the throw! That causes a JS error and aborts the script. I don't know how that then impacts whatever state the WASM is in (I don't use), but it perhaps does not even return into your calling program?

            8Observer88 1 Reply Last reply
            2
            • JonBJ JonB

              @8Observer8
              Well, that's why I asked about the throw! That causes a JS error and aborts the script. I don't know how that then impacts whatever state the WASM is in (I don't use), but it perhaps does not even return into your calling program?

              8Observer88 Offline
              8Observer88 Offline
              8Observer8
              wrote on last edited by 8Observer8
              #6

              @JonB said in Failed to show GUI in WASM after JavaScript call:

              but it perhaps does not even return into your calling program?

              Yes, you are right! When I comment throw "all done" It returns to a calling program:

              EM_JS(void, call_alert, (),
                    {
                        console.log("hello");
                        // throw "all done";
                    })
              
              class Widget : public QWidget
              {
                  Q_OBJECT
              
              public:
                  Widget()
                  {
                      call_alert();
                      qDebug() << "Text in Widget";
              

              a57862ff-2438-4845-bbab-4eed9d240906-image.png
              And with throw "all done" it doesn't return:

              EM_JS(void, call_alert, (),
                    {
                        console.log("hello");
                        throw "all done";
                    })
              
              class Widget : public QWidget
              {
                  Q_OBJECT
              
              public:
                  Widget()
                  {
                      call_alert();
                      qDebug() << "Text in Widget";
              

              71b1f39d-e89c-4714-a035-2e431e1f40fc-image.png

              JonBJ 1 Reply Last reply
              0
              • 8Observer88 8Observer8

                @JonB said in Failed to show GUI in WASM after JavaScript call:

                but it perhaps does not even return into your calling program?

                Yes, you are right! When I comment throw "all done" It returns to a calling program:

                EM_JS(void, call_alert, (),
                      {
                          console.log("hello");
                          // throw "all done";
                      })
                
                class Widget : public QWidget
                {
                    Q_OBJECT
                
                public:
                    Widget()
                    {
                        call_alert();
                        qDebug() << "Text in Widget";
                

                a57862ff-2438-4845-bbab-4eed9d240906-image.png
                And with throw "all done" it doesn't return:

                EM_JS(void, call_alert, (),
                      {
                          console.log("hello");
                          throw "all done";
                      })
                
                class Widget : public QWidget
                {
                    Q_OBJECT
                
                public:
                    Widget()
                    {
                        call_alert();
                        qDebug() << "Text in Widget";
                

                71b1f39d-e89c-4714-a035-2e431e1f40fc-image.png

                JonBJ Offline
                JonBJ Offline
                JonB
                wrote on last edited by
                #7

                @8Observer8
                Now that you know that, you could protect yourself with "neat" code by enclosing anything in the body of that function inside try ... catch ... (with some warning/alert dialog), so that if it ever does something bad your calling code still continues.

                1 Reply Last reply
                1
                • 8Observer88 Offline
                  8Observer88 Offline
                  8Observer8
                  wrote on last edited by 8Observer8
                  #8

                  I wrote an example that play a sound using Web Audio API in Qt WebAssembly. It is a 2D sound but Web Audio API can play 3D sounds too. There are two buttons in this example: "Run" and "Play". The "Run" button must be pressed first and next the "Play" button must be pressed. You can run it by one click: https://replit.com/@8Observer8/play-audio-with-web-audio-api-qt6-cpp

                  a4eaf8a3-6b99-4c83-a597-8a85d1b4a559-image.png

                  main.cpp

                  #include <QtWidgets/QApplication>
                  #include <QtWidgets/QPushButton>
                  #include <QtWidgets/QVBoxLayout>
                  #include <QtWidgets/QWidget>
                  #include <emscripten.h>
                  
                  EM_JS(void, call_init, (),
                        {
                            my_init();
                        })
                  
                  EM_JS(void, call_run, (),
                        {
                            my_run();
                        })
                  
                  EM_JS(void, call_play, (),
                        {
                            playSound();
                        })
                  
                  class Widget : public QWidget
                  {
                      Q_OBJECT
                  
                  public:
                      Widget()
                      {
                          call_init();
                          runButton = new QPushButton("Run");
                          playButton = new QPushButton("Play");
                          playButton->setEnabled(false);
                          QVBoxLayout *vbox = new QVBoxLayout();
                          vbox->addWidget(runButton);
                          vbox->addWidget(playButton);
                          vbox->addStretch();
                          setLayout(vbox);
                          connect(runButton, &QPushButton::pressed, this, &Widget::runButtonClick);
                          connect(playButton, &QPushButton::pressed, this, &Widget::playButtonClick);
                      }
                  
                  private slots:
                  
                      void runButtonClick() {
                          call_run();
                          runButton->setEnabled(false);
                          playButton->setEnabled(true);
                      }
                  
                      void playButtonClick() {
                          call_play();
                      }
                  
                  private:
                      QPushButton *runButton;
                      QPushButton *playButton;
                  };
                  
                  #include "main.moc"
                  
                  int main(int argc, char *argv[])
                  {
                      QApplication a(argc, argv);
                      Widget w;
                      w.show();
                      return a.exec();
                  }
                  

                  my_script.js

                  let audioContext, decideArrayBuffer, decideAudioBuffer;
                  
                  async function my_init() {
                      console.log("init");
                      const decideResponse = await fetch("assets/sounds/decidemp3-14575.mp3");
                      decideArrayBuffer = await decideResponse.arrayBuffer();
                  }
                  
                  async function my_run() {
                      console.log("my run");
                      audioContext = new window.AudioContext();
                      decideAudioBuffer = await audioContext.decodeAudioData(decideArrayBuffer);
                  }
                  
                  function play(audioBuffer, isLoop = false) {
                      const source = audioContext.createBufferSource();
                      source.buffer = audioBuffer;
                      source.loop = isLoop;
                      const gain = audioContext.createGain();
                      source.connect(gain).connect(audioContext.destination);
                      gain.gain.value = 0.3;
                      source.start();
                      return source;
                  }
                  
                  function playSound() {
                      play(decideAudioBuffer);
                  }
                  
                  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