Filip Phigari
Filip Phigari

Reputation: 135

How to Use Console for Input while also using Kivy UI ? (Python with Kivy)

Question:

How do I access console for input without causing Kivy UI to freeze up?

Or, alternatively, how do I easily translate 1,000 input requests into Kivy UI format? (I'm skeptical of this at all being quick and easy)

Why I want this:

I have a program that asks for an exorbitant amount of input response from user. Upwards of 1,000 questions. Ideally, I'd have all the user input nested in the UI, but it seems like that would take way too long to program. So I've opted (for the time being) to have the user refer to the Python console to answer all the questions..

Potential Alternative to My Approach:

Find an easy way to implement console input requests into Kivy UI format... But with a 1,000 questions to ask, that approach seems rather daunting.

Current Problem:

When I click on 'Begin', the console then prompts for input.. However, simultaneously, the kv app ceases to respond. Which makes sense. But it'd be nice if it didn't crash when the user tries to click a button without responding to the console input request. I'm just unsure of how to prevent that.

Below is a runnable example...

Python Code:

from kivy.app import App
# kivy.require("1.10.0")
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen, FadeTransition
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.widget import Widget
from kivy.uix.scrollview import ScrollView
from kivy.properties import StringProperty, ObjectProperty, NumericProperty

class ScrollableLabel(ScrollView):
    text = "blah blah blah"

class AnotherScreen(Screen):
    text = StringProperty("BEGIN")
    def new(self):
        text = "SEE CONSOLE!"      

class BackHomeWidget(Widget):
    pass

class MainScreen(Screen):
    pass

class ScreenManagement(ScreenManager):
    pass

presentation = Builder.load_file("Test_Running_Console.kv")

class MainApp(App):

    def goofytest(self):
        goofy = input("Enter something: ")

    def build(self):
        return presentation

if __name__ == "__main__":
    MainApp().run()

Kv Code:

#: import FadeTransition kivy.uix.screenmanager.FadeTransition

ScreenManagement:
    transition: FadeTransition()
    MainScreen:
    AnotherScreen:

<SmallNavButton@Button>:    
    font_size: 32
    size: 125, 50    
    color: 0,1,0,1

<MedButton@Button>:
    font_size: 30
    size_hint: 0.25, 0.1
    color: 0,1,0,1

<BackHomeWidget>:
    SmallNavButton:
        on_release: app.root.current = "main"
        text: "Home"
        pos: root.x, root.top - self.height

<ScrollableLabel>:
    Label:
        id: dataentryinstructions
        text: root.text
        font_size: 20
        text_size: self.width, None
        size_hint_y: None
        height: self.texture_size[1]
        padding_y: 10
        padding_x: 200

<MainScreen>:
    name: "main"
    FloatLayout: 
        MedButton:
            on_release: app.root.current = "newgarage"
            text: "Create New"
            pos_hint: {"x":0.3728, "top": 0.4}

<AnotherScreen>:
    name: "newgarage"
    ScrollableLabel:
    BackHomeWidget:
    FloatLayout:
        MedButton:
            text: "Begin"
            pos_hint: {"right":1, "top": 1}
            on_release: 
                root.new()
                app.goofytest()
    FloatLayout:
        MedButton
            text: "1. Stuff"
            pos_hint: {"x":0, "top": 0.75}
        MedButton:
            text: "2. Stuff"
            pos_hint: {"x":0, "top": 0.6}
        MedButton:
            text: "3. Stuff"
            pos_hint: {"x":0, "top": 0.45}
        MedButton:
            text: "4. Stuff"
            pos_hint: {"x":0, "top": 0.3}
        MedButton:
            text: "5. Stuff"
            pos_hint: {"x":0, "top": 0.15}

Upvotes: 0

Views: 413

Answers (1)

eyllanesc
eyllanesc

Reputation: 243975

input() is a blocking task, and that kind of tasks are not friendly with the GUI since they block the main thread, a possible solution is to execute it in another thread:

import threading

class MainApp(App):
    def goofytest(self):
        thread = threading.Thread(target=self.input_threading)
        thread.daemon = True
        thread.start()

    def input_threading(self):
        goofy = input("Enter something: ")
        print(goofy)

    def build(self):
        return presentation

Upvotes: 1

Related Questions