标签: qt-signals

当接收器忙时,Qt信号会发生什么?

在我的应用程序中,我有一个实例QTimer,其timeout()信号连接到主窗口对象中的一个插槽,导致它定期被调用.插槽用相机拍照并将其保存到磁盘.

我想知道QTimer当接收器(主线程上的窗口对象)当前正忙时(如同拍摄并保存前一张图片),如果发出信号(来自执行的单独线程,我推测)会发生什么.在前一个呼叫终止后,呼叫是否排队并执行?整个想法是让它定期运行,但这些调用可以排队,然后当控制返回到事件循环时随机调用,导致混乱吗?我怎么能避免呢?从理论上讲,插槽应该快速执行,但是假设硬件有一些问题并且存在停顿.

我希望在这种情况下调用被丢弃而不是排队,更有用的是能够在发生时作出反应(警告用户,终止执行).

c++ qt multithreading qt-signals qtcore

10
推荐指数
1
解决办法
4086
查看次数

使用具有多重继承的Qt信号和插槽

我有一个class(MyClass)从Qt内置对象(QGraphicsTextItem)继承其大部分功能.QGraphicsTextItem从中间接继承QObject.MyClass还实现了一个接口MyInterface.

class MyClass : public QGraphicsTextItem, public MyInterface
Run Code Online (Sandbox Code Playgroud)

我需要能够使用connectdisconnect开启MyInterface*.但现在看来,connectdisconnect只在工作QObject*实例.由于Qt不支持从QObject的派生类多继承,我不能得到MyInterfaceQObject.(无论如何,这对于界面也没有多大意义.)

有一个问题的讨论在网上,但IMO所提出的解决方案是在通常情况下(访问通过其接口的对象)相当无用的,因为你无法连接的信号和槽MyInterface*,但必须将它转换为派生类型.由于MyClass是许多MyInterface衍生类中的一个,这将需要"代码 - 臭"如果 - 这个 - 演绎 - 否则 - 如果 - 那个 - 演绎到那个语句并且破坏了接口的目的.

这个限制有一个很好的解决方案吗?

更新:我注意到,如果我dynamic_castMyInterface*QObject*(因为我知道所有MyInterface的派生类也最终从继承QObject,它似乎工作即:

MyInterface *my_interface_instance = GetInstance();
connect(dynamic_cast<QObject*>(my_interface_instance), …
Run Code Online (Sandbox Code Playgroud)

c++ qt multiple-inheritance qt-signals

9
推荐指数
2
解决办法
7191
查看次数

C++ Qt信号和插槽没有触发

我的Qt程序很难将按钮信号连接到我的插槽.我的代码是:

Main.cpp的

#include <QtGui/QApplication>
#include "MainWidget.h"

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    MainWidget mainWidget;
    mainWidget.show();

    return app.exec();
}
Run Code Online (Sandbox Code Playgroud)

MainWidget.h

#ifndef MAINWIDGET_H
#define MAINWIDGET_H

#include <QWidget>

class MainWidget : public QWidget
{
public:
    MainWidget();

public slots:
    void bAdvice_clicked();
    void bWeather_clicked();
    void bNextMeeting_clicked();
    void bQuit_clicked();
};

#endif // MAINWIDGET_H
Run Code Online (Sandbox Code Playgroud)

MainWidget.cpp

#include "MainWidget.h"
#include <QMessageBox>
#include <QPushButton>
#include <QTextEdit>
#include <QVBoxLayout>

MainWidget::MainWidget()
{
    QLayout *layout = new QVBoxLayout();
    this->setLayout(layout);

    QTextEdit *message = new QTextEdit();
    layout->addWidget(message);

    QPushButton *bAdvice = new QPushButton("Advice"); …
Run Code Online (Sandbox Code Playgroud)

c++ qt qt-signals

9
推荐指数
1
解决办法
1万
查看次数

扩展共同基础:Diamond继承与QObject

我想我在这里遇到了一种钻石继承问题.

Qt提供了几个旋转框,用于整数值,用于双精度以及日期/时间.它们都来自QAbstractSpinBox:

#include <QtWidgets/QSpinBox>
class QSpinBox:
    public QAbstractSpinBox {

};

#include <QtWidgets/QDoubleSpinBox>
class QDoubleSpinBox:
    public QAbstractSpinBox {

};
Run Code Online (Sandbox Code Playgroud)

现在我想添加一些通用于所有旋转框的功能,在这个具体的例子中,一个按钮将旋转框恢复到最小(因此是specialValueText).所以我也从中衍生出来QAbstractSpinBox并想出了这样的东西:

class AbstractRevertibleSpinBox:
    public QAbstractSpinBox {

    public:
        RevertibleSpinBox() {
            /* Use abstract base: */
            QAction *revertAction = new QAction(this);
            QAbstractSpinBox::lineEdit()->addAction(
                revertAction, QLineEdit::TrailingAction);
            /* ... */
        }

    public slots:
        virtual void revert()  = 0;
}
Run Code Online (Sandbox Code Playgroud)

revert()包含应该实现如何恢复不同旋转框的纯净.例如,setValue(double)用于QDoubleSpinBoxsetDate(QDate)用于QDateEdit.然后我以明显的方式为我需要的所有旋转框派生了相应的类,如下所示:

class RevertibleSpinBox:
    public QSpinBox,
    public AbstractRevertibleSpinBox {

    protected:
        void revert() {
            /* Revert …
Run Code Online (Sandbox Code Playgroud)

c++ inheritance qt qwidget qt-signals

9
推荐指数
1
解决办法
517
查看次数

Qt:信号的返回值有效,为什么官方文件说不可能/被禁止?

Qt文档说,信号的返回值是不可能的:

信号由moc自动生成,不得在.cpp文件中实现.他们永远不会有返回类型(即使用void).

相关的SO问题:

  1. Qt信号可以返回一个值吗?
  2. Qt:槽返回值的含义?

但是,根据我的试验(Qt 4.8.1),我可以告诉返回值确实有效:

  1. 如果signal/slot在同一个线程中,则ConnectionType可能是 Qt::AutoConnection
  2. 我需要使用不同线程中的信号/插槽 Qt::BlockingQueuedConnection

所以在我的代码中我通过调用信号

QString dp = emit WscAircrafts::signalAircraftsJsonArray();
Run Code Online (Sandbox Code Playgroud)

并且信号moc返回a QString,

QString _t0;
void *_a[] = { const_cast<void*>(reinterpret_cast<const void*>(&_t0)) };
QMetaObject::activate(this, &staticMetaObject, 0, _a);
return _t0;
Run Code Online (Sandbox Code Playgroud)

这里是它传回的插槽moc QString

case 4: { QString _r = _t->slotAircraftJsonArray();
  if (_a[0]) *reinterpret_cast< QString*>(_a[0]) = _r; }  break;
Run Code Online (Sandbox Code Playgroud)

所有这一切似乎都很直接,为什么这与文档的矛盾呢?使用返回值的问题在哪里?如上所述,在我的代码中,这似乎有效.

qt qt4 qt-signals

8
推荐指数
1
解决办法
2510
查看次数

如何在Qt中创建动态信号和插槽?

Qt中的信号/槽机制是一种静态机制.这些类必须由moc编译器预处理.
现在我想在运行时动态创建信号和插槽.
我已经有了一个可行的解决方案,但我觉得我觉得它像黑客,虽然我使用的是公开的方法.
这是动态插槽的代码:

bool DynamicQObject::connectDynamicSlot(const QString &objectName, QObject *pSourceObject, QMetaMethod signalMethod)
{
    QByteArray slotName = signalMethod.name().prepend("on").append("(");
    QStringList parameters;
    for (int i = 0, j = signalMethod.parameterCount(); i < j; ++i)
    {
        parameters << QMetaType::typeName(signalMethod.parameterType(i));
    }
    slotName.append(parameters.join(",")).append(")");
    QByteArray theSignal = QMetaObject::normalizedSignature(signalMethod.methodSignature().constData());
    QByteArray theSlot = QMetaObject::normalizedSignature(slotName);
    if (!QMetaObject::checkConnectArgs(theSignal, theSlot))
    {
        return false;
    }

    int signalId = pSourceObject->metaObject()->indexOfSignal(theSignal);
    if (signalId < 0)
    {
        return false;
    }

    int slotId = slotIndices.value(theSlot, -1);
    if (slotId < 0)
    {
        slotId = slotList.size();
        slotIndices[theSlot] = slotId; …
Run Code Online (Sandbox Code Playgroud)

c++ qt moc qt-signals

8
推荐指数
1
解决办法
3579
查看次数

Qt从继承自QObject后"发出未定义的引用错误信号"

我最近需要向类添加一个信号,所以我将类更改为继承自QObject并将Q_OBJECT宏添加到类定义中.由于这样做,我在下面的类别行中得到"vtable for CLICommand'的信号未定义引用错误"错误:

// File clicommand.h
#include <QString>
#include <QStringList>
#include <QTcpSocket>
#include "telnetthread.h"
class CLICommand : public QObject
{
Q_OBJECT
public:
    CLICommand(TelnetThread *parentTelnetThread);
signals:
    void signal_shutdown_request(); 
private:
    TelnetThread *m_parentTelnetThread;
Run Code Online (Sandbox Code Playgroud)

以及第二个错误"在'vtable for CLICommand''的信号未定义的引用错误"在下面的行上(初始化成员变量):

// File clicommand.cpp
#include <QDebug>
#include <QTcpSocket>
#include <QTextStream>
#include "version.h"
#include "clicommand.h"
#include "telnetthread.h"
#include "logger.h"
CLICommand::CLICommand(TelnetThread *parentTelnetThread)
  : m_parentTelnetThread(parentTelnetThread)
{
}
Run Code Online (Sandbox Code Playgroud)

就在这里我发出信号的地方.emit行生成对`CLICommand :: signal_shutdown_request()'的错误未定义引用:

// file shutdown_clicommand.cpp
#include <QIODevice>
#include "clicommand.h"
#include "logger.h"
#include "version.h"
void CLICommand::execute_shutdown(const …
Run Code Online (Sandbox Code Playgroud)

c++ qt moc qt-signals qtcore

8
推荐指数
1
解决办法
6011
查看次数

在Qt 5中嵌入Python3

我想将Python解释器3.4嵌入到Qt 5.2.1应用程序(64位)中.但是我有构建问题,我的意思是当我在main.cpp中包含Python头时它编译得很好.

#include <python.h>
#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
  QApplication a(argc, argv);
  MainWindow w;
  w.show();

  return a.exec();
}
Run Code Online (Sandbox Code Playgroud)

但是当我把它放在其他地方时(在Qt标题之后)

//
// embedpytest.cpp
//
#include <QLibrary>
#include <python.h>


EmbedPyTest::EmbedPyTest()
{
}
Run Code Online (Sandbox Code Playgroud)

我得到编译错误:

C:\Python34\include\object.h:435: error: C2059: syntax error : ';'
C:\Python34\include\object.h:435: error: C2238: unexpected token(s) preceding ';'
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

这与此问题非常相似,但解决方案无效

在Qt 5中嵌入Python

谁知道如何解决这个问题?或建议一些干净的解决方法,以便python.h和Qt5能够幸福地生活在一起吗?

c++ python qt qmake qt-signals

8
推荐指数
2
解决办法
3169
查看次数

如何从插槽中找出哪个信号称为此插槽?

我的意思是,如果我有许多不同的信号连接到同一个插槽.我看到了这个问题,但无法理解答案中的链接.你能给我一个简单的例子吗?

c++ qt qt-signals qtcore qmetaobject

8
推荐指数
1
解决办法
2696
查看次数

Is it safe to emit signal from another thread?

Is it safe to emit a signal on an object from another thread (if the slot is connected as QueuedConnection)? I couldn't find a specific piece of documentation that would mention this, the most relevant quote I found is this:

QObject 是可重入的。它的大多数非 GUI 子类,例如 QTimer、QTcpSocket、QUdpSocket 和 QProcess,也是可重入的,从而可以同时从多个线程使用这些类。请注意,这些类旨在从单个线程中创建和使用;在一个线程中创建一个对象并从另一个线程调用它的函数不能保证工作

这表明它可能不行,这也适用于信号吗?有一个QMutexLockerinside QMetaObject::activate,所以在我看来它可能是线程安全的......?

#include <QCoreApplication>
#include <QTimer>
#include <thread>
#include <iostream>

struct Foo : public QObject
{
    Q_OBJECT
public:
    Foo(QObject* parent) : QObject(parent) {}

public slots:
    void run() …
Run Code Online (Sandbox Code Playgroud)

c++ qt multithreading thread-safety qt-signals

8
推荐指数
1
解决办法
4085
查看次数