Grafiske Brukergrensesnitt (GUI)
Konstruksjon av grafiske grensesnitt
Grafiske grensesnitt består av en rekke GUI elementer som kalles widgets. Dette kan være knapper, tekstfelt eller dropdown-lister.

Callback
Et «callback» er en funksjon som kalles etter at en spesifikk hendelse har inntruffet. Disse brukes ofte med brukergrensesnitt, for eksempel for å spesifisere hva som skal skje etter brukeren har trykket på en knapp. Hvert GUI-element lar deg definere én slik funksjon som blir kjørt etter hver interaksjon. Nøyaktig hvilken interaksjon er avhengig av GUI-elementet.
For å vise hvordan man definerer og bruker en callback funksjon, fortsetter vi med samme eksempelet som før:
#include "AnimationWindow.h"
#include "widgets/Button.h"
int main() {
const TDT4102::Point buttonPosition {100, 100};
const unsigned int buttonWidth = 100;
const unsigned int buttonHeight = 40;
const string buttonLabel = "Click me!";
TDT4102::Button button {buttonPosition, buttonWidth, buttonHeight, buttonLabel};
TDT4102::AnimationWindow window;
window.add(button);
window.wait_for_close();
return 0;
}
Vi kan nå definere callback funksjonen. Den skal ha ingen parametere, og returnere void. Det er mulig å definere flere callback funksjoner i en enkelt fil, og navnet på funksjonene er ikke viktig. Flere GUI elementer kan ha samme callback funksjonen.
#include "AnimationWindow.h"
#include "widgets/Button.h"
void callbackFunction() {
std::cout << "This is printed when this function is executed." << std::endl;
}
int main() {
const TDT4102::Point buttonPosition {100, 100};
const unsigned int buttonWidth = 100;
const unsigned int buttonHeight = 40;
const string buttonLabel = "Click me!";
TDT4102::Button button {buttonPosition, buttonWidth, buttonHeight, buttonLabel};
TDT4102::AnimationWindow window;
window.add(button);
window.wait_for_close();
return 0;
}
Den siste steget er å bruke callbackFunction() funksjonen som callback av knappen vi laget tidligere. Vi gjør dette ved å bruke setCallback() funksjonen, med navn på funksjonen som vi ønsker å bruke som parameter:
#include "AnimationWindow.h"
#include "widgets/Button.h"
void callbackFunction() {
std::cout << "This is printed when this function is executed." << std::endl;
}
int main() {
const TDT4102::Point buttonPosition {100, 100};
const unsigned int buttonWidth = 100;
const unsigned int buttonHeight = 40;
const string buttonLabel = "Click me!";
TDT4102::Button button {buttonPosition, buttonWidth, buttonHeight, buttonLabel};
TDT4102::AnimationWindow window;
button.setCallback(callbackFunction);
window.add(button);
window.wait_for_close();
return 0;
}
Når vi kjører dette programmet og klikker på knappen ser vi at callback funksjonen skriver ut tekst på skjermen:

Objekt-orienterte callback funksjoner
Dersom man ønsker å sette callback-funksjonen til en klassemetode må man bruke std::bind for å gjøre funksjonen kompatibel.
class SuperManWindow : public TDT4102::AnimationWindow {
public:
SuperManWindow();
void superCallbackFunction();
void fly();
private:
TDT4102::Button flyButton;
};
void SuperManWindow::superCallbackFunction() {
std::cout << "Thanks for clicking, im going to fly\n";
this->fly();
// Do something else
}
SuperManWindow::SuperManWindow()
: AnimationWindow(50, 50, 500, 500, "Super man window"),
flyButton{{100, 100}, 50, 50, "fly"} {
// Here we convert the class method to a void function
// by binding this instance of the class to the function
flyButton.setCallback(std::bind(&SuperManWindow::superCallbackFunction, this));
add(flyButton);
}
GUI Elementer
Hvert GUI element som kan brukes i TDT4102::AnimationWindow er definert i sin egen klasse som arver fra TDT4102::Widget. GUI elementer som støttes er TDT4102::Button , TDT4102::TextInput og TDT4102::DropdownList. Hvis du for eksempel ønsker å vise en knapp i vinduet, lager du en instans av TDT4102::Button klassen og legger den til i vinduet ved å bruke medlemsfunksjonen:
Hvis du ikke ønsker å vise knappen med en gang, kan du kalle på funksjonen setVisible(bool isVisible) med false på knapp-variabelen for å skjule elementet. Bruk true for å vise elementet.
Knapp
En knapp er et GUI element som gjør noe når du klikker på den:

Her er et eksempel som vises hvordan den brukes:
#include "AnimationWindow.h"
#include "widgets/Button.h"
void buttonClicked() {
std::cout << "Someone clicked on me!" << std::endl;
}
int main() {
const TDT4102::Point buttonPosition {100, 100};
const unsigned int buttonWidth = 100;
const unsigned int buttonHeight = 40;
const string buttonLabel = "Click me!";
TDT4102::Button button {buttonPosition, buttonWidth, buttonHeight, buttonLabel};
TDT4102::AnimationWindow window;
window.add(button);
button.setCallback(buttonClicked);
button.setButtonColor(TDT4102::Color::silver);
window.wait_for_close();
return 0;
}
Merk at vi må først inkludere headeren til TDT4102::Button klassen ved å skrive #include "widgets/Button.h" øverst i filen.
Deretter lager vi en knapp ved å instansiere TDT4102::Button klassen, som har følgende konstruktør:
TDT4102::Button(TDT4102::Point location, unsigned int width, unsigned int height, std::string label);
Her definerer TDT4102::Point location hvor knappen skal plasseres på skjermen, width og height størrelsen, og label teksten som skal vises på knappen. Vi bruker add() og setCallback() funksjonene for å sørge at knappen blir synlig i vinduet, og at det skjer noe når vi klikker på den.
Callback funksjonen blir kalt hver gang brukeren klikker på knappen.
Buttonklassen har diverse funksjoner for å endre på utseende.
void setLabel(std::string newLabel);
void setLabelColor(TDT4102::Color newColor);
void setButtonColor(TDT4102::Color newColor);
void setButtonColorHover(TDT4102::Color newColor);
void setButtonColorActive(TDT4102::Color newColor);
Du kan endre tekst og tekstfarge med setLabel og setLabelColor. Du kan endre fargen for knappen med setButtonColor, fargen når du har musepekeren over med setButtonColorHover og fargen på knappen når den er trykket ned med setButtonColorActive.
Tekstfelt
Et tekstfelt er et GUI element hvor man kan skrive inn tekst. Det er også mulig å hente ut teksten som er i tekstfelet med funksjonen TDT4102::TextInput::getText(). For å skrive til et tekstfelt bruker vi funksjonen TDT4102::TextInput::setText(std::string text).

#include "AnimationWindow.h"
#include "widgets/TextInput.h"
TDT4102::TextInput textField {{100, 100}, 300, 30, "This text field is small!"};
void textFieldChanged() {
std::cout << "The text field now contains: " << textField.getText() << std::endl;
}
int main() {
TDT4102::AnimationWindow window;
window.add(textField);
textField.setCallback(textFieldChanged);
window.wait_for_close();
return 0;
}
Tekstfeltene kan også være over flere linjer:

#include "AnimationWindow.h"
#include "widgets/TextInput.h"
TDT4102::TextInput textField {{100, 100}, 300, 150, "This text field\ncontains more than\none line of text!"};
void textFieldChanged() {
std::cout << "The text field now contains: " << textField.getText() << std::endl;
}
int main() {
TDT4102::AnimationWindow window;
window.add(textField);
textField.setCallback(textFieldChanged);
window.wait_for_close();
return 0;
}
DropdownList
Dropdown-liste har en liste med elementer som man kan velge mellom. Det valgte elementet henter vi ut med funksjonen TDT4102::DropdownList::getSelectedValue(). For å endre på elementene i lista, kall på funksjonen TDT4102::DropdownList::setOptions(std::vector<std::string> &updatedOptionsList) med en vector som inneholder de nye elementene.

#include "AnimationWindow.h"
#include "widgets/DropdownList.h"
std::vector<std::string> options {"Hello", "There", "General", "You", "Are", "A", "Bold", "One"};
TDT4102::DropdownList list({100, 100}, 300, 30, options);
void handle() {
std::cout << "Selected: " << list.getSelectedValue() << std::endl;
}
int main()
{
TDT4102::AnimationWindow window;
window.add(list);
list.setCallback(handle);
window.wait_for_close();
return 0;
}