如何修改来自不同 class QT/C++ 的动态创建的 Widget 的值

how to modify values of dynamically created Widget from different class QT/C++

我知道这个问题已被问过几次,但那里给出的所有建议对我都不起作用。

概述: 我正在实施客户端服务器模型,并希望一旦消息到达服务器,它就应该显示在主 Qt 小部件中。 widget,我选择显示msg的是QLineEdit。

目前我的项目中有 3 个文件。 Agent_A 这是动态创建的所有小部件。然后Server_test基于QTCPServer和sockClient进行socket连接。我已从客户端成功收到有关 sockclient 的消息,但我不知道如何在 Agent_A 上正确显示它。

我在 socketClient.cpp 中添加了函数来更新 Agent_A 中的函数,但我想在创建实例时它总是为 NULL。

首先是我的一小段代码,然后是我尝试过的代码。也许你们可以输入一些有价值的信息。

Agent_A.h

class Agent_A : public QWidget
{
    Q_OBJECT

public:
    explicit Agent_A(QWidget *parent = 0);
     void setLineEdit( const& modifyStr ); // function to change lineEditCmdString
    ~Agent_A();

private:
    Ui::Agent_A *ui;
    QPushButton   *buttonStartServer;
    QPushButton   *buttonStopServer;
    // some other widgets 
    QLabel        *labelDisplay;
    QLineEdit     *lineEditCmdString;// I want to modify this value from sock client
    ServerTest   *server;

// few slots defined here
}

Agent_A.cpp

Agent_A::Agent_A( QWidget *parent ):
           QWidget( parent ),
           ui( new Ui::Agent_A )
{

  //define push buttons
  buttonStartServer = new QPushButton( tr( "&Start Server" ) );
  buttonStopServer  = new QPushButton( tr( "S&top" ));

  // some properties of other widgets defined here which is not relevant to mention here

  labelDisplay      = new QLabel( tr("DisplayMessgae" ) );
  lineEditCmdString    = new QLineEdit;// I want to modify this value on sock client
  labelDisplay->setBuddy( lineEditCmdString );

  // define signals and slots for Server
  connect( buttonStartServer, SIGNAL( clicked() ), this, SLOT( startServers() ) );
  connect( buttonStopServer,  SIGNAL( clicked() ), this, SLOT( stopServer()  ) );


// some layout here  which agian is not important to mention here.
 ui->setupUi( this );
}

Agent_A::~Agent_A()
{
    delete ui;
}

void Agent_A::setLineEdit( const Qstring& modifyStr )
{
   lineEditCmdString->setText( modifyStr );
}

// 现在由创建套接字的套接字客户端 sockClient.h

class SockClient : public QObject
{
  Q_OBJECT
public:
 explicit  SockClient( QObject *parent, QTcpSocket* socket= 0 );

 ~SockClient();

// I have added this function to update QLIneEdit in Agent_A
 void updateTextinParent(const QString &changeText);

signals:

private slots:
  void readClient();

private:
 // some other functions

  QTcpSocket *socketClient;
  quint16 nextBlockSize;

public slots:
};

sockclient.cpp

// constructor for sockclient and some other functions


SockClient::SockClient( QObject *parent, QTcpSocket* socket ) : QObject( parent )

{
   socketClient =  socket ;
  // create signals and slots
  connect( socketClient, SIGNAL( readyRead() ),    this, SLOT( readClient()  ) );
  connect( socketClient, SIGNAL( disconnected() ), this, SLOT( deleteLater() ) );

}

SockClient::~SockClient()
{
  socketClient->close();
  delete socketClient;
}

void SockClient::readClient()
{


  QDataStream clientReadStream( socketClient );
  clientReadStream.setVersion( QDataStream::Qt_4_3 );

  QString strRecvFrm;
  quint8 requestType;
  clientReadStream >> nextBlockSize;
  clientReadStream >> requestType;
  if( requestType == 'S')
    {

      clientReadStream >> strRecvFrm;
    }

  qDebug() << " the string is " << strRecvFrm; // Has recieved correctly from client
  updateTextinParent( strRecvFrmMops ); // Now trying to update widget

  socketClient->close();
}



 void SockClient::updateTextinParent( const QString& changeText )
    {

 if( this->parent() == 0 )
{
  qDebug() << " Parent not assigned"; // This get printed ..
}
      Agent_A *agent = qobject_cast< Agent_A* >( this->parent() ); // ?? is this is right way to do..?
      if( agent != NULL )
        {
          qDebug() << " we are in updateTextin" << changeText; // it never get printed so I assume  instance is always nULL
           agent->setLineEdit( changeText );
        }

    }

// ServerTest.cpp where instance of sockClient is created

    ServerTest::ServerTest(QObject *parent) : QObject(parent)
    {
      server = new QTcpServer( this ); 
    }

    void ServerTest::startServer()
    {
      connect( server, SIGNAL( newConnection() ), this, SLOT( incomingConnection() ) );
      if( !server->listen( QHostAddress::Any, 9999) )
      {
        qDebug() << " Server failed to get started";
      }
      else
      {
       qDebug() << " Server started";
      }
    }


    void ServerTest::stopServer()
    {
      server->close();
      qDebug() << "Server closed";
    }

    ServerTest::~ServerTest()
    {
      server->close();
      delete socketforClient;
      delete server;
    }

    void ServerTest::incomingConnection()
    {
      socketforClient = new SockClient(this->parent(), server->nextPendingConnection() );
    }
    Agent_A *agent = qobject_cast< Agent_A* >( this->parent() ); // ?? is this is right way to do..?
    if( agent != NULL )
    {
      qDebug() << " we are in updateTextin" << changeText; // it never get printed so I assume  instance is always nULL
      agent->setLineEdit( chnageText );
    }

能否请您先检查一下 parent 是否不为 NULL? 您能否展示创建 SockClient 实例的代码?

当然,你不能修改文本,因为你设置为 socketClient object this pointer in Server_test class 的父对象,所以父对象为 socketClient 将是 Server_test 但不是 Agent_A

所以为 socketClient 对象设置父对象 Agent_A:

socketforClient = new SockClient(this->parent(), server->nextPendingConnection());

或者您可以制定其他一些解决方法。

还有一个 注意:您在 startServer 方法而不是构造函数中连接到 newConnection() 信号。因此,如果我启动服务器,然后停止它们并再次启动,服务器将连接两次以发出信号,并且插槽 incomingConnection() 也将被调用两次。因此,您需要在 stopServer() 方法中断开信号或在 class 的构造函数中进行连接或使用 Qt::UniqueConnection.

这是一个非常简单的例子:

qt.pro:

TEMPLATE = app
TARGET = 
DEPENDPATH += .
INCLUDEPATH += .    
# Input
HEADERS += classes.h
SOURCES += main.cpp

classes.h:

#include <QObject>
#include <QDebug>

class Agent_A : public QObject
{
    Q_OBJECT

    public slots:
    void updateText(const QString &changeText) {
        qDebug() << "updateText: " << changeText;
    };
};

class SockClient : public QObject
{
    Q_OBJECT

    signals:
    void updateTextinParent(const QString &text);
 public:
    void incomingText(const QString &text) {
        emit updateTextinParent(text);
    };
};

main.cpp:

#include "classes.h"

int main(int argc, char **argv) {
    Agent_A *agent = new Agent_A;
    SockClient client;

    QObject::connect(&client, SIGNAL(updateTextinParent(const QString &)),
                     agent, SLOT(updateText(const QString &)));

    client.incomingText(QString("hello"));

    return 0;
}