Programmeerimine keeles C++
Praktikum 5: lisateegi kasutamine: Qt raamistik
Üldised tingimused
Tähtis! Loe läbi ülesannete vormistamise tingimused aine veebilehelt! Ülesandeid esitatakse läbi aine veebilehel asuva vormi. E-posti teel lahendusi vastu ei võeta. Küsimustega pöörduda aine listi või praktikumijuhendaja poole.
Lahendamiseks on aega 14 päeva.
Tähtaeg: 17.04.2022 23:59:59
Märkus: Palun kasutage Qt raamistikku 5.0 või uuemat.
Üldised nõuded
Kirjutage joonistusprogramm, mille abil saab joonistada tippe ning neid ühendavaid sirglõike. Meenutage neljanda praktikumi DynamicLine klassi ning selle rakenduseideed.
NB! Ülesanne eeldab, et te taaskasutate sealset klassi DynamicLine.
Praktikumi alusprogrammis on toodud lihtne Qt projekt, mille projektifailid on .pro laiendiga. Qt Creatori nimelises töökeskkonnas saab programmi triviaalsel viisil kompileerida ja käivitada.
Käesolev praktikum on erandlik, sest lahendi esitamisel pole Makefile'i olemasolu kohustuslik. Lahenduste kontrollimisel kasutatakse Qt Creatorit. NB! Erand ei laiene teistele praktikumidele.
Teie ülesandeks on vastavalt ülesande tekstile täiendada alusprogrammi. Nagu tavaliselt, on viited ülesande lahendamiseks vajalikele materjalidele praktikumi veebilehel.
Ülesanne 1 – Fikseerige alusprogrammi akna suurus (1 punkt)
Alusprogrammi Joonistamine
akna suurust saab hetkel muuta, mis aga võib muuta keeruliseks hilisemad ülesanded. Fikseerige joonistusala suuruseks 800x600 pikslit ning keelake peaakna suuruse muutmine.
Ülesanne 2 – Programmi üldine väljanägemine (1 punkt)
Programmi akna 800x600 joonistusala taust peab olema teie lemmikvärvi, näiteks sinakasroheline. Programmi peamenüüs on tööriista valimiseks eraldi menüü „Tools“, kus on järgnevad elemendid:
Add vertex Move vertex Delete vertex Add line Delete line
Lisage programmi peaakna alumisse äärde olekuriba, millel on kolm osa. Esimene osa näitab parasjagu aktiivse tööriista nime. Teine ja kolmas osa näitavad vastavalt mitu tippu ja joont on joonisel („Vertices: <arv>“, „Lines: <arv>“). Vihje: olekuriba tekstialade lisamiseks saab kasutada QLabel klassi.
Vajalikud käsud leiate Qt dokumentatsioonist, kas Qt Creatori dokumentatsioonist või internetist:
- Signaalid ja pesad: http://qt-project.org/doc/qt-5.0/qtcore/signalsandslots.html
- QMainWindow: http://qt-project.org/doc/qt-5.0/qtwidgets/qmainwindow.html
- QWidget: http://qt-project.org/doc/qt-5.0/qtwidgets/qwidget.html
- QMenuBar: http://qt-project.org/doc/qt-5.0/qtwidgets/qmenubar.html
- QStatusBar: http://qt-project.org/doc/qt-5.0/qtwidgets/qstatusbar.html
- QMenu: http://qt-project.org/doc/qt-5.0/qtwidgets/qmenu.html
- QAction: http://qt-project.org/doc/qt-5.0/qtwidgets/qaction.html
- QLabel: http://qt-project.org/doc/qt-5.0/qtwidgets/qlabel.html
Ülesanne 3 – Tippude lisamine (2 punkti)
Kui kasutaja on menüüst valinud tipu lisamise, on programm tipu lisamise režiimis. Selle tähistamiseks ilmub olekuribale esimesele osale tekst „Adding vertices“
. Kui programm on tipu lisamise režiimis, siis hiire vasakule nupule vajutamine mingis joonistamisala punktis tekitab
sellesse punkti tipu. Tippu tähistatakse musta ringiga, mille läbimõõduks ligikaudu 20 pikslit. Tippu ei lisata, kui 10 piksli raadiuses juba on tipp. Lähedaste tippude otsimisel kasutage varem loodud point klassi meetodeid. Kui üks tipp on lisatud, siis programm jääb tipu lisamise režiimi.
Selleks tuleb joonistusalal realiseerida hiireklikki töötlev meetod:
void QWidget::mousePressEvent(QMouseEvent *event);
Ning täiendada meetodit:
void QWidget::paintEvent(QPaintEvent *event);
Vihje: peate looma andmestruktuurid oleku (tipud, lõigud) salvestamiseks, hiirekliki peale seda uuendama ning paintEvent klassis andmete põhjal ekraanile joonistama.
Hiirenuppe loetleb Qt::MouseButton (QMouseEventi juurest leiate). Veel on abiks QPainter klass: http://qt-project.org/doc/qt-5.0/qtgui/qpainter.html. Renderdamise kohta on natuke kirjas ka klassi QRect dokumentatsioonis: http://qt-project.org/doc/qt-5.0/qtcore/qrect.html.
Ülesanne 4 – Tippude liigutamine (2 punkti)
Kui menüüst on valitud tipu liigutamine, satub programm tipu liigutamise režiimi. Vastavaks olekuriba tekstiks olgu „Moving vertices“
. Kui kasutaja vajutab hiire vasaku nupu alla joonisel oleval tipul või sellest kuni 10 piksli kaugusele, siis muutub tipp liikuvaks ning kasutaja saab hiirt liigutades tippu liigutada. Kui tipuga on seotud mõni joon, siis peab see kaasa liikuma. Kui kasutaja laseb hiirenupu lahti, jääb tipp uude punkti paigale. Tippu ei saa liigutada joonistusalalt välja. Pärast ühe tipu liigutamist saab kasutaja valida järgmise tipu. Kui joonistusalal tippe pole, siis sellesse režiimi minna ei saa.
Lahendus teenib punktid siis, kui tippe saab liigutada ning jooned liiguvad tipuga kaasa.
Selleks tuleb joonistusalal realiseerida lisaks meetodid:
void QWidget::mouseMoveEvent(QMouseEvent *event); void QWidget::mouseReleaseEvent(QMouseEvent *event);
Ülesanne 5 – Tippude kustutamine (2 punkti)
Menüüst tippude kustutamise režiimi valik lubab joonistatud tippe kustutada. Kasutajat teavitab sellest olekuribal kiri „Deleting vertices“
. Vasaku hiirenupuga tipul (või 10 piksli raadiuses)
vajutades kustutatakse tipp ja kõik jooned, mis sellega seotud on. Kui üks tipp on kustutatud, saab kasutaja kohe järgmise tipu kustutada. Kui joonistusalal tippe pole, siis sellesse režiimi minna ei saa.
Ülesanne 6 – Sirglõikude lisamine (2 punkti)
Menüüst sirglõigu lisamise valik viib programmi sirglõikude lisamise režiimi. Seda vaid juhul, kui on lisatud kaks või rohkem tippu. Sisenemisel seatakse olekuriba tekstiks „Adding lines“
. Kasutaja saab nüüd mõnel tipul vasaku hiirenupu alla vajutades valida esimese tipu (10 piksli raadiuse nõue kehtib ikka). Vajutades nüüd hiire vasakut klahvi mõne teise tipu lähedal (taas 10 piksli nõue) saab kasutaja valida teise tipu. Kui kasutaja on edukalt kaks erinevat tippu valinud,
luuakse nende vahele sirglõik. Sirglõiku tähistatakse 1-piksli paksuse musta joonega. Programm on uuesti joone lisamise režiimis ning kasutaja saab valida esimest tippu.
Soovitus: kui esimene tipp on valitud, värvige see mõnda teist värvi. See pole hindamisel kohustuslik, kuid teeb programmi mugavamaks ja testida on toredam.
Lisaülesanne 7 – Sirglõigu kustutamine (1 lisapunkt)
Kui kasutaja valib menüüst lõikude kustutamise, siis satub ta režiimi nimega „Deleting lines“
. Selles režiimis kustutatakse vasakut hiirenuppu alla vajutades sirglõik, millel hiirekursor asub.
Kasutaja peab joone kustutamiseks vajutama vasaku nupuga joone peale või sellest piksli kaugusele. Pikslit läbivate sirglõikude leidmiseks kasutage näiteks joone võrrandeid. Selle kohta leiate materjali siit: http://www.cut-the-knot.org/Curriculum/Calculus/DistanceToLine.shtml
Kui ühte pikslit läbib mitu joont, siis kustutage esimene, mille leiate. Kasutaja saab kustutada mitu sirglõiku järjest.
Vihjeid lahenduse jaoks
- Kui te ei kasuta Qt Creatorit, peab uute failide lisamisel nende nimed lisama ka vastavasse Qt projektifaili (faililaiend .pro).
- Kasutage mingit andmestruktuuri joonisele lisatud tippude ja sirgete hoidmiseks. Arvestage, et kuna DynamicLine tahab hoida viitasid tippudele, peate te tagama, et DynamicLine'ile antud tippude aadressid ei muutu töö käigus.
- Olge väga ettevaatlikud
std::vector
andmestruktuuri kasutamisel tippude salvestamisel. Tippude lisamine või eemaldamine vektori keskele võib tekitada olukorra, kus DynamicLine tippude viidad enam ei kehti. - Kirjutage endale funktsioon, mis ekraani koordinaatide järgi tagastab andmestruktuurist lähima tipu. Võite teha ka nii, et kui 10 piksli raadiuses tippu ei ole, siis ei tagastata midagi. Kasutage sellist funktsiooni igal pool, kus on vaja tippu valida. Sarnase funktsiooni võib kirjutada ka sirglõikude jaoks.
- Funktsiooni tr() abil saab teha kergemini tõlgitavaid rakendusi. Näiteks:
m_label->setText (tr ("Siia tuleb tekst"));
(täpsem info: http://qt-project.org/doc/qt-5.0/qtcore/qtranslator.html). - Kui kood ei tööta päris nii nagu peaks, tasub kasutada debuggerit, mis enamasti aitab kiiremini probleemile jälile jõuda, kui lihtsalt ekraanile teksti välja trükkimine.
(täpsem info: http://doc.qt.io/qtcreator/creator-debugging.html)