Is it possible to create a pointer to the main window?



  • Hi I have a Qt Application and ROS Action Server which takes in requests and invoke some features of my application like displaying dialog windows etc,.

    My Main method is something like this:

    int main(int argc, char *argv[]) {
    qInstallMessageHandler(myMessageOutput);
    
    if( !ros::isInitialized() )
      {
        ros::init( argc, argv, "APS");//, ros::init_options::AnonymousName );
        ros::param::set("/use_gui", true);
        
      }
    QApplication a(argc, argv);
    w = new MainWindow;
    w->show();
    
    GUIActionServer as_(ros::this_node::getName(), w);// Here I start my action server based on the reqests i have to invoke some functionalites in my Main window
        
    int result = a.exec();
    
    delete w;
    w=NULL;
    
    return result;
    

    }

    GUIActionServer.h is as follows:

    #ifndef GUIACTIONSERVER_H
    #define GUIACTIONSERVER_H
    #include <ros/ros.h>
    #include <actionlib/server/simple_action_server.h>
    #include <aps_msgs/MoveArmAction.h>
    #include <moveit_msgs/MoveItErrorCodes.h>
    #include <configdialog.h>
    #include <QDebug>
    #include "mainwindow.h"
    
    #include <QObject>
    
    class GUIActionServer : public QObject
    {
        Q_OBJECT
    
    public:
        GUIActionServer(std::string name, MainWindow* w);
        ~GUIActionServer();
        void executeCB(const aps_msgs::MoveArmGoalConstPtr &goal);
    
    protected:
    
      ros::NodeHandle nh_;
      // NodeHandle instance must be created before this line. Otherwise strange error may occur.
      actionlib::SimpleActionServer<aps_msgs::MoveArmAction> as_; 
      std::string action_name_;
      // create messages that are used to published feedback/result
      aps_msgs::MoveArmFeedback feedback_;
      aps_msgs::MoveArmResult result_;
      MainWindow* sw;
    };
    
    #endif // GUIACTIONSERVER_H
    

    GUIActionServer.cpp is as follows:

    #include "guiactionserver.h"
    
    GUIActionServer::GUIActionServer(std::string name, MainWindow* w) :
        as_(nh_, name, boost::bind(&GUIActionServer::executeCB, this, _1), false),
        action_name_(name)
      {
        as_.start();
        sw = w;
      }
    
      GUIActionServer::~GUIActionServer(){};
    
      void GUIActionServer::executeCB(const aps_msgs::MoveArmGoalConstPtr &goal)
      {
        // helper variables
        ros::Rate r(1);
        bool success = true;
    
        feedback_.state = "In Execute Callback method";
    
        std::cout << goal->exec_path.at(0).position.x << std::endl;
    
        as_.publishFeedback(feedback_);
        r.sleep();
    
        if(sw){
            sw->testDialog();
        }
        
        sw = NULL;
    
        success = true;
    
        if(success)
        {
          result_.error_code.val = 1;
          ROS_INFO("%s: Succeeded", action_name_.c_str());
          // set the action state to succeeded
          as_.setSucceeded(result_);
        }
      }
    

    When I am using the above code application is not stable and got the following error

    QObject::connect: Cannot queue arguments of type 'QTextBlock'
    (Make sure 'QTextBlock' is registered using qRegisterMetaType().)
    QObject::connect: Cannot queue arguments of type 'QTextCursor'
    (Make sure 'QTextCursor' is registered using qRegisterMetaType().)
    Segmentation fault (core dumped)

    Any ideas will be much appreciated. Thanks in advance


  • Lifetime Qt Champion

    Hi,

    Looks like you are already doing something fishy with some signals and slots. Can you show the code where you establish these connections ?



  • GUIActionServer as_(ros::this_node::getName(), w);// Where i creates my obj to Action Server and pass the mainwindow 'w'.

    // Assigns to another pointer in GUIActionServer Mainwindow* sw;
    sw = w;

    // Calls the testDialog method in GUIActionServer::executeCB function which popsup Dialog in mainwindow
    if(sw){
    sw->testDialog();
    }

    Hope this looks simple rather than going through the whole code...


  • Lifetime Qt Champion

    Except your error has nothing to do with the code you posted and more likely with the rest your didn't post.

    Like the error says, you are trying to use a type that is not known to the signal and slots system so you likely did some connect calls somewhere in your code. That's the part that must be checked.



  • If I remove my GUIActionServer then the application works fine. This error popsup only when i include this GUIActionServer thingy. I suspect there might be some wrong thing in the way i work with threads and pointers.

    I have one General question MainWindow has its own thread and GUIActionServer will also up and running. Can i invoke the main thread whenever my Action Server wants to talk to it?


  • Lifetime Qt Champion

    No, you cannot modify directly GUI elements from another thread. You should use signals and slots for that.

    But still, the connect error should be investigated.



  • In that case, I think this might be causing the error:

    void MainWindow::testDialog(){
        ConfigDialog cond;
        qInfo() << "From Action Server obj is created";
        cond.setMode("View");
        qInfo() << "Mode is " << cond.mode.c_str();
        cond.updateConfigDialog();
        cond.setModal(false);
        cond.exec();
    }
    

    I am creating a new dialog whenever i receive a request from the action server. Mightbe it is failing here to connect Qobjects because this is a pointer to mainwindow. Am I correct?


  • Lifetime Qt Champion

    No you're not.

    Connection error like that have nothing to do with the fact that you are using a pointer for your MainWindow.

    Again, do you have any connect statement somewhere in your code ?



  • I have these connections which are present in the ConfigDialog.ui

    <connections>
      <connection>
       <sender>buttonBox</sender>
       <signal>accepted()</signal>
       <receiver>ConfigDialog</receiver>
       <slot>accept()</slot>
       <hints>
        <hint type="sourcelabel">
         <x>248</x>
         <y>254</y>
        </hint>
        <hint type="destinationlabel">
         <x>157</x>
         <y>274</y>
        </hint>
       </hints>
      </connection>
      <connection>
       <sender>buttonBox</sender>
       <signal>rejected()</signal>
       <receiver>ConfigDialog</receiver>
       <slot>reject()</slot>
       <hints>
        <hint type="sourcelabel">
         <x>316</x>
         <y>260</y>
        </hint>
        <hint type="destinationlabel">
         <x>286</x>
         <y>274</y>
        </hint>
       </hints>
      </connection>
     </connections>
    

    Other than these i haven't defined any custom connections. I have searched my code but I am unable to find QTextBlock and QTextCursor defined



  • I got it..... I have made a mistake I was calling the testDialog using normal method instead of signals and slots. Now i have connected as follows:

    GUIActionServer::GUIActionServer(std::string name, MainWindow* w) :
        as_(nh_, name, boost::bind(&GUIActionServer::executeCB, this, _1), false),
        action_name_(name)
      {
        as_.start();
        sw = w;
    // Connecting using signals and slots here 
    // ActionInvoked is a signal in GUIActionServer and testDialog is a public slot in MainWindow
        QObject::connect(this, &GUIActionServer::actionInvoked, w, &MainWindow::testDialog);
      }
    
      GUIActionServer::~GUIActionServer(){};
    
      void GUIActionServer::executeCB(const aps_msgs::MoveArmGoalConstPtr &goal)
      {
        // helper variables
        ros::Rate r(1);
        bool success = true;
    
        feedback_.state = "In Execute Callback method";
    
        std::cout << goal->exec_path.at(0).position.x << std::endl;
    
        as_.publishFeedback(feedback_);
        r.sleep();
    // If main window is opened then I will call the signal.
        if(sw){
            actionInvoked();
        }
        
        sw = NULL;
    
        success = true;
    
        if(success)
        {
          result_.error_code.val = 1;
          ROS_INFO("%s: Succeeded", action_name_.c_str());
          // set the action state to succeeded
          as_.setSucceeded(result_);
        }
      }
    

    The previous issue is related to threading i guess.... Now I am not receiving any error the code works fine. Thank you for your support @SGaist


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.