簡體   English   中英

如何從Qt中所有繼承的類的基類中使用信號?

[英]How use signal in base class from all inherited class in qt?

我有一個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);
}

現在在asease類中,當方法從服務器獲取一些數據時,我想顯示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和...(上)以及在ase頁面中的所有工作都可以正常顯示, BookPage.qml我想按時執行。

我tryed這樣的:我使用的基類ManagerEngine顯示BusyIndicator

我要顯示如下所示的busyIndi​​cator。(我在主頁中聲明了基類。現在,如果我打開BookPage.qml來顯示圖書清單,則現在必須可見busyIndi​​cator

main.qml

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

但這不起作用。還有另一種方式可以完成這項工作嗎(例如我可以使用static關鍵字)

這將永遠行不通,因為這些類似乎在主線程中起作用,並且當處理完成時,不會進行用戶界面更新,並且您的應用程序將被凍結。

在所有情況下,解決方案都必須從將忙碌指示器設置為適當的屬性開始-這將神奇地解決您的Qt Quick問題,並且您可以簡單地綁定到該屬性,而不必完全使用該信號。 這就是屬性通知的用途,並且QML為您處理它們。 您也不希望設置器是公開的-這是內部的只讀狀態。 您還需要const正確的簽名。

解決所有問題后,我們得到:

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;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM