Oprogramowanie i wykorzystanie stacji roboczych Wykład 4
Transkrypt
Oprogramowanie i wykorzystanie stacji roboczych Wykład 4
Mechanizm sygnałów i slotów Mechanizm sygnałów i slotów umożliwia komunikacje˛ pomiedzy ˛ obiektami. Oprogramowanie i wykorzystanie stacji roboczych Sygnał jest komunikatem informujacym, ˛ o wystapieniu ˛ pewnego zdarzenia. Obiekty z biblioteki Qt emituja˛ ((emit)) sygnał w momencie wystapienia ˛ zdarzenia, np. gdy użytkownik nacisnał˛ przycisk (QPushButton) - przycisk emituje sygnał clicked. Wykład 4 Slot jest specyficzna˛ metoda˛ obiektu z biblioteki Qt, które może obsługiwać zdarzenie, np. zamykajaca ˛ aplikacje Qt (quit z klasy Dr inż. Tomasz Olas [email protected] QApplication). Zarówno sygnały, jak i sloty moga˛ posiadać parametry, poprzez które można przekazywać dodatkowe informacje o zaistniałym zdarzeniu. Instytut Informatyki Teoretycznej i Stosowanej Politechnika Cz˛estochowska Sygnały można dowolnie łaczyć ˛ ze slotami (o ile posiadaja˛ takie same parametry). Wykład 4 Wykład 4 – p. 1/30 Sygnały i sloty - przykład użycia Sygnały i sloty - definicja klasy definicja klasy zawierajacej ˛ sygnały i sloty powinna znajdować sie˛ w osobnym pliku nagłówkowym (np. myclass.h) class MyClass: public QObject { Q_OBJECT public: MyClass(); protected slots: void MySlot(); void MySlot2(int value); signals: void MySignal(); void MySignal2(int value); }; Wykład 4 – p. 3/30 Wykład 4 Sygnały i sloty - deklaracja metod Sygnały i sloty - łaczenie, ˛ rozłaczanie ˛ Sloty sa˛ zwykłymi metodami (poza faktem, że moga˛ być połaczone ˛ z sygnałami) i należy je zdefiniować tak jak zwykłe metody: Do połaczenia ˛ sygnału ze slotem służy statyczna metoda connect z klasy QObject: void MyClass::MySlot() { ... } bool QObject::connect(const QObject* sender, const char* signal, const QObject* receiver, const char* member) Do określenia sygnałów i slotów należy wykorzystać makra SIGNAL() i SLOT(). Przykład: Sygnały należy jedynie zadeklarować i nie wolno ich definiować (odpowiedni kod zostanie wygenerowany przez narz˛edzie MOC). MyClass a; MyClass b; QObject::connect(&a, SIGNAL(MySignal()), &b, SLOT(MySlot())); QObject::connect(&a, SIGNAL(MySignal2(int)), &b, SLOT(MySlot(int))); Do zgłoszenia (wyemitowania) wystapienia ˛ określonego zdarzenia modelowanego przez sygnał służy konstrukcja emit nazwa_sygnału(parametry): Do rozłaczania ˛ połacze ˛ ń sygnałów ze slotami służa˛ metody disconnect z klasy QObject: emit MySignal(); ... int a = 10; emit MySignal2(a); bool disconnect(const char * signal=0, const QObject* receiver=0, const char * member=0); bool disconnect(const QObject* receiver, const char * member=0); Wykład 4 – p. 5/30 Wykład 4 Sygnały i sloty - kompilacja Makefile i moc Pliki zawierajace ˛ definicje klas zawierajacych ˛ sygnały i sloty należy przetworzyć narz˛edziem MOC: OBJS = main.o mywidget.o mywidget.moc.o all: program moc myclass.h -o myclass_moc.cpp Zostanie w ten sposób wygenerowany dodatkowy plik źródłowy, który należy zlinkować z pozostałymi plikami źródłowymi projektu. Np.: %.o: %.cpp g++ $(CXXFLAGS) -c $< g++ -o myprogram myclass.cpp myclass_moc.cpp -lqt-mt %.moc.cpp: %.cpp moc -o $@ $*.h program: $(OBJS) g++ -o program $(OBJS) -lqt-mt clean: rm *.o rm *.moc.o rm *.moc.cpp Wykład 4 – p. 7/30 Wykład 4 QTimer - przykład Klasa QTimer Klasa QTimer służy do generowania zdarzenia QTimerEvent w stałych odstepach ˛ czasu. Tworzac ˛ obiekt klasy QTimer określamy do którego obiektu bed ˛ a˛ takie zdarzenia kierowane: QTimer(QObject * parent=0) Użyteczne metody: int start(int msec, bool singleShot = FALSE) ... QTimer *timer = new QTimer(myObject); connect(timer, SIGNAL(timeout()), myObject, SLOT(timerDone())); timer->start(10000, TRUE); QTimer *t = new QTimer( myObject); connect(t, SIGNAL(timeout()), SLOT(processOneThing())); t->start(1000); ... void stop() void changeInterval(int msec) Obsługa zdarzenia może zostać zrealizowana przy wykorzystaniu metody QObject::timerEvent(QTimerEvent *), lub poprzez sygnał timeout(). Z jednym obiektem może być zwiazanych ˛ dowolna liczba sygnałów. Wykład 4 Wykład 4 – p. 9/30 Rysowanie Rysowanie - typowe wykorzystanie Do rysowania służy klasa QPainter. Typowe zastosowanie: Służy ona do rysowania w obszarach obiektów klas dziedziczacych ˛ po klasie QPaintDevice (widgety, ale również obiekty klas QPixmap, QPicture i QPrinter). Utworzyć obiekt klasy QPainter Do rysowania służy zestaw niskopoziomowych metod klasy QPainter umożliwiajacych ˛ rysowanie linii, elips, prostokatów, ˛ wpisywanie tekstu, wklejanie rysunków, itp. Usunać ˛ obiekt klasy QPainter Ustawić pedzel, ˛ sposób wypełnienia, czcionk˛e, itp. Wywołać metody do rysowania W wiekszości ˛ przypadków rysowanie odbywa sie˛ przy obsłudze zdarzenie paintEvent: Standardowo do rysowania wykorzystywany jest „normalny” układ współrz˛ednych, ale może on zostać zmodyfikowany przy wykorzystaniu zbioru transformacji. void MyWidget::paintEvent(QPaintEvent* e) { QPainter paint(this); paint.setPen(Qt::blue); paint.drawText(rect(), AlignCenter, "The Text"); } Przy wywyołaniu konstruktora określa sie˛ obiekt na którym bed ˛ a˛ dokonywane operacje rysowania. Wykład 4 – p. 11/30 Wykład 4 QPainter - współrzedne ˛ QPainter - ustawienia void MyWidget::paintEvent( QPaintEvent * ) { QPainter p( this ); p.setPen( darkGray ); p.drawRect( 1,2, 5,4 ); p.setPen( lightGray ); p.drawLine( 9,2, 7,7 ); } Czcionka - setFont(const QFont &font), font(), fontInfo(), P˛edzel - setBrush(BrushStyle style), brush(), Pióro - setPen(const QPen &pen), pen(), Tło (Opaque lub Transparent) setBackgroundMode(BGMode m), backgroundMode(), Kolor tła - setBackgroundColor(const QColor &c), backgroundColor(), Pozycja wirtualnego kursora (metoda LineTo - moveTo(int x, int y), pos(), Transformacje układu współrz˛ednych, Obcinanie - setClipping(bool enable), setClipRegion(const QRegion &rgn, CoordinateMode m = CoordDevice). Wykład 4 – p. 13/30 Transformacje układu wpółrzednych ˛ I Wykład 4 Macierz transformacji I W klasie QPainter zaimplementowano mechanizm transformacji 2D układu wpółrz˛ednych. Jest on analogiczny do modelu opisanego w ksiażce ˛ Foley & Van Dam i stosowanego w standardzie OpenGL. Przy określaniu transformacji wykorzystywana jest tzw. macierz transformacji ((transformation matrix)). Jest ona wykorzystywana do ustawienia położenia obiektów w modelu. Składa sie˛ on z trzech etapów: Do modyfikacji macierzy transformacji służa˛ metody: określenie transformacji ((transformations)) układu współrz˛ednych modelu, void QPainter::rotate(double a), ustalenie okna ((window)), poprzez które określamy granice widoku we współrz˛ednych modelu, void QPainter::translate(double dx, double dy), określenie widoku ((viewport)) we współrz˛ednych urzadzenia ˛ graficznego (projekcja modelu na urzadzeniu). ˛ void QPainter::resetMatrix(). void QPainter::scale(double sx, double sy), void QPainter::shear(double sh, double sv), Nie wszystkie wyżej wymienione etapy musza˛ zawsze wystepować. ˛ Wykład 4 – p. 15/30 Wykład 4 Transformacje - przykład 1 Macierz transformacji II Klasa QMatrix określa dwuwymiarowe transformacje układu współrz˛ednych. void Transformation::paintEvent(QPaintEvent* e) { QPainter p(this); Wykorzystywana jest w tym celu macierz o rozmiarze 3 × 3: p.setPen(Qt::red); p.drawLine(0, 0, 50, 50); p.setPen(Qt::darkRed); p.drawText(0, 0, 60, 20, Qt::AlignHCenter | Qt::AlignVCenter, "(0,0)"); p.drawText(50, 50, 60, 20, Qt::AlignHCenter | Qt::AlignVCenter, "(50,50)"); p.translate(0, height()); p.rotate(270); p.setPen(Qt::blue); p.drawLine(0, 0, 50, 50); p.setPen(Qt::darkBlue); p.drawText(0, 0, 60, 20, Qt::AlignHCenter | Qt::AlignVCenter, "(0,0)"); p.drawText(50, 50, 60, 20, Qt::AlignHCenter | Qt::AlignVCenter, "(50,50)"); m11 m12 0 m21 m22 0 dx dy 1 Macierz transformacji przekształca punkt na płaszczyźnie na punkt o innych współrz˛ednych: x′ = m11 · x + m21 · y + dx , y′ = m22 · y + m12 · x + dy gdzie (x, y) sa˛ współrz˛ednymi oryginalnego punktu, natomiast współrz˛edne (x′ , y′ ) określaja˛ punkt po transformacji. } Wykład 4 – p. 17/30 Macierz transformacji III Wykład 4 Macierz transformacji - przykład QMatrix m; m.translate(10, -20); m.rotate(25); m.scale(1.2, 0.7); m11 m12 0 m21 m22 0 dx dy 1 elementy dx i dy macierzy transformacji określaja˛ odpowiednio poziome i pionowe przesuniecie ˛ układu współrz˛ednych, elementy m11 i m22 odpowiadaja˛ za skalowanie po odpowiednio po osi x i y, elementy m12 i m21 określaja˛ poziome i pionowe ścinanie. W klasie QMatrix można bezpośrednio ustawić te wartości: QMatrix(double m11, double m12, double m21, double m22, double dx, double dy), setMatrix(double m11, double m12, double m21, double m22, double dx, double dy). Wykład 4 – p. 19/30 double a = pi/180 * 25; double sina = sin(a); double cosa = cos(a); QMatrix m1(1, 0, 0, 1, 10, -20); QMatrix m2(cosa, sina, -sina, cosa, 0, 0); QMatrix m3(1.2, 0, 0, 0.7, 0, 0); QMatrix m; m = m3 * m2 * m1; Wykład 4 Operacje na macierzach transformacji Ustawienie okna Macierz jednostkowa: Ustawiane okno określa granice modelu, którego projekcja bedzie ˛ wyświetlana na urzadzeniu ˛ graficznym. 1 0 0 0 1 0 0 0 1 Określajac ˛ okno wykorzystujemy współrz˛edne logiczne (modelu). Do ustawienia okna służa˛ metody: void QPainter::setWindow(int x, int y, int w, int h), Do załadowania macierzy jednostkowej do aktualnej macierzy transformacji służy metoda void QPainter::resetMatrix(), void QPainter::setWindow(const QRect & r). Domyślnie współrz˛edne okna sa˛ takie same jak granice urzadzenia ˛ graficznego. Metody do operowania na stosie macierzy transformacji: void QPainter::save(), void QPainter::restore(). Wykład 4 Wykład 4 – p. 21/30 Transformacje - przykład 2 Ustawienie widoku void Transformation::paintEvent(QPaintEvent* e) { QPainter p(this); p.setWindow(-200, -200, 400, 400); p.setViewport(10, 10, width() - 20, height() - 20); p.setBrush(Qt::SolidPattern); p.drawEllipse(-200, -200, 400, 400); p.setFont(QFont("Helvetica", 40, QFont::Bold)); Widok określa położenie i rozmiary prezentowanego modelu na danym urzadzeniu ˛ graficznym. Ustalajac ˛ widok wykorzystuje sie˛ współrz˛edne urzadzenia ˛ graficznego. Do określenia widoku wykorzystuje sie˛ metody: void QPainter::setViewport(int x, int y, int w, int h), void QPainter::setViewport (const QRect & r). p.rotate(-90); for (int i = 1; i <= 12; ++i) { p.rotate(30); p.setPen(QPen(Qt::white, 3)); p.drawLine(190, 0, 200, 0); p.setPen(QPen(Qt::yellow, 3)); QString number; number.setNum(i); p.drawText(150, -20, 40, 40, Qt::AlignHCenter | Qt::AlignVCenter, number); } Domyślne współrz˛edne widoku sa˛ identyczne z współrz˛ednymi urzadzenia ˛ graficznego. } Wykład 4 – p. 23/30 Wykład 4 QInputDialog QInputDialog - przykład QString getText ( QWidget * parent, const QString & title, const QString & label, QLineEdit::EchoMode mode = QLineEdit::Normal, const QString & text = QString(), bool * ok = 0, Qt::WindowFlags f = 0 ), int getInteger ( QWidget * parent, const QString & title, const QString & label, int value = 0, int #include <qapplication.h> #include <qinputdialog.h> #include <unistd.h> minValue = -2147483647, int maxValue = 2147483647, int step = 1, bool * ok = 0, Qt::WindowFlags f = 0 ), double getDouble ( QWidget * parent, const QString & title, const QString & label, double value = 0, double minValue = -2147483647, double maxValue = 2147483647, int decimals = 1, bool * int main(int argc, char** argv) { QApplication app(argc, argv); ok = 0, Qt::WindowFlags f = 0 ), bool ok; QString application = QInputDialog::getText(NULL, "Run", "Nazwa programu:", QLineEdit::Normal, QString::null, &ok, 0 ); if (ok == true) { execlp(application, application, NULL); } QString getItem ( QWidget * parent, const QString & title, const QString & label, const QStringList & list, int current = 0, bool editable = true, bool * ok = 0, Qt::WindowFlags f = 0 ). } Wykład 4 – p. 25/30 QColorDialog Wykład 4 QFontDialog QColor QColorDialog::getColor ( const QColor & initial = Qt::white, QWidget * parent = 0 ), QFont getFont ( bool * ok, QWidget * parent = 0 ), QRgb QColorDialog::getRgba ( QRgb initial, bool * ok = 0, QWidget * parent = 0 ). QFont getFont ( bool * ok, const QFont & initial, QWidget * parent, const QString & caption ). Wykład 4 – p. 27/30 Wykład 4 QMessageBox QFileDialog StandardButton information ( QWidget * parent, const QString & title, const QString & text, QString getOpenFileName ( QWidget * parent = 0, const QString & caption = QString(), const StandardButtons buttons = Ok, StandardButton defaultButton = NoButton ), QString & dir = QString(), const QString & filter = QString(), QString * selectedFilter = 0, StandardButton critical ( QWidget * parent, const QString & title, const QString & text, Options options = 0 ), StandardButtons buttons = Ok, StandardButton defaultButton = NoButton ), QString getSaveFileName ( QWidget * parent = 0, const QString & caption = QString(), const StandardButton question ( QWidget * parent, const QString & title, const QString & text, QString & dir = QString(), const QString & filter = QString(), QString * selectedFilter = 0, StandardButtons buttons = Ok, StandardButton defaultButton = NoButton ), Options options = 0 ), StandardButton warning ( QWidget * parent, const QString & title, const QString & text, QString getExistingDirectory ( QWidget * parent = 0, const QString & caption = QString(), StandardButtons buttons = Ok, StandardButton defaultButton = NoButton ), const QString & dir = QString(), Options options = ShowDirsOnly ), void about ( QWidget * parent, const QString & title, const QString & text ), QStringList getOpenFileNames ( QWidget * parent = 0, const QString & caption = QString(), const QString & dir = QString(), const QString & filter = QString(), QString * selectedFilter = 0, void aboutQt ( QWidget * parent, const QString & title = QString() ). Options options = 0 ). question information warning critical Wykład 4 – p. 29/30 Wykład 4