Search code examples
androidpythonkivyapkbuildozer

Usage of 2 page layouts on kivy in a single app and emulator for kivy


I made a simple Calculator app using Kivy. The problem I am facing is I am able to use just one layout in the app. I am able to use just grid layout while I need to have Page Layout as well as Grid Layout. I want a slider through which I can scroll and see rest of the buttons in the app instead of all the buttons on one Page.More Precisely The Code is:

main.py

from __future__ import division
import kivy
from math import sqrt
from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.config import Config
from kivy.uix.pagelayout import PageLayout
class CalcGridLayout(GridLayout):
    def something(x):
        x+="hi"
        return x
    # Function called when equals is pressed
    def calculate(self, calculation):
        if calculation:
            try:
                # Solve formula and display it in entry
                # which is pointed at by display
                self.display.text = str(eval(calculation))
            except Exception:
                self.display.text = "Galat Hai Bhai !"
class CalculatorApp(App):
    def build(self):
        return CalcGridLayout()
calcApp = CalculatorApp()
calcApp.run()
#buildozer init
#buildozer android debug deploy ---------------code to deploy into apk and then transfer the file into ur mobile

calculator.kv:

# Custom button
<CustButton@Button>:
    font_size: 65
    #color:.25,.80,.92,1
    size:100,100
    background_color:.50,.50,.50,1

# Define id so I can refer to the CalcGridLayout
# class functions
# Display points to the entry widget
<CalcGridLayout>:
    id: calculator
    display: entry
    rows: 8
    padding: 0
    spacing: 0

    # Where input is displayed
    BoxLayout:
        TextInput:
            id: entry
            font_size: 80
            multiline: False

    # When buttons are pressed update the entry
    BoxLayout:
        spacing: 0
        CustButton:
            text: "7"
            on_press: entry.text += self.text
        CustButton:
            text: "8"
            on_press: entry.text += self.text
        CustButton:
            text: "9"
            on_press: entry.text += self.text
        CustButton:
            text: "+"
            on_press: entry.text += self.text

    BoxLayout:
        spacing: 0
        CustButton:
            text: "4"
            on_press: entry.text += self.text
        CustButton:
            text: "5"
            on_press: entry.text += self.text
        CustButton:
            text: "6"
            on_press: entry.text += self.text
        CustButton:
            text: "-"
            on_press: entry.text += self.text

    BoxLayout:
        spacing: 0
        CustButton:
            text: "1"
            on_press: entry.text += self.text
        CustButton:
            text: "2"
            on_press: entry.text += self.text
        CustButton:
            text: "3"
            on_press: entry.text += self.text
        CustButton:
            text: "*"
            on_press: entry.text += self.text

    # When equals is pressed pass text in the entry
    # to the calculate function
    BoxLayout:
        spacing: 0
        CustButton:
            text: "AC"
            on_press: entry.text = ""
        CustButton:
            text: "0"
            on_press: entry.text += self.text
        CustButton:
            text: "="
            on_press: calculator.calculate(entry.text)
        CustButton:
            text: "/"
            on_press: entry.text += self.text
    #my new layout
    BoxLayout:
        spacing: 0
        CustButton:
            text: "Del"
            on_press: entry.text =entry.text[:-1] 
        CustButton:
            text: "Pow"
            on_press: entry.text += '**'
        CustButton:
            text: "//"
            on_press: entry.text +=self.text
        CustButton:
            text: "mod"
            on_press: entry.text +='%'
    BoxLayout:
        CustButton:
            text: "Made for learning face"

Now the output of this app is pretty simple : enter image description here

Over here all the numbers and operations are there only on one single page. I want another page which I can scroll and it must contain operations like '(',')'. I was thinking of implementing Page Layout for that but wasn't able to implement both the layout(Grid+Page) in the app. Could someone please help. Also my second doubt was that can I simultaneously check the app on mobile(kinda emulator), I tried using Kivy Remote Shell but it didn't work. And every time I have to use buildozer init and then deploy which itself takes much time. And then transfer the apk file in mobile using USB and then test. It's time consuming.


Solution

  • you are right on wanting to use the PageLayout and it can be done,just follow these steps:

    Step 1: In your main.py add this line:

    from kivy.uix.pagelayout import PageLayout
    

    Then in your CalcGridLayout class inherit from PageLayout instead of GridLayout like this:

    class CalcGridLayout(PageLayout):
    

    Step 02: In your calculator.kv right after <CalcGridLayout>: add the following:

    GridLayout:
    

    then indent your code as needed.A working example is below..taken from your code:main.py

    from __future__ import division
    import kivy
    from math import sqrt
    from kivy.app import App
    from kivy.uix.gridlayout import GridLayout
    from kivy.uix.pagelayout import PageLayout
    from kivy.config import Config
    from kivy.uix.pagelayout import PageLayout
    
    class CalcGridLayout(PageLayout):
        def something(x):
            x+="hi"
            return x
        # Function called when equals is pressed
        def calculate(self, calculation):
            if calculation:
                try:
                    # Solve formula and display it in entry
                    # which is pointed at by display
                    self.display.text = str(eval(calculation))
                except Exception:
                    self.display.text = "Galat Hai Bhai !"
    class CalculatorApp(App):
        def build(self):
            return CalcGridLayout()
    if __name__=='__main__':
        calcApp = CalculatorApp()
        calcApp.run()
    

    and calculator.kv

    # Custom button
    <CustButton@Button>:
        font_size: 65
        #color:.25,.80,.92,1
        size:100,100
        background_color:.50,.50,.50,1
    
    # Define id so I can refer to the CalcGridLayout
    # class functions
    # Display points to the entry widget
    <CalcGridLayout>:
        GridLayout:
            id: calculator
            display: entry
            rows: 8
            padding: 0
            spacing: 0
    
            # Where input is displayed
            BoxLayout:
                TextInput:
                    id: entry
                    font_size: 80
                    multiline: False
    
            # When buttons are pressed update the entry
            BoxLayout:
                spacing: 0
                CustButton:
                    text: "7"
                    on_press: entry.text += self.text
                CustButton:
                    text: "8"
                    on_press: entry.text += self.text
                CustButton:
                    text: "9"
                    on_press: entry.text += self.text
                CustButton:
                    text: "+"
                    on_press: entry.text += self.text
    
            BoxLayout:
                spacing: 0
                CustButton:
                    text: "4"
                    on_press: entry.text += self.text
                CustButton:
                    text: "5"
                    on_press: entry.text += self.text
                CustButton:
                    text: "6"
                    on_press: entry.text += self.text
                CustButton:
                    text: "-"
                    on_press: entry.text += self.text
    
            BoxLayout:
                spacing: 0
                CustButton:
                    text: "1"
                    on_press: entry.text += self.text
                CustButton:
                    text: "2"
                    on_press: entry.text += self.text
                CustButton:
                    text: "3"
                    on_press: entry.text += self.text
                CustButton:
                    text: "*"
                    on_press: entry.text += self.text
    
            # When equals is pressed pass text in the entry
            # to the calculate function
            BoxLayout:
                spacing: 0
                CustButton:
                    text: "AC"
                    on_press: entry.text = ""
                CustButton:
                    text: "0"
                    on_press: entry.text += self.text
                CustButton:
                    text: "="
                    on_press: calculator.calculate(entry.text)
                CustButton:
                    text: "/"
                    on_press: entry.text += self.text
            #my new layout
            BoxLayout:
                spacing: 0
                CustButton:
                    text: "Del"
                    on_press: entry.text =entry.text[:-1] 
                CustButton:
                    text: "Pow"
                    on_press: entry.text += '**'
                CustButton:
                    text: "//"
                    on_press: entry.text +=self.text
                CustButton:
                    text: "mod"
                    on_press: entry.text +='%'
            BoxLayout:
                CustButton:
                    text: "Made for learning face"
        BoxLayout:
            id: test
            Button:
                text: 'You can then add more widgets here'
    

    Finally regarding an emulator,this is no real emulator in kivy as of yet however you can simulate a device by configuring your app to run on a certain device's specs e.g to run your app simulating Motorola droid 2:

    KIVY_DPI=240 KIVY_METRICS_DENSITY=1.5 python main.py --size 854x480
    

    or the HTC ONE X:

    KIVY_DPI=320 KIVY_METRICS_DENSITY=2 python main.py --size 1280x720
    

    or any other device:

    KIVY_DPI=<your-desired-dpi> KIVY_METRICS_DENSITY=<your-device-density> python main.py --size <your-device-size>