Wstęp
Ten artykuł ma być początkiem serii pomniejszych na temat możliwości refleksji w Qt/C++. Rozpoczynam to studium ze względu na potrzebę zbudowania w miarę uniwersalnego narzędzie do zapisu danych z obiektów do XML w sposób automatyczny. Aktualnie posługuję się względnie ubogą implementacją opartą na szablonach, jednak wierzę, że zautomatyzowanie tego za pomocą refleksji stanowczo przyśpieszy prace w przyszłości.
Chciałbym zaznaczyć, że seria ta nie na darmo nazywa się „studium”! W trakcie realizacji tych artykułów uczę się sam i dzielę się wiedzą, która raczej nie ma wielkiego potwierdzenia w praktyce (chyba, że zaznaczę inaczej). Także proszę miej na uwadze, że rzeczy przedstawione w tej serii mogą mieć bliżej nieznane konsekwencje. Oczywiście nie planuję tutaj całkowicie wyłączyć swojego rozumu i ignorować już zdobytego doświadczenia – nie będę tutaj publikował kodu ewidentnie złego, chyba, że zaznaczę to wcześniej i zostanie zrobione to dla uproszczenia przykładu, co czasem jest konieczne.
Właściwości - przykład
Zacznę od najważniejszego, czyli podstawy. Aby móc w ogóle zrobić cokolwiek refleksyjnego w Qt musimy użyć ichnich właściwości – wszystkie szczegóły na ich temat znajdziemy w dokumentacji (https://doc.qt.io/qt-5/properties.html). W dalszych częściach studium mam nadzieję, że uda się stworzyć praktyczny przykład wykorzystania wszystkich elementów, które wchodzą w skład definicji właściwości.
Poniżej prezentuję najprostszy przykład.
class PropertyExample : QObject {
Q_OBJECT
Q_PROPERTY(bool isEnabled READ isEnabled WRITE setIsEnabled NOTIFY isEnabledChanged)
private:
bool _isEnabled;
public:
bool isEnabled() { return _isEnabled; }
void setIsEnabled(bool value)
{
if (_isEnabled == value) return;
_isEnabled = value;
emit isEnabledChanged();
}
signals:
void isEnabledChanged();
};
Zaczynając od początku o tym co się dzieje w kodzie:- Aby możliwe było użycie właściwości (a co za tym idzie – refleksji) niezbędne jest dziedziczenie po QObject (możliwe, że można to ominąć za pomocą Q_GADGET, ale to jest jeszcze do zbadania),
- Obowiązkowe makro Q_OBJECT, które nie powinno Cię dziwić jeśli pracowałeś wcześniej z Qt,
- Definicja właściwości – rozbijemy ją szczegółowo poniżej,
- prywatny magazyn dla właściwości (bool _isEnabled),
- funkcja READ dla właściwości (bool isEnabled()),
- funkcja WRITE dla właściwości (void setIsEnabled(bool value)) - zaczynanie takich funkcji od słowa 'set' jest jedną z konwencji stosowanej w Qt,
- sygnał, który informuje o tym, że wartość się zmieniła.
To jest minimalny działający przykład, który prezentuje jak stworzyć właściwość wewnątrz klasy Qt. Zwróć jeszcze tylko uwagę, na fakt, że funkcja WRITE sprawdza, czy wartość przechowywana w magazynie jest inna niż ta, którą ktoś próbuje ustawić – zaleca się stosowanie takiej konstrukcji praktycznie zawsze, gdyż chroni to przed zapętleniem, kiedy połączysz dwie właściwości a one będą się zmieniać na okrągło.
Definicja właściwości
Nie będę tutaj opisywał wszystkich możliwości, bo i po co, skoro można znaleźć je w przytoczonej wcześniej dokumentacji. Dla porządku opiszę tylko to co pojawiło się w przykładzie:
Q_PROPERTY(
|
bool isEnabled
|
READ isEnabled
|
WRITE setIsEnabled
|
NOTFIY
isEnabledChanged)
|
Makro.
|
typ i nazwa
właściwości dostępna
dla systemu refleksji.
|
nazwa
funkcji, która służy do odczytu wartości.
|
nazwa
funkcji, która służy do zapisu nowej wartości.
|
Nazwa
sygnału, który jest emitowany, gdy wartość właściwości zostanie zmieniona.
|
Komentarze
Prześlij komentarz