如何在qt中使用所有继承类的基类信号?

时间:2018-06-11 10:53:09

标签: c++ qt qt-quick qtquickcontrols2 busyindicator

我有一个qt quick 2应用程序,我有我的c ++类的基类

class ManagerEngine : public QObject
{
    Q_OBJECT
public:
    explicit ManagerEngine(QObject *parent = nullptr);
    bool isProcessing();
    void setIsProcssing(bool isProcessing);
signals:    
    void isProcessingChanged(bool isProcessing);
private:
     bool m_IsProccessing;
};

我有很多从上面继承的课程

class BookManager : public ManagerEngine
{
};

void BookManager::getList(bool refreshList){
    setIsProcssing(true);
    //get data from server
    setIsProcssing(false);
}

现在在这些类中,我想在方法从服务器获取一些数据时显示BusyIndicator

BookPage.qml

BookManager{
    id: bm
    onIsProcessingChanged: {
        busyIndicator.visible=isProcessing; // busyIndicator is in main.qml
    }
}

CategoryPage.qml

CategoryManager{
    id: cm
    onIsProcessingChanged: {
        busyIndicator.visible=isProcessing;
    }
}

QuestionPage.qml

QuestionManager{
    id: qm
    onIsProcessingChanged: {
        busyIndicator.visible=isProcessing;
    }
}

//I have many class like : login signup and ... inherited from base class

main.qml

BusyIndicator{
    id:busyIndicator        
}

一切正常BookPage.qml和......(上图),在本页中,busyIndi​​cator会显示。但我想按时完成。

我试过这个:我使用基类ManagerEngine来显示BusyIndicator

我想显示busyIndi​​cator如下所示。(我在主页面中声明了基类。现在如果我打开BookPage.qml显示书籍列表,现在busyIndi​​cator必须是可见的

main.qml

ManagerEngine{
    id: me
    onIsProcessingChanged: {
        progressIndicator.visible=isProcessing;
    }
}
BusyIndicator{
    id:busyIndicator        
}

但它不起作用。还有其他方法可以完成这项工作(例如我可以使用静态关键字)

1 个答案:

答案 0 :(得分:0)

这不会有用,因为这些类似乎在主线程中工作,并且在处理完成时,没有进行用户界面更新,并且您的应用程序被冻结。

在所有情况下,解决方案必须首先使busy指示符成为一个合适的属性 - 这将神奇地修复你的Qt Quick问题,你可以简单地绑定到属性,而不必显式地使用信号。这是属性通知的用途,QML会为您处理。您也不希望setter被公开 - 这是内部的只读状态。您还需要const-correct签名。

解决所有问题后,我们得到:

class ManagerEngine : public QObject {
    Q_OBJECT
    Q_PROPERTY(bool isProcessing READ isProcessing NOTIFY isProcessingChanged)
public:
    using QObject::QObject; //for C++14 & up
    bool isProcessing() const;
    Q_SIGNAL void isProcessingChanged(bool);
protected:
    void setIsProcessing(bool);
private:
    bool m_isProccessing = false;
};

/// This method is not thread-safe
void ManagerEngine::setIsProcessing(bool p) {
  if (p == m_isProcessing) return;
  m_isProcessing = p; // precondition of the signal
  return emit isProcessingChanged(m_isProcessing);
}

/// This method is not thread-safe
bool ManagerEngine::isProcessing() const {
  return m_isProcessing;
}

如果希望处理是在管理器引擎的所有实例之间共享的状态,则将其设为类的属性,而不是对象的属性。在C ++中,static成员声明意味着它是类成员,而不是对象成员。

接口

class ManagerEngine : public QObject {
    Q_OBJECT
    Q_PROPERTY(bool isProcessing READ isProcessing NOTIFY isProcessingChanged)
public:
    using QObject::QObject; //for C++14 & up
    ~ManagerEngine() override;
    bool isProcessing() const;
    Q_SIGNAL void isProcessingChanged(bool);
protected:
    void setIsProcessing(bool);
private:
    bool m_isProcessing = false; // per-object
    static QAtomicInt m_processingCount; // per-class
};

实施

QAtomicInt ManagerEngine::m_processingCount;

ManagerEngine::~MangerEngine() {
  setIsProcessing(false);
  // Perhaps it'd be more appropriate instead to simply
  // Q_ASSERT(!m_isProcessing) if the engine should not be destroyed
  // during processing.
}

// This method is not thread-safe, but multiple engines can
// reside in different threads.
void ManagerEngine::setIsProcessing(bool p) {
  if (p == m_isProcessing) return;
  int const delta = p ? (+1) : (-1);
  auto count = m_processingCount.load();
  Q_ASSERT(count >= 0);
  Q_ASSERT(p || count > 0);
  m_isProcessing = p;
  while (!m_processingCount.testAndSetOrdered(count, count+delta)) {
    count = m_processingCount.load();
  }
  // The signal will be emitted only when the global state changes,
  // and exactly once per global state change.
  if ((count > 0) != ((count+delta) > 0))
    emit isProcessingChanged(count > 0);
  return;
}

// Note: Due to data races, it is not guaranteed that the result of
// this method is the same as the parameter in the isProcessingChanged
// signal. Only the signal's parameter is guaranteed to change state
// in a race-free fashion, i.e. always toggle (alternate) and never repeat.
bool ManagerEngine::isProcessing() const {
  auto const count = m_processingCount.load();
  Q_ASSERT(count >= 0);
  Q_ASSERT(!m_isProcessing || count > 0);
  return count > 0;
}