2010-02-11 25 views
16

Tôi đã tạo sự kiện tùy chỉnh trong ứng dụng Qt của mình bằng cách phân lớp QEvent.Qt: Xác định loại sự kiện tùy chỉnh

class MyEvent : public QEvent 
{ 
    public: 
    MyEvent() : QEvent((QEvent::Type)2000)) {} 
    ~MyEvent(){} 
} 

Để kiểm tra sự kiện này, tôi sử dụng đoạn mã sau trong một) Phương thức sự kiện (:

if (event->type() == (QEvent::Type)2000) 
{ 
    ... 
} 

Tôi muốn để có thể xác định loại sự kiện tùy chỉnh của nơi nào đó trong ứng dụng của tôi để tôi không cần phải truyền số nguyên thực trong các phương thức sự kiện của mình. Vì vậy, trong trường hợp của tôi() phương pháp tôi muốn để có thể làm điều gì đó như

if (event->type() == MyEventType) 
{ 
    ... 
} 

Bất kỳ suy nghĩ như thế nào và ở đâu trong đoạn code tôi có thể làm điều này?

+4

Thay vì hằng số phép thuật '2000', bạn có thể sử dụng' QEvent :: User'. –

+2

@TonvandenHeuvel: +1. Cũng thế. Thay vì "có thể sử dụng", tôi muốn nói ** nên sử dụng **. ;) – Macke

Trả lời

15

Nếu sự kiện-type xác định lớp học cụ thể của bạn, tôi muốn đặt nó ở đó:

class MyEvent : public QEvent { 
public: 
    static const QEvent::Type myType = static_cast<QEvent::Type>(2000); 
    // ... 
}; 

// usage: 
if(evt->type() == MyEvent::myType) { 
    // ... 
} 
+0

Điều đó đã giúp ích rất nhiều, cảm ơn! Mặc dù tôi không hoàn toàn hiểu tại sao bạn lại đưa bạn sửa đổi mà bạn đã làm. – Chris

+1

Nếu được khởi tạo trong định nghĩa lớp, nó có thể được sử dụng trong các biểu thức hằng số không tách rời như với 'case' trong câu lệnh' switch' hoặc như là các giới hạn mảng. –

13

Để thuận tiện, bạn có thể sử dụng QEvent :: registerEventType() chức năng tĩnh để đăng ký và đặt sự kiện tùy chỉnh gõ cho ứng dụng của bạn. Làm như vậy sẽ cho phép bạn tránh vô tình tái sử dụng một loại sự kiện tùy chỉnh đã được sử dụng ở nơi khác trong ứng dụng của bạn.

Ví dụ:

class QCustomEvent : public QEvent 
{ 
public: 
    QCustomEvent() : QEvent(QCustomEvent::type()) 
    {} 

    virtual ~QCustomEvent() 
    {} 

    static QEvent::Type type() 
    { 
     if (customEventType == QEvent::None) 
     { 
      int generatedType = QEvent::registerEventType() 
      customEventType = static_cast<QEvent::Type>(generatedType); 
     } 
     return customEventType; 
    } 

private: 
    static QEvent::Type customEventType; 
}; 

QEvent::Type QCustomEvent::customEventType = QEvent::None; 
+6

Đây là một đề xuất tốt đẹp, nhưng bạn có thể bỏ qua phần QEvent :: None: const QEvent :: Loại CustomEvent :: EventType = static_cast (QEvent :: registerEventType()); – gaspard

+1

Và đặt tên cho ví dụ QCustomEvent của bạn không phải là rất thông minh: đó là tên của lớp Qt 3. – gaspard

+0

Ngoài ra, bạn không cần biến thành viên. Chỉ cần sử dụng một địa phương tĩnh. –

4

Cách thành ngữ để đối phó với các vấn đề như vậy là để tạo ra một lớp mẫu wrapper, tận dụng CRTP. Đối với mỗi loại sự kiện tùy chỉnh, mẫu đó đại diện cho một loại mới, do đó một thành viên riêng biệt staticType() tồn tại cho từng loại, trả về loại đăng ký duy nhất của nó.

Dưới đây tôi đưa ra ba cách các loại xác định:

  1. By staticType() - đây là chỉ hữu ích trong một lời gọi của ứng dụng, và là loại được sử dụng với QEvent. Các giá trị không được bảo đảm để giữ nguyên giữa các lời gọi của ứng dụng. Họ không thuộc về bộ nhớ bền, như trong nhật ký.

  2. Bằng localDurableType() - những thứ sẽ tồn tại giữa các lời gọi và giữa các lần biên dịch lại với cùng trình biên dịch. Nó lưu định nghĩa thủ công của phương pháp durableType() khi xác định các sự kiện phức tạp.

  3. Bằng durableType() - chúng thực sự là nền tảng chéo và sẽ giống nhau trừ khi bạn thay đổi tên lớp sự kiện trong mã của mình. Bạn phải xác định thủ công durableType() nếu bạn không sử dụng macro NEW_QEVENT.

Cả localDurableType()durableType() khác betwen Qt 4 và 5 do sự thay đổi để qHash.

Bạn sử dụng các tiêu đề trong một trong hai cách sau:

#include "EventWrapper.h" 

class MyComplexEvent : public EventWrapper<MyComplexEvent> { 
    // An event with custom data members 
    static int durableType() { return qHash("MyEvent"); } 
    ... 
}; 

NEW_QEVENT(MySimpleEvent) // A simple event carrying no data but its type. 

EventWrapper.h

#ifndef EVENTWRAPPER_H 
#define EVENTWRAPPER_H 

#include <QEvent> 
#include <QHash> 

template <typename T> class EventWrapper : public QEvent { 
public: 
    EventWrapper() : QEvent(staticType())) {} 
    static QEvent::Type staticType() { 
     static int type = QEvent::registerEventType(); 
     return static_cast<QEvent::Type>(type); 
    } 
    static int localDurableType() { 
     static int type = qHash(typeid(T).name()); 
     return type; 
    } 
}; 

#define NEW_QEVENT(Name) \ 
    class Name : public EventWrapper<Name> \ 
    { static int durableType() { \ 
     static int durable = qHash(#Name); return durable; \ 
    } }; 

#endif // EVENTWRAPPER_H 
+0

Tôi thích việc sử dụng CRTP ở đây nhưng tôi tự hỏi làm thế nào bạn sẽ chắc chắn rằng các biến thể sử dụng 'qHash' không va chạm với các loại sự kiện hiện có? – Kamajii

+0

Bạn không thể chắc chắn nói chung, nhưng bạn có thể chắc chắn cho bất kỳ chương trình cụ thể nào. Bạn có thể kiểm tra tĩnh các va chạm và nhận được câu trả lời "có, có xung đột" hoặc "không, không có xung đột". Vì vậy, đôi khi thực tế là không có cách nào để biết nói chung không loại trừ việc biết nó trong hoàn cảnh cụ thể. –

+0

Nhưng đây không phải là một điểm rất quan trọng cần được đề cập trong câu trả lời của bạn? Cuối cùng, bạn không bao gồm bất kỳ điều khoản nào chống lại các xung đột trong mã của bạn. – Kamajii

Các vấn đề liên quan