from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.gridlayout import GridLayout
from kivy.uix.textinput import TextInput
from kivy.uix.button import Button
from kivy.uix.screenmanager import ScreenManager, Screen
import json
import re
class Grid(GridLayout):
def __init__(self, **kwargs):
super(Grid, self).__init__(**kwargs)
# Columns for the main view
self.cols = 1
# Start of the Inside
self.inside = GridLayout()
self.inside.rows = 3
self.inside.add_widget(Label(text = 'Enter the Brand Name for its Products: '))
self.brand_input = TextInput(multiline = False)
self.inside.add_widget(self.brand_input)
# Add the things in inside to the main
self.add_widget(self.inside)
self.submit = Button(text = 'Submit', font_size = 20)
self.submit.bind(on_press = self.pressed)
self.add_widget(self.submit)
def pressed(self, instance):
# Pull the text inside the textInput
brand_name = self.brand_input.text
with open('mcg_app/brands.json', 'r') as f:
brands_dict = json.load(f)
request = brands_dict[brand_name]
modified_result = re.sub(r',\s(?![^(]*\))', "\n", str(request))
self.inside.add_widget(Label(text = modified_result))
# Clear out the fields after submitting
self.brand_input.text = ''
class Mcg(App):
def build(self):
return Grid()
if __name__ == '__main__':
Mcg().run()
Hello, this program here has a text input box and the user inputs a brand name for example "Dove" after that he presses the submit button, and the button is connected to the pressed() function. Everything about the program is actually working fine the only problem is after I print the products of the entered brand let's say he inputs a different brand in that case the old output is still there so the program outputs new products with the old ones already there. How can I fix this? Thanks in advance
I can't really test it without a json data file, but check out this:
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.gridlayout import GridLayout
from kivy.uix.textinput import TextInput
from kivy.uix.button import Button
import json
import re
class Grid(GridLayout):
def __init__(self, **kwargs):
super(Grid, self).__init__(**kwargs)
# Columns for the main view
self.cols = 1
# Start of the Inside
self.inside = GridLayout()
self.inside.rows = 3
self.inside.add_widget(Label(text='Enter the Brand Name for its Products: '))
self.brand_input = TextInput(multiline=False)
self.inside.add_widget(self.brand_input)
# Add the things in inside to the main
self.add_widget(self.inside)
self.submit = Button(text='Submit', font_size=20)
self.submit.bind(on_press=self.pressed)
self.add_widget(self.submit)
def pressed(self, instance):
# Clear out the fields after submitting
self.brand_input.text = ''
self.inside.clear_widgets()
self.inside.add_widget(Label(text='Enter the Brand Name for its Products: '))
self.inside.add_widget(self.brand_input)
# Pull the text inside the textInput
brand_name = self.brand_input.text
with open('mcg_app/brands.json', 'r') as f:
brands_dict = json.load(f)
request = brands_dict[brand_name]
modified_result = re.sub(r',\s(?![^(]*\))', "\n", str(request))
self.inside.add_widget(Label(text=modified_result))
class Mcg(App):
def build(self):
return Grid()
if __name__ == '__main__':
Mcg().run()
It resets the self.inside GridLayout on every button press...
Related
I need to make an application consisting of a window. In its upper half, this window has 2 text boxes and a button, aligned horizontally.
If you enter two numbers, one in each of the text boxes, and press the button, an operation of these two numbers is displayed in the lower half of the screen.
In the middle of the screen, 4 checkboxes (addition, subtraction, multiplication or division) to define the operation on the 2 numbers.
If one of the two numbers is not a digit, an error message is displayed.
from kivy.app import App
from kivy.config import Config
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.textinput import TextInput
from kivy.uix.checkbox import CheckBox
class MyApp(App):
def __init__(self, **kwargs):
super().__init__()
self.a = None
self.b = None
self.button = None
self.display = None
def build(self):
self.title = 'Addition'
"""------------------------------------------------"""
calc = BoxLayout(orientation='horizontal')
self.a = TextInput(multiline=False)
calc.add_widget(self.a)
calc.add_widget(Label(text='+', font_size=20))
self.b = TextInput(multiline=False)
calc.add_widget(self.b)
self.button = Button(text='Entrer', font_size=20)
self.button.bind(on_press=self.add_numbers)
calc.add_widget(self.button)
"""------------------------------------------------"""
check = BoxLayout(orientation='horizontal')
check.add_widget(CheckBox(group='op'))
check.add_widget(Label(text='add'))
check.add_widget(CheckBox(group='op'))
check.add_widget(Label(text='sub'))
check.add_widget(CheckBox(group='op'))
check.add_widget(Label(text='mult'))
check.add_widget(CheckBox(group='op'))
check.add_widget(Label(text='div'))
"""------------------------------------------------"""
display = BoxLayout(orientation='horizontal')
self.display = Label(text='Result: ')
display.add_widget(self.display)
"""------------------------------------------------"""
box = BoxLayout(orientation='vertical')
box.add_widget(calc)
box.add_widget(check)
box.add_widget(display)
return box
def add_numbers(self, instance):
num1 = self.a.text
num2 = self.b.text
try:
somme = float(num1) + float(num2)
self.display.text = "Result: " + str(somme)
except ValueError:
self.display.text = "Erreur, vous devez entrer des chiffres."
Config.set('graphics', 'width', '350')
Config.set('graphics', 'height', '50')
if __name__ == '__main__':
MyApp().run()
That's my program at the moment.
I've been trying to link the checkboxes to the function but without success
Can somebody help me?
I am making a project involving looking up images. I decided to use kivy, creating a system where you can input a name of a folder (located in a specific directory) into a search bar, and it will return all images inside said folder tagged '.jpg'. I am stuck with updating the window to display these images, and I can't find anything online which helps.
from kivy.properties import StringProperty, ObjectProperty
from kivy.uix.screenmanager import Screen
from kivymd.app import MDApp
from kivy.uix.textinput import TextInput
from kivy.uix.button import Button
from kivy.uix.gridlayout import GridLayout
from kivy.uix.widget import Widget
from kivy.uix.image import Image
from kivy.core.window import Window
import glob
import os
os.chdir(r'directory/of/imagefolders')
class functions:
def lookup(name):
root = f'imagefolder'
for root, subdirs, files in os.walk(f'imagefolder'):
for d in subdirs:
if d == name:
print(d)
path = f'imagefolder/'+d
print(path)
return path
def load_images(f):
facefile = []
for images in glob.glob(f + '\*.jpg'):
facefile.append(images)
print(facefile)
return facefile
class MainApp(MDApp):
def build(self):
Window.clearcolor = (1,1,1,1)
layout = GridLayout(cols=2, row_force_default=True, row_default_height=40,
spacing=10, padding=20)
self.val = TextInput(text="Enter name")
submit = Button(text='Submit', on_press=self.submit)
layout.add_widget(self.val)
layout.add_widget(submit)
return layout
def submit(self,obj):
print(self.val.text)
layout2 = GridLayout(cols=2, row_force_default=True, row_default_height=40,
spacing=10, padding=20)
name = self.val.text
f = functions.lookup(name)
print(f)
facefile = functions.load_images(f)
x = len(facefile)
print(x)
for i in range(0, x):
print(facefile[i])
self.img = Image(source=facefile[i])
self.img.size_hint_x = 1
self.img.size_hint_y = 1
self.img.pos = (200,100)
self.img.opacity = 1
layout2.add_widget(self.img)
return layout2
MainApp().run()
This is what I tried, but the window doesn't update. All images are returned (demonstrated by print(facefile[i])), but nothing happens with them. Any help would be massively appreciated
Your submit() method is creating Image widgets and adding them to a newly created layout2, You are returning that new layout2 from that method, but that does not add it to your GUI. Try replacing:
layout2.add_widget(self.img)
with:
self.root.add_widget(self.img)
I'm trying to output text from button presses and add it to a textbox each time it's pressed as well as delete the text when the delete button is pressed - in normal python.
I've been trying to use kivy.uix.textinput, but I'm not sure on how to output the value from the buttons as well as delete it.
This is what I've done so far.
from kivy.app import App
from kivy.uix.screenmanager import Screen
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.textinput import TextInput
class CodeScreen(Screen):
def __init__(self):
super(CodeScreen, self).__init__(name='code_screen')
main_grid_lay = GridLayout(cols=2,cols_minimum={0:640, 1:175})
self.add_widget(main_grid_lay)
#Code ouput display
display_code = TextInput(text='Code!', readonly = True, id=output)
main_grid_lay.add_widget(display_code)
#Options Buttons
box_lay = BoxLayout(orientation='vertical')
main_grid_lay.add_widget(box_lay)
delete_button = Button(
text='Delete',
size_hint_x= None,
width=160,
id='' #unsure on how to delete
)
box_lay.add_widget(delete_button)
base_left = Button(
text='Base Left',
#on_release= b_left(),
#id='left',
)
base_right = Button(
text='Base Right',
on_release=self.degree_popup,
#on_release= b_right(),
)
#b_left = self.ids.output.text='left'
#b_left = self.ids.output.text='right'
box_lay.add_widget(base_left)
box_lay.add_widget(base_right)
# The app class
class MyMain(App):
def build(self):
return CodeScreen()
# Runs the App
if __name__ == '__main__':
MyMain().run()
It currently sends an error and is probably because of the ids. Not fully sure how ids work without using kv language. Any help is appreciated.
The id only makes sense in .kv, in python they are useless. In this case the solution is to access the objects in the methods connected to on_release but for this they must be class attributes.
from kivy.app import App
from kivy.uix.screenmanager import Screen
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.textinput import TextInput
class CodeScreen(Screen):
def __init__(self):
super(CodeScreen, self).__init__(name="code_screen")
self.display_code = TextInput(text="Code!", readonly=True)
self.delete_button = Button(
text="Delete", size_hint_x=None, width=160, on_release=self.delete_clicked
)
self.base_left = Button(text="Base Left", on_release=self.left_clicked)
self.base_right = Button(text="Base Right", on_release=self.right_clicked)
main_grid_lay = GridLayout(cols=2, cols_minimum={0: 640, 1: 175})
main_grid_lay.add_widget(self.display_code)
self.add_widget(main_grid_lay)
box_lay = BoxLayout(orientation="vertical")
box_lay.add_widget(self.delete_button)
main_grid_lay.add_widget(box_lay)
box_lay.add_widget(self.base_left)
box_lay.add_widget(self.base_right)
def delete_clicked(self, instance):
self.display_code.text = ""
def left_clicked(self, instance):
self.display_code.text += "left"
def right_clicked(self, instance):
self.display_code.text += "right"
# The app class
class MyMain(App):
def build(self):
return CodeScreen()
# Runs the App
if __name__ == "__main__":
MyMain().run()
Using Kivy 1.10.0 with Python 2.7.9 I am trying to get the TextInput value entered by user when Button (my_button2) is clicked .And although I have been able to get this working with GridLayout it seems like the method I am using is not working with ScreenManager with BoxLayout . Error received is : AttributeError: 'ScreenTwo' object has no attribute 'inpt' when my_button2
After clicking 'Next Screen ' button , it takes me to page where user enters text value , and 'print' button should print it
Please see below :
import kivy
from kivy.app import App
from kivy.uix.screenmanager import Screen, ScreenManager
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.uix.textinput import TextInput
class ScreenOne(Screen):
def __init__ (self,**kwargs):
super (ScreenOne, self).__init__(**kwargs)
my_box1 = BoxLayout(orientation='vertical')
my_button1 = Button(text="Next Screen ",size_hint_y=None,size_y=100)
my_button1.bind(on_press=self.changer)
my_box1.add_widget(my_button1)
self.add_widget(my_box1)
def changer(self,*args):
self.manager.current = 'screen2'
class ScreenTwo(Screen):
def __init__(self,**kwargs):
super (ScreenTwo,self).__init__(**kwargs)
layout = BoxLayout(orientation='vertical')
self.add_widget(layout)
inpt = TextInput(text="Some text ",size_y=50)
layout.add_widget(inpt)
my_button2 = Button(text="Print ")
my_button2.bind(on_press=self.click)
layout.add_widget(my_button2)
Home_btn = Button(text="Back")
Home_btn.bind(on_press=self.home)
layout.add_widget(Home_btn)
def click(self,my_button2):
entered_value = self.inpt.text
print entered_value
def home(self,*args):
self.manager.current = 'screen1'
class TestApp(App):
def build(self):
my_screenmanager = ScreenManager()
screen1 = ScreenOne(name='screen1')
screen2 = ScreenTwo(name='screen2')
my_screenmanager.add_widget(screen1)
my_screenmanager.add_widget(screen2)
return my_screenmanager
if __name__ == '__main__':
TestApp().run()
second screen
When you use self you are trying to access members of the class, but in your case inpt it is not since it is a variable any, if you want to be a member of the class you must put forward self, in your case change:
inpt = TextInput(text="Some text ",size_y=50)
layout.add_widget(inpt)
to:
self.inpt = TextInput(text="Some text ",size_y=50)
layout.add_widget(self.inpt)
Note: I recommend you read OOP basics, if you are not going to have many of these problems.
I have some trouble to transfert a list of element, that i get from a file (in the first screen), to the second and third screen.
I have 3 Screen managed by ScreenManager, every screen is in a different file.py and have a file.kv.
This is what my ScreenManager looks like (filename : login.py):
from interface1 import Interface1App
from interface2 import Interface2App
class LoginApp(App):
def build(self):
manager = ScreenManager()
#add view login
manager.add_widget(Login(name='login'))
# add view 'interface1'
app = Interface1App()
app.load_kv()
interfacen1 = app.build()
manager.add_widget(interfacen1)
# add view 'interface2'
app2 = Interface2App()
app2.load_kv()
interfacen2 = app2.build()
manager.add_widget(interfacen2)
# add view 'interface3'
app3 = Interface3App()
app3.load_kv()
interfacen3 = app3.build()
manager.add_widget(interfacen3)
manager.transition = SlideTransition(direction="left")
return manager
In the screen manager login i import all the screens (ex: from interface1 import Interface1App)
In the second file, i put in self.list some data, and use it for that interface (filename : interface1.py):
from interface2 import Interface2App
class AllImage(Screen):
CONTAINER_PNG = os.path.join(AllImage_ROOT, 'images')
IMAGES_NAMES = [c[:-4] for c in os.listdir(CONTAINER_PNG)]
def __init__(self, **kwargs):
Screen.__init__(self, **kwargs)
for im in IMAGES_NAMES:
if IMAGES_NAMES != None :
toggleimage = ToggleWithImage(src=im+'.png')
toggleimage.bind(on_press= lambda a, im=im:self.onpress_addpage(self.listim, im))
self.layout.add_widget(toggleimage)
def change_screen(self, x, list):
self.manager.transition = SlideTransition(direction="left")
self.manager.current = 'interface2'
self.manager.get_screen('interface2')
self.manager.list1 = [1,2,3]
def backtologin(self):
self.manager.transition = SlideTransition(direction="right")
self.manager.current = 'login'
self.manager.get_screen('login')
class Interface1App(App):
'''The kivy App that runs the main root. All we do is build a AllImage
widget into the root.'''
def build(self):
screen = AllImage()
screen.name = 'interface1'
return screen
After that i want to use again the data collected in the 2nd interface (self.list) and use it in the 3rd Interface (filename: interace2.py):
from interface1 import AllImage #this isn't working
class Combinaison(Screen):
screen = ObjectProperty(None)
def __init__(self, **kwargs):
# self._previously_parsed_text = ''
super(Combinaison, self).__init__(**kwargs)
# self.list = list(self.manager.get_screen('interface1').list)
print(self.manager.list1) # The problem is here <===========
def backtointerface1(self):
self.manager.transition = SlideTransition(direction="right")
self.manager.current = 'interface1'
self.manager.get_screen('interface1')
class Interface2App(App):
'''The kivy App that runs the main root. All we do is build a Combinaison
widget into the root.'''
def build(self):
screen = Combinaison()
screen.name = 'interface2'
return screen
With this code i have this error : print(self.manager.list1)
AttributeError: 'NoneType' object has no attribute 'list1'
I think i didn't understand how i should use the self.manager.list1=[1, 2, 3]
I hope that i was clear, sorry for the long post.
Thank you for your time :)
You can use Screen.manager.get_screen(name).list = list(self.list)
A complete example:
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.button import Button
class Screen1(Screen):
list = [1,2,3]
def __init__(self,**kwargs):
super(Screen1,self).__init__(**kwargs)
self.switch_button = Button(text="goto 2")
self.switch_button.bind(on_release=self.switch)
self.add_widget(self.switch_button)
def switch(self,*args):
self.list = [4,5,6]
self.manager.get_screen("screen2").list = list(self.list)
self.manager.current = "screen2"
class Screen2(Screen):
def __init__(self,**kwargs):
super(Screen2,self).__init__(**kwargs)
self.switch_button = Button(text="goto 1")
self.switch_button.bind(on_release=self.switch)
self.add_widget(self.switch_button)
def switch(self,*args):
self.manager.current = "screen1"
def on_enter(self):
print self.list
class MainApp(App):
def build(self):
sc1 = Screen1(name="screen1")
sc2 = Screen2(name="screen2")
self.sm = ScreenManager()
self.sm.add_widget(sc1)
self.sm.add_widget(sc2)
return self.sm
MainApp().run()
You can also use the ScreenManager to store the list or lists.
self.manager.list1 = [1,2,3] # dont call this in __init__
self.manager.list2 = [4,5,6] # call it in on_enter instead
Those lists will be available from all screens after they are added to the manager. The on_enter method on the screen would be suitable for your example.