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. Recursion on object creation
Forum Updated to NodeBB v4.3 + New Features

Recursion on object creation

Scheduled Pinned Locked Moved Unsolved General and Desktop
13 Posts 3 Posters 681 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.
  • JonBJ JonB

    @Nick-Shapper
    Hi. Please copy & paste code, not screenshots, it helps people to answer.

    Why are you creating a brand new MainWindow window object inside a MainWindow method? If you want to access the current instance use this, e.g. volumeValue = this->volume(); or just volumeValue = volume();.

    N Offline
    N Offline
    Nick Shapper
    wrote on last edited by
    #3

    @JonB I said that i'm creating it for a simplicity purposes, just imagine that it's not in a MainWindow class, but a Player class.
    Yeah, sorry about screenshot, i was in hurry.
    Yes, the method that you described is working, but it's not working from a different class, or it's just me being dumb and not knowing how to properly write the code

    Here:

    
    #include "mainwindow.h"
    #include "player.h"
    
    Player::Player(QWidget *parent) : QObject(parent),
        player()
    {
    
    
    
    
        mediaPlayer = new QMediaPlayer();
    
        mediaPlayer->setVolume(this->volume()); // SIGSEGV when this method is invoked
    }
    
    Player::~Player()
    {
        //delete player;
        //delete mediaPlayer;
    }
    
    int Player::volume()
    {
        MainWindow window;
        volumeValue = window.getVolume();
        return volumeValue;
    }
    
    
    
    
    void Player::setVolume(int volume)
    {
        mediaPlayer->setVolume(volume);
    }
    
    Christian EhrlicherC JonBJ 2 Replies Last reply
    0
    • N Nick Shapper

      @JonB I said that i'm creating it for a simplicity purposes, just imagine that it's not in a MainWindow class, but a Player class.
      Yeah, sorry about screenshot, i was in hurry.
      Yes, the method that you described is working, but it's not working from a different class, or it's just me being dumb and not knowing how to properly write the code

      Here:

      
      #include "mainwindow.h"
      #include "player.h"
      
      Player::Player(QWidget *parent) : QObject(parent),
          player()
      {
      
      
      
      
          mediaPlayer = new QMediaPlayer();
      
          mediaPlayer->setVolume(this->volume()); // SIGSEGV when this method is invoked
      }
      
      Player::~Player()
      {
          //delete player;
          //delete mediaPlayer;
      }
      
      int Player::volume()
      {
          MainWindow window;
          volumeValue = window.getVolume();
          return volumeValue;
      }
      
      
      
      
      void Player::setVolume(int volume)
      {
          mediaPlayer->setVolume(volume);
      }
      
      Christian EhrlicherC Online
      Christian EhrlicherC Online
      Christian Ehrlicher
      Lifetime Qt Champion
      wrote on last edited by
      #4

      @Nick-Shapper said in Recursion on object creation:

      int Player::volume()
      {
      MainWindow window;
      volumeValue = window.getVolume();
      return volumeValue;
      }

      What should this code do? Why do you create a local variable of type MainWindow here?

      Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
      Visit the Qt Academy at https://academy.qt.io/catalog

      N 1 Reply Last reply
      0
      • N Nick Shapper

        @JonB I said that i'm creating it for a simplicity purposes, just imagine that it's not in a MainWindow class, but a Player class.
        Yeah, sorry about screenshot, i was in hurry.
        Yes, the method that you described is working, but it's not working from a different class, or it's just me being dumb and not knowing how to properly write the code

        Here:

        
        #include "mainwindow.h"
        #include "player.h"
        
        Player::Player(QWidget *parent) : QObject(parent),
            player()
        {
        
        
        
        
            mediaPlayer = new QMediaPlayer();
        
            mediaPlayer->setVolume(this->volume()); // SIGSEGV when this method is invoked
        }
        
        Player::~Player()
        {
            //delete player;
            //delete mediaPlayer;
        }
        
        int Player::volume()
        {
            MainWindow window;
            volumeValue = window.getVolume();
            return volumeValue;
        }
        
        
        
        
        void Player::setVolume(int volume)
        {
            mediaPlayer->setVolume(volume);
        }
        
        JonBJ Offline
        JonBJ Offline
        JonB
        wrote on last edited by JonB
        #5

        @Nick-Shapper said in Recursion on object creation:

        @JonB I said that i'm creating it for a simplicity purposes, just imagine that it's not in a MainWindow class, but a Player class.

        You will not be want to create a new MainWindow object from the Player constructor, or for that matter from anywhere else.

        It's not much use us trying to "imagine" what you really have. Purely at a guess: if you need to access something in an existing MainWindow (or whatever) instance you need the pointer to that instance. Try to understand the difference between accessing an existing object versus creating a new instance, my suspicion is that is where your issue lies.

        You should never be including mainwindow.h in any .cpp file other than mainwindow.cpp and you should never be accessing the main window object from another class. Pass a parameter to other classes if required, though this should never be done for a main window. Redesign your code if you think it is necessary for other classes to see anything about the main window, because they should not.

        If i declare window as a pointer, i'm getting SIGSEGV.

        Declaring something never causes a SIGSEGV. If you are getting one show us the stack trace pane to understand exactly what is happening and where it crashes. In this case, my guess is during the call to MainWindow::volume() from the new instance you incorrectly create, that accesses ui->volumeSlider->.... But that new instance has not had called setupUi(), so ui->volumeSlider == nullptr, hence a SIGSEGV on attempting to dereference.

        N 1 Reply Last reply
        1
        • Christian EhrlicherC Christian Ehrlicher

          @Nick-Shapper said in Recursion on object creation:

          int Player::volume()
          {
          MainWindow window;
          volumeValue = window.getVolume();
          return volumeValue;
          }

          What should this code do? Why do you create a local variable of type MainWindow here?

          N Offline
          N Offline
          Nick Shapper
          wrote on last edited by
          #6

          @Christian-Ehrlicher It should get a value of volume from a slider in UI. Look at a volume() in my first post. Basically it's a simple getter function

          JonBJ 2 Replies Last reply
          0
          • N Nick Shapper

            @Christian-Ehrlicher It should get a value of volume from a slider in UI. Look at a volume() in my first post. Basically it's a simple getter function

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

            @Nick-Shapper said in Recursion on object creation:

            It should get a value of volume from a slider in UI. Look at a volume() in my first post. Basically it's a simple getter function

            Which you should never do by having a class try to access the main window object. It's just bad design.

            But if you are not going to change it to make it good: if you want to access the main window in another class, like you show, pass it as an extra explicit parameter to the other class's constructor, or provide a setter method from the other class so that the main window can set it. But in the latter case you will not be able to access it during the other class's constructor, which you are currently trying to do. If you are only going to access the main window's volume() method, pass that instead of attempting to pass the main window object.

            1 Reply Last reply
            0
            • N Nick Shapper

              @Christian-Ehrlicher It should get a value of volume from a slider in UI. Look at a volume() in my first post. Basically it's a simple getter function

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

              @Nick-Shapper
              Presumably here you want the player to take on the same volume as you have set somewhere in the main window. Do not approach that by trying to read the actual widget in the main window's ui. Instead suggest one of:

              • If the main window creates the Player, have that export a "volume setter" (or an extra parameter to the constructor) and have the main window call that on the created Player instance passing it the desired volume from its ui.

              • Create some kind of "settings" object of your own. Have the main window set the volume in that as its UI slider changes. Have the Player object pick up the desired volume from that "settings" object.

              1 Reply Last reply
              0
              • JonBJ JonB

                @Nick-Shapper said in Recursion on object creation:

                @JonB I said that i'm creating it for a simplicity purposes, just imagine that it's not in a MainWindow class, but a Player class.

                You will not be want to create a new MainWindow object from the Player constructor, or for that matter from anywhere else.

                It's not much use us trying to "imagine" what you really have. Purely at a guess: if you need to access something in an existing MainWindow (or whatever) instance you need the pointer to that instance. Try to understand the difference between accessing an existing object versus creating a new instance, my suspicion is that is where your issue lies.

                You should never be including mainwindow.h in any .cpp file other than mainwindow.cpp and you should never be accessing the main window object from another class. Pass a parameter to other classes if required, though this should never be done for a main window. Redesign your code if you think it is necessary for other classes to see anything about the main window, because they should not.

                If i declare window as a pointer, i'm getting SIGSEGV.

                Declaring something never causes a SIGSEGV. If you are getting one show us the stack trace pane to understand exactly what is happening and where it crashes. In this case, my guess is during the call to MainWindow::volume() from the new instance you incorrectly create, that accesses ui->volumeSlider->.... But that new instance has not had called setupUi(), so ui->volumeSlider == nullptr, hence a SIGSEGV on attempting to dereference.

                N Offline
                N Offline
                Nick Shapper
                wrote on last edited by
                #9

                @JonB Here how it looks in a debugger and a line where it thinks a crash occurred
                Also, by " If you are only going to access the main window's volume() method, pass that instead of attempting to pass the main window object." you mean that i should pass a function as a parameter?
                Screenshot_2.jpg
                And here's also how i create a Player object in MainWindow class
                Screenshot_3.jpg

                JonBJ 1 Reply Last reply
                0
                • N Nick Shapper

                  @JonB Here how it looks in a debugger and a line where it thinks a crash occurred
                  Also, by " If you are only going to access the main window's volume() method, pass that instead of attempting to pass the main window object." you mean that i should pass a function as a parameter?
                  Screenshot_2.jpg
                  And here's also how i create a Player object in MainWindow class
                  Screenshot_3.jpg

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

                  @Nick-Shapper
                  The screenshot shows exactly what I expected:

                  In this case, my guess is during the call to MainWindow::volume() from the new instance you incorrectly create, that accesses ui->volumeSlider->.... But that new instance has not had called setupUi(), so ui->volumeSlider == nullptr, hence a SIGSEGV on attempting to dereference.

                  This will go away when you correctly no longer try to create any new MainWindow instance.

                  Also, by " If you are only going to access the main window's volume() method, pass that instead of attempting to pass the main window object." you mean that i should pass a function as a parameter?

                  No, just pass the value: volume() (not volume). So if you create the Player from MainWindow somewhere you might have:

                  this->player = new Player(this);
                  player->setVolume(this->volume());
                  // or
                  this->player = new Player(this->volume(), this);
                  
                  N 1 Reply Last reply
                  1
                  • JonBJ JonB

                    @Nick-Shapper
                    The screenshot shows exactly what I expected:

                    In this case, my guess is during the call to MainWindow::volume() from the new instance you incorrectly create, that accesses ui->volumeSlider->.... But that new instance has not had called setupUi(), so ui->volumeSlider == nullptr, hence a SIGSEGV on attempting to dereference.

                    This will go away when you correctly no longer try to create any new MainWindow instance.

                    Also, by " If you are only going to access the main window's volume() method, pass that instead of attempting to pass the main window object." you mean that i should pass a function as a parameter?

                    No, just pass the value: volume() (not volume). So if you create the Player from MainWindow somewhere you might have:

                    this->player = new Player(this);
                    player->setVolume(this->volume());
                    // or
                    this->player = new Player(this->volume(), this);
                    
                    N Offline
                    N Offline
                    Nick Shapper
                    wrote on last edited by Nick Shapper
                    #11

                    @JonB Ok, now i see a problem. I'll try to deduce what you said and somehow redesign my code.
                    Here's one more question. Is there a page in Qt docs that describes how to properly work with that *ui and how to properly design communication between ui and other objects? Or just a good example from docs will do. I searched but didn't find anything on that matter. It's pretty complicated stuff and should be documented

                    JonBJ 1 Reply Last reply
                    0
                    • N Nick Shapper

                      @JonB Ok, now i see a problem. I'll try to deduce what you said and somehow redesign my code.
                      Here's one more question. Is there a page in Qt docs that describes how to properly work with that *ui and how to properly design communication between ui and other objects? Or just a good example from docs will do. I searched but didn't find anything on that matter. It's pretty complicated stuff and should be documented

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

                      @Nick-Shapper
                      No, there is not (that I am aware of). This is not specifically a Qt issue, it is general design principles that I and others have learned over a lifetime of programming! :) You might look up general "OOP" (object-oriented programming) principles.

                      Your principle of encapsulating access between classes via getter & setter methods was already good. It's just that it's not something to use to gain access to the main window! That may be a "parent" to other QObjects (e.g. passed as parent to Player's constructor), but the general rule is that parents may access child methods but children should not, and should not need to, access their parent. Try to design Player so that it might be used from anywhere, e.g. it should still function if, say, there were no main window to call.

                      In any case, the most important lesson to learn here is that passing a pointer to an existing object/instance is quite different from creating a brand new object/instance. Even if your code had not crashed, the result returned by window::volume() on your freshly created MainWindow instance would have borne no relationship to the value of the slider in the actual MainWindow instance already in existence.

                      N 1 Reply Last reply
                      1
                      • JonBJ JonB

                        @Nick-Shapper
                        No, there is not (that I am aware of). This is not specifically a Qt issue, it is general design principles that I and others have learned over a lifetime of programming! :) You might look up general "OOP" (object-oriented programming) principles.

                        Your principle of encapsulating access between classes via getter & setter methods was already good. It's just that it's not something to use to gain access to the main window! That may be a "parent" to other QObjects (e.g. passed as parent to Player's constructor), but the general rule is that parents may access child methods but children should not, and should not need to, access their parent. Try to design Player so that it might be used from anywhere, e.g. it should still function if, say, there were no main window to call.

                        In any case, the most important lesson to learn here is that passing a pointer to an existing object/instance is quite different from creating a brand new object/instance. Even if your code had not crashed, the result returned by window::volume() on your freshly created MainWindow instance would have borne no relationship to the value of the slider in the actual MainWindow instance already in existence.

                        N Offline
                        N Offline
                        Nick Shapper
                        wrote on last edited by
                        #13

                        @JonB said in Recursion on object creation:

                        @Nick-Shapper
                        No, there is not (that I am aware of). This is not specifically a Qt issue, it is general design principles that I and others have learned over a lifetime of programming! :) You might look up general "OOP" (object-oriented programming) principles.

                        Your principle of encapsulating access between classes via getter & setter methods was already good. It's just that it's not something to use to gain access to the main window! That may be a "parent" to other QObjects (e.g. passed as parent to Player's constructor), but the general rule is that parents may access child methods but children should not, and should not need to, access their parent. Try to design Player so that it might be used from anywhere, e.g. it should still function if, say, there were no main window to call.

                        In any case, the most important lesson to learn here is that passing a pointer to an existing object/instance is quite different from creating a brand new object/instance. Even if your code had not crashed, the result returned by window::volume() on your freshly created MainWindow instance would have borne no relationship to the value of the slider in the actual MainWindow instance already in existence.

                        Ok, now that makes sense. So basically i gotta design Player so that it would be completely independent and also could be used from anywhere, right?

                        1 Reply Last reply
                        2

                        • Login

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