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;
}