# Guide miniräknare i Kivy Vi ska bygga en miniräknar-app med hjälp av kivy och python. Appen ska bestå av två fält där man kan skriva in siffror, fyra knapper: en för varje räknesätt och en plats där resultatet skrivs ut. När man har skrivit in två siffror och trycker på en knapp ska rätt operation utföras och resultatet skrivas ut. ### Template kod Vi utgår från template-koden för en kivy-app, och namn: ```python from kivy.app import App class Calculator(App): def build(self): #Här skapar vi alla widgets Calculator().run() ``` ### Layout Vi behöver följande kivy widgets för varje del av vår miniräknare: * 2 st sifferfält --> TextInput * 4 st knappar --> Button * resultattext --> Label Om vi använder oss av en BoxLayout för att lägga allt eftervarandra kan build-funktionen se ut så här: ```python from kivy.app import App from kivy.uix.boxlayout import BoxLayout from kivy.uix.textinput import TextInput from kivy.uix.label import Label from kivy.uix.button import Button class Calculator(App): def build(self): # Tre rutor i början: två inputs, en label layoutWidget = BoxLayout(orientation="vertical") textInputA = TextInput() textInputB = TextInput() layoutWidget.add_widget(textInputA) layoutWidget.add_widget(textInputB) addButton = Button(text="+") layoutWidget.add_widget(addButton) minusButton = Button(text="-") layoutWidget.add_widget(minusButton) multiplicationButton = Button(text="*") layoutWidget.add_widget(multiplicationButton) divisionButton = Button(text="/") layoutWidget.add_widget(divisionButton) resultLabel = Label() layoutWidget.add_widget(resultLabel) return layoutWidget Calculator().run() ``` Vi kan snygga till det genom att lägga knapparna på samma *horisontella* rad. För att göra det skapar vi en till BoxLayout för knapparna, och vi lägger den BoxLayouten i den vertikala BoxLayouten. ```python ... #Skapa en ny layout för knapparna buttonLayout = BoxLayout(orientation="horizontal") addButton = Button(text="+") buttonLayout.add_widget(addButton) minusButton = Button(text="-") buttonLayout.add_widget(minusButton) multiplicationButton = Button(text="*") buttonLayout.add_widget(multiplicationButton) divisionButton = Button(text="/") buttonLayout.add_widget(divisionButton) #Lägg till knapp-layouten i den yttre layouten layoutWidget.add(buttonLayout) ... ``` ### Knapp-funktioner För varje knapp vill vi nu lägga till funktioner som utför beräkningarna. Vi kan lägga till en funktion till en knapp med två steg. 1. Skapa funktionen inuti klassen 2. Anropa bind-funktionen på knappen Till exempel, för plus-knappen kan vi skapa en funktion *add*. Obs! Den behöver ha två parameterar: `self` och `btn` ```python # I Calculator-klassen def add(self, btn): #Här skriver vi kod som körs när vi trycker på knappen ``` Vi lägger till funktionen genom att anropa `bind` med argumentet `on_press=self.add` ``` # I build funktionen: ... addButton = Button(text="+") layoutWidget.add_widget(addButton) addButton.bind(on_press=self.add) ... ``` Vi vill upprepa samma procedur för alla fyra knappar, med olika funktioner som heter relevanta saker. ### Skriva koden för räkneoperationer Nu vill vi se till att `add`-funktionen samt de andra funktionerna inte är tomma. För varje funktion vill vi: 1. Läsa siffran i textInputA 2. Läsa siffran i textInputB 3. Uföra räknesättet med siffrorna 4. Ändra texten på resultat-label För att göra detta måste vi ha tillgång till `textInputA`, `textInputB` och `resultLabel` som finns i build funktionen. Detta löser vi genom att lägga till `self.` framför variabelnamnen. ```python self.textInputA = TextInput() self.textInputB = TextInput() layoutWidget.add_widget(self.textInputA) layoutWidget.add_widget(self.textInputB) ... self.resultLabel = Label() layoutWidget.add_widget(self.resultLabel) ``` Då kan vi komma åt variabelerna i `add`. Vi kommer åt texten i en widget med `.text` och vi kan göra om det till en siffra med `int()`. ```python def add(self, btn): numA = int(self.textInputA.text) numB = int(self.textInputB.text) resultValue = numA + numB self.resultLabel.text = str(resultValue) ``` Efter att vi har plockat ut värdena i TextInput A och B kan vi lägga ihop dem, och sätta resultLabelns text till resultatet. Här gör vi om värdet till en string igen med `str()`. Nu behöver vi endast skapa de andra funktionerna på samma sätt, men med andra räknesätt!