Różnice między wybraną wersją a wersją aktualną.
Both sides previous revision Poprzednia wersja Nowa wersja | Poprzednia wersja | ||
sk2:qt [2022/11/28 15:41] jkonczak [Wprowadzenie] |
sk2:qt [2024/11/28 20:13] (aktualna) jkonczak [Zadania] |
||
---|---|---|---|
Linia 18: | Linia 18: | ||
=== O Qt === | === O Qt === | ||
- | Qt to framework (zestaw bibliotek i narzędzi) dla języka C++. Duży nacisk w Qt jest położony na budowę aplikacji z graficznym interfejsem użytkownika i tworzenie wieloplatformowego kodu. \\ | + | Qt to framework (zestaw bibliotek i narzędzi) dla języka C+''''+. Duży nacisk w Qt jest położony na budowę aplikacji z graficznym interfejsem użytkownika i tworzenie wieloplatformowego kodu. \\ |
[[https://www.qt.io/product|Strona produktu]] [[https://wiki.qt.io/About_Qt|Strona "O Qt" w wiki Qt]] [[https://pl.wikipedia.org/wiki/Qt|Polska Wikipedia o Qt]] | [[https://www.qt.io/product|Strona produktu]] [[https://wiki.qt.io/About_Qt|Strona "O Qt" w wiki Qt]] [[https://pl.wikipedia.org/wiki/Qt|Polska Wikipedia o Qt]] | ||
=== Narzędzia === | === Narzędzia === | ||
- | Qt do wersji 5 jako podstawowego systemu budowania używa dostarczonego z Qt programu ''[[https://doc.qt.io/qt-5/qmake-manual.html|qmake]]''. Dodatkowo Qt 5 wspiera oficjalnie CMake (nieoficjalnie Qt jest wspierane też przez inne systemy budowania).\\ | + | <small>Qt do wersji 5 jako podstawowego systemu budowania używa dostarczonego z Qt programu ''[[https://doc.qt.io/qt-5/qmake-manual.html|qmake]]''. Dodatkowo Qt 5 wspiera oficjalnie CMake (nieoficjalnie Qt jest wspierane też przez inne systemy budowania).</small>\\ |
Qt od wersji 6 jako podstawowego systemu budowania używa CMake ([[https://doc.qt.io/qt-6/cmake-manual.html|dokumentacja dla Qt]]) nie zaprzestając rozwoju qmake. | Qt od wersji 6 jako podstawowego systemu budowania używa CMake ([[https://doc.qt.io/qt-6/cmake-manual.html|dokumentacja dla Qt]]) nie zaprzestając rozwoju qmake. | ||
Linia 33: | Linia 33: | ||
Qt korzysta z dodatkowego preprocesora ''[[https://doc.qt.io/qt-6/why-moc.html|moc]]''. Od Qt5 użycie ''moc'' można pominąć, jeśli korzysta się z nowej składni funkcji ''connect'' i nie definiuje własnych sygnałów. | Qt korzysta z dodatkowego preprocesora ''[[https://doc.qt.io/qt-6/why-moc.html|moc]]''. Od Qt5 użycie ''moc'' można pominąć, jeśli korzysta się z nowej składni funkcji ''connect'' i nie definiuje własnych sygnałów. | ||
\\ | \\ | ||
- | <html><small></html>Zarówno ''uic'' jak i ''moc'' są wywoływane automatycznie przez system budowania qmake. W cmake trzeba włączyć opcje [[https://cmake.org/cmake/help/latest/prop_tgt/AUTOUIC.html|AUTOUIC]] i [[https://cmake.org/cmake/help/latest/prop_tgt/AUTOMOC.html|AUTOMOC]].<html></small></html> | + | <small>Zarówno ''uic'' jak i ''moc'' są wywoływane automatycznie przez system budowania qmake. |
+ | W CMake dla Qt6 należy <html><a class="urlextern" href="https://doc.qt.io/qt-6/cmake-get-started.html#building-a-c-gui-application"></html>dodać ''qt_standard_project_setup()'' i zamiast ''add_executable'' użyć ''qt_add_executable''<html></a></html> (w Qt5 zamiast tego trzeba włączyć opcje [[https://cmake.org/cmake/help/latest/prop_tgt/AUTOUIC.html|AUTOUIC]] i [[https://cmake.org/cmake/help/latest/prop_tgt/AUTOMOC.html|AUTOMOC]]).<html></small></html> | ||
===== Sieć w Qt ===== | ===== Sieć w Qt ===== | ||
- | Opis z podręcznika Qt: [[https://doc.qt.io/qt-5/qtnetwork-programming.html|Network Programming with Qt]] | + | Opis z podręcznika Qt: [[https://doc.qt.io/qt-6/qtnetwork-programming.html|Network Programming with Qt]] |
W Qt funkcje sieciowe są **nieblokujące** (asynchroniczne).\\ | W Qt funkcje sieciowe są **nieblokujące** (asynchroniczne).\\ | ||
Linia 43: | Linia 44: | ||
Ważniejsze klasy do obsługi socketów i podstawowe metody i sygnały: | Ważniejsze klasy do obsługi socketów i podstawowe metody i sygnały: | ||
- | * ''[[http://doc.qt.io/qt-5/qtcpserver.html|QTcpServer]]'' - klasa tworząca gniazdo nasłuchujące protokołu TCP | + | * ''[[https://doc.qt.io/qt-6/qtcpserver.html|QTcpServer]]'' - klasa tworząca gniazdo nasłuchujące protokołu TCP |
- | * klasa udostępnia sygnał (zdarzenie) ''[[http://doc.qt.io/qt-5/qtcpserver.html#newConnection|newConnection]]'' | + | * klasa udostępnia sygnał (zdarzenie) ''[[https://doc.qt.io/qt-6/qtcpserver.html#newConnection|newConnection]]'' |
- | * metoda ''[[http://doc.qt.io/qt-5/qtcpserver.html#listen|listen]]'' wywołuje ''bind'', ustawia ''SO_REUSEADDR''((w uproszczeniu; szczegóły tutaj: https://doc.qt.io/qt-5/qabstractsocket.html#BindFlag-enum)) i wywołuje ''listen'' | + | * metoda ''[[https://doc.qt.io/qt-6/qtcpserver.html#listen|listen]]'' wywołuje ''bind'', ustawia ''SO_REUSEADDR''((w uproszczeniu; szczegóły tutaj: https://doc.qt.io/qt-6/qabstractsocket.html#BindFlag-enum)) i wywołuje ''listen'' |
- | * metoda ''[[http://doc.qt.io/qt-5/qtcpserver.html#nextPendingConnection|nextPendingConnection]]'' wykonuje ''accept'' | + | * metoda ''[[https://doc.qt.io/qt-6/qtcpserver.html#nextPendingConnection|nextPendingConnection]]'' wykonuje ''accept'' |
- | * ''[[http://doc.qt.io/qt-5/qtcpsocket.html|QTcpSocket]]'' - klasa gniada TCP klienckiego (łączącego się pod podany adres) | + | * ''[[https://doc.qt.io/qt-6/qtcpsocket.html|QTcpSocket]]'' - klasa gniada TCP klienckiego (łączącego się pod podany adres) |
- | * sygnały ''[[http://doc.qt.io/qt-5/qabstractsocket.html#signals|connected]]'' i ''[[http://doc.qt.io/qt-5/qabstractsocket.html#signals|disconnected]]'' | + | * sygnały ''[[https://doc.qt.io/qt-6/qabstractsocket.html#signals|connected]]'' i ''[[https://doc.qt.io/qt-6/qabstractsocket.html#signals|disconnected]]''((Rozłączenie gniazda poza sygnałem ''disconnected'' wygeneruje też ''errorOccured'' z argumentem ''RemoteHostClosedError''.)) |
- | * sygnał ''[[http://doc.qt.io/qt-5/qabstractsocket.html#signals|errorOccured]]'' (Qt w wersji ≥5.15) \\ <html><small></html> sygnał ''[[http://doc.qt.io/qt-5.14/qabstractsocket.html#signals|error]]'' (Qt w wersji przed 5.15)(( Uwaga, w nowej składni ''connect'' wymagany jest wskaźnik na funkcję, a klasa QTcpSocket ma dwie funkcje ''error''. W efekcie potrzebne jest wybranie funkcji przez rzutowanie na właściwy typ [[https://wiki.qt.io/New_Signal_Slot_Syntax#Asynchronous_made_easier|[1]]] ))<html></small></html> | + | * sygnał ''[[https://doc.qt.io/qt-6/qabstractsocket.html#signals|errorOccured]]'' (Qt w wersji ≥5.15) \\ <html><small></html> sygnał ''[[https://doc.qt.io/qt-5.14/qabstractsocket.html#signals|error]]'' (Qt w wersji przed 5.15)(( Uwaga, w nowej składni ''connect'' wymagany jest wskaźnik na funkcję, a klasa QTcpSocket ma dwie funkcje ''error''. W efekcie potrzebne jest wybranie funkcji przez rzutowanie na właściwy typ [[https://wiki.qt.io/New_Signal_Slot_Syntax#Asynchronous_made_easier|[1]]] ))<html></small></html> |
- | * sygnał ''[[http://doc.qt.io/qt-5/qiodevice.html#signals|readyRead]]'', określający że przyszły nowe dane do odbioru | + | * sygnał ''[[https://doc.qt.io/qt-6/qiodevice.html#signals|readyRead]]'', określający że przyszły nowe dane do odbioru |
- | * metoda ''[[http://doc.qt.io/qt-5/qabstractsocket.html#connectToHost|connectToHost]]'' żąda połączenia pod podany adres | + | * metoda ''[[https://doc.qt.io/qt-6/qabstractsocket.html#connectToHost|connectToHost]]'' żąda połączenia pod podany adres |
- | * metoda ''[[http://doc.qt.io/qt-5/qiodevice.html#write|write]]'' pisze dane, natomiast ''[[http://doc.qt.io/qt-5/qiodevice.html#read|read]]'' i ''[[http://doc.qt.io/qt-5/qiodevice.html#readAll|readAll]]'' odbierają dane | + | * metoda ''[[https://doc.qt.io/qt-6/qiodevice.html#write|write]]'' pisze dane, natomiast ''[[https://doc.qt.io/qt-6/qiodevice.html#read|read]]'' i ''[[https://doc.qt.io/qt-6/qiodevice.html#readAll|readAll]]'' odbierają dane |
- | * ''[[http://doc.qt.io/qt-5/qudpsocket.html|QUdpSocket]]'' - klasa obsługująca gniazda UDP | + | * ''[[https://doc.qt.io/qt-6/qudpsocket.html|QUdpSocket]]'' - klasa obsługująca gniazda UDP |
* sygnały identyczne jak dla ''QTcpSocket'' | * sygnały identyczne jak dla ''QTcpSocket'' | ||
- | * odbiór wiadomości metodą ''[[http://doc.qt.io/qt-5/qudpsocket.html#receiveDatagram|receiveDatagram]]'' | + | * odbiór wiadomości metodą ''[[https://doc.qt.io/qt-6/qudpsocket.html#receiveDatagram|receiveDatagram]]'' |
- | * wysłanie wiadomości metodą ''[[http://doc.qt.io/qt-5/qudpsocket.html#writeDatagram|writeDatagram]]'' | + | * wysłanie wiadomości metodą ''[[https://doc.qt.io/qt-6/qudpsocket.html#writeDatagram|writeDatagram]]'' |
Qt jest modularny. Do włączenia modułu odpowiedzialnego za sieć należy: | Qt jest modularny. Do włączenia modułu odpowiedzialnego za sieć należy: | ||
* dla qmake dodać linię: \\ ''QT += network'' | * dla qmake dodać linię: \\ ''QT += network'' | ||
- | * dla cmake dodać do linii szukające Qt komponent Network, a następnie dodać go do bibliotek łączonych: \\ ''find_package(Qt5 COMPONENTS … Network …) \\ target_link_libraries(target … Qt5::Network …)'' \\ <html><small></html>Dla Qt 6 trzeba zmienić oczywiście Qt5 na Qt6 <html></small></html> | + | * dla cmake dodać do linii szukające Qt komponent Network, a następnie dodać go do bibliotek łączonych: \\ ''find_package(Qt6 COMPONENTS … Network …) \\ target_link_libraries(target … Qt6::Network …)'' \\ <html><small></html>Dla Qt 5 trzeba zmienić oczywiście Qt6 na Qt5 <html></small></html> |
<html><small></html> | <html><small></html> | ||
Linia 97: | Linia 98: | ||
QCoreApplication a(argc, argv); | QCoreApplication a(argc, argv); | ||
+ | // obsługa standardowego wejścia jako zdarzenie | ||
#ifdef _WIN32 | #ifdef _WIN32 | ||
QWinEventNotifier inputNotifier(GetStdHandle(STD_INPUT_HANDLE)); | QWinEventNotifier inputNotifier(GetStdHandle(STD_INPUT_HANDLE)); | ||
Linia 170: | Linia 172: | ||
# UDP-DATAGRAM:239.0.0.1:2000 → wysyłaj datagramy do podanego adresu (239.0.0.1:2000) i odbieraj co przyjdzie | # UDP-DATAGRAM:239.0.0.1:2000 → wysyłaj datagramy do podanego adresu (239.0.0.1:2000) i odbieraj co przyjdzie | ||
# reuseaddr → włącze SO_REUSEADDR; pozwala wielu programom na tym samym komputerze używać tego samego portu do mcastu | # reuseaddr → włącze SO_REUSEADDR; pozwala wielu programom na tym samym komputerze używać tego samego portu do mcastu | ||
- | # ip-add-membership=239.0.0.1:enp0s3 → dołącza do grupy mcastowej 239.0.0.1 na urządzeniu enp0s3 | + | # ip-add-membership=239.0.0.1:br0 → dołącza do grupy mcastowej 239.0.0.1 na urządzeniu br0 |
# bind=0.0.0.0:2000 → wykonaj bind na podany adres; pod tym adresem będą odbierane datagramy | # bind=0.0.0.0:2000 → wykonaj bind na podany adres; pod tym adresem będą odbierane datagramy | ||
</code> | </code> |