简体   繁体   English

C ++ - QT - SIGNAL和SLOT理解

[英]C++ - QT - SIGNAL and SLOT understanding

I dont understand why this code doesnt work, maybe I haven't understanding the concept of SIGNAL and SLOT. 我不明白为什么这段代码不起作用,也许我还没有理解SIGNAL和SLOT的概念。

For example: I have a class named MainWindow , this class contains the ui components. 例如:我有一个名为MainWindow的类,这个类包含ui组件。 On this UI I can start and shut down a local server. 在此UI上,我可以启动和关闭本地服务器。 This server is defined in class MyServer . 此服务器在类MyServer定义。 The MainWindow class has a reference to MyServer class '&myServer' . MainWindow类引用了MyServer class '&myServer' If i do this in class mainwindow.cpp it works: 如果我在类mainwindow.cpp这样做,它的工作原理:

connect(ui->startServer,SIGNAL(clicked()),&myServer,SLOT(startServer()));
connect(ui->shutdownServer,SIGNAL(clicked()),&myServer,SLOT(shutDownServer()));

but this line not: 但这一行不是:

connect(&myServer,SIGNAL(signalMessage()), this, SLOT(slotUpdate()));

This Problem is: I have a SIGNAL named void signalMessage(); 这个问题是:我有一个名为void signalMessage();的SIGNAL void signalMessage(); in MyServer class, this signal is called in function void startServer(); 在MyServer类中,此函数在函数void startServer();调用void startServer(); and void shutDownServer() void shutDownServer()

signals:
    void signalMessage();

Normally after calling singalMessage() in MyServer class, the function slotUpdate() in MainWindow class should be called. 通常在MyServer类中调用singalMessage()之后,应该调用MainWindow类中的函数slotUpdate() But only signalMessage() is called and not slotUpadate() . 但是只signalMessage()而不是slotUpadate()

I hope anyone understand my problem. 我希望有人理解我的问题。 I can define slot and signal from MainWindow to MyServer but not reverse. 我可以定义从MainWindow到MyServer的插槽和信号,但不能反向。 :( :(

Edit: Okey, here some code for understanding my problem: 编辑: Okey,这里有一些代码用于理解我的问题:

mainwindow.h mainwindow.h

...
public:
    Ui::MainWindow *ui;
    MyServer myServer;


public slots:
    void slotUpdate();
...

mainwindow.cpp mainwindow.cpp

...
connect(ui->startServer,SIGNAL(clicked()),&myServer,SLOT(startServer()));
connect(ui->shutdownServer,SIGNAL(clicked()),&myServer,SLOT(shutDownServer()));
connect(&myServer,SIGNAL(signalMessage()), this, SLOT(slotUpdate()));
...
void MainWindow::slotUpdate()
{
    qDebug()<< "update()";
}
...

myserver.h myserver.h

public slots:
void startServer();//start the server on 127.0.0.1 port: 1234
void shutDownServer();//disconnect threads, shut down server

signals:
    void signalMessage();

myserver.cpp myserver.cpp

...
void MyServer::startServer(){
if(!this->listen(QHostAddress::Any,1234)){
    message.append("Could not start server, because server is already running");
}else{
    message.append("Listening...");
}

emit signalMessage();
}

...
void MyServer::signalMessage()
{
  qDebug() << "getMessage()";
}

In order to receive/emit signals: 为了接收/发出信号:

  1. Your class must be derived from QObject. 您的类必须从QObject派生。
  2. Your class must contain Q_OBJECT macro within its declaration. 您的类必须在其声明中包含Q_OBJECT宏。
  3. Header file with this class must be processed with moc (happens automatically, when you use qmake to generate project file). 必须使用moc处理此类的头文件(当您使用qmake生成项目文件时自动发生)。

Troubleshooting: 故障排除:

  1. If your header didn't originally have classes with signal/slots and you added them, you'll need to re-run qmake and regenerate Makefile(or visual studio project file). 如果您的标题最初没有包含信号/插槽的类并且您添加了它们,则需要重新运行qmake并重新生成Makefile(或visual studio项目文件)。
  2. Build debug versions of your program as console applications ( CONFIG += console in *.pro file) OR read debug output when you run your program. 将程序的调试版本构建为控制台应用程序( CONFIG += console * .pro文件中的CONFIG += console )或在运行程序时读取调试输出。 If you make a typo and qt can't connect to a signal it will print message about this problem either into debug output window or into stdout/stderr. 如果您输入错字并且qt无法连接到信号,它会将有关此问题的消息打印到调试输出窗口或stdout / stderr中。 That's the only way to notice that you failed to establish connection - connections are established when you RUN application (at runtime), not at compile-time. 这是注意到无法建立连接的唯一方法 - 在运行RUN应用程序(运行时)时建立连接,而不是在编译时建立连接。
  3. If you forget to add Q_OBJECT into class declaration or if you didn't run your headers (with classes that have signals/slot) through moc, you won't be able to connect to signals/slots. 如果您忘记将Q_OBJECT添加到类声明中,或者如果您没有通过moc运行标头(具有信号/插槽的类),则无法连接到信号/插槽。

There should be no need to write function body for signals. 不需要为信号编写函数体。 If you had to write function body, there's a problem with your code. 如果你必须编写函数体,那么你的代码就会出现问题。

Also: 也:
Qt has great documentation, so you should read it If you installed qt, documentation should be available via "assistant" program, and it is also available online . Qt有很好的文档,所以你应该阅读它如果你安装了qt,文档应该通过“助手”程序提供,它也可以在线获得

如果必须定义signalMessage函数,则意味着您没有在MyServer类定义中使用Q_OBJECT宏。

The Solution: 解决方案:

@arne: @arne:

"You provided an implementation for the function in the source file, ie void MyServer::signalMessage() { qDebug() << "getMessage()"; }. That is not correct." “你在源文件中为函数提供了一个实现,即void MyServer :: signalMessage(){qDebug()<<”getMessage()“;}。这是不正确的。”

"The connection statement was correct already. The fact that your sever receives the other signal indicates that the QOBJECT macro is there. Just remove the function implementation, ie the code I quoted in my previous comment (from the cpp file)" “连接语句已经是正确的。你的服务器收到另一个信号的事实表明QOBJECT宏在那里。只需删除函数实现,即我之前评论中引用的代码(来自cpp文件)”

So I must delete the implementation of singalMessage(); 所以我必须删除singalMessage();的实现singalMessage(); in .cpp file. 在.cpp文件中。 After this the line connect(&myServer, SIGNAL(singalMessage()), this, SLOT(slotUpdate())); 在此之后连接线(&myServer,SIGNAL(singalMessage()),这,SLOT(slotUpdate())); works. 作品。

You must not implement signalMessage yourself, as you have done in your myserver.cpp file. 您不能像在myserver.cpp文件中那样自己实现signalMessage This way, the one from QObject will be overridden and not signal is sent out. 这样,来自QObject那个将被覆盖,并且不发送信号。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM