How do I save user's input in KivyMD [duplicate] - python-3.x

I made a simple app that accepts users' input (Image file). But whenever it is closes the inputed file is losted, (of course, I did not make a way for it to be saved).
Please, I'd like the inputed image file to be available, when next the app is opened, so please how do I save the inputed image file (Perharbs you could show me a sample code, direct me somewhere or anything, I'd really appreciate). Thanks a lot in advance for your help.
Here's my code:
from kivy.lang import Builder
from kivymd.app import MDApp
from kivy.core.window import Window
from plyer import filechooser
Window.size = (300, 530)
KV = """
MDBoxLayout:
orientation: 'vertical'
MDToolbar:
id: progress_toolbar
title: 'Progress'
ScrollView:
MDGridLayout:
cols: 2
adaptive_height: True
spacing: (10, 15)
padding: [25, 25]
MDLabel:
halign: 'center'
text: 'Before'
MDLabel:
halign: 'center'
text: 'Now'
MDCard:
ripple_behavior: True
orientation: 'vertical'
size_hint_y: None
size: 120, 220
elevation: 15
radius: 8
MDIconButton:
icon: "camera-outline"
user_font_size: "24sp"
pos_hint: {"center_x": .5, "center_y": .5}
on_release: app.file_chooser1()
Image:
id: img1
allow_stretch: True
keep_ratio: False
# size_hint_y: .5
MDCard:
ripple_behavior: True
orientation: 'vertical'
size_hint_y: None
size: 120, 220
elevation: 15
radius: 8
MDIconButton:
icon: "camera-outline"
user_font_size: "24sp"
pos_hint: {"center_x": .5, "center_y": .5}
on_release: app.file_chooser2()
Image:
id: img2
allow_stretch: True
keep_ratio: False
# size_hint_y: .5
MDTextField:
hint_text: 'Date'
width: 100
MDTextField:
hint_text: 'Date'
width: 100
"""
class Example(MDApp):
def build(self):
return Builder.load_string(KV)
def file_chooser1(self):
filechooser.open_file(on_selection=self.selected1)
def file_chooser2(self):
filechooser.open_file(on_selection=self.selected2)
def selected1(self, selection1):
self.root.ids.img1.source = selection1[0]
def selected2(self, selection2):
self.root.ids.img2.source = selection2[0]
Example().run()
Again, Thanks a lot for your help, I'll appreciate any effort.

I think you should log the image files.
How ?
You can use the kivy.storage.jsonstore.JsonStore class for logging like a database.
from kivy.storage.jsonstore import JsonStore
store = JsonStore('database.json')
...
def selected1(self, selection1):
self.root.ids.img1.source = selection1[0]
files_list = store['database']['files']
files_list.append(selection1[0])
store.put('database', files=files_list)
like this. I hope i could help you. You can search the How to use JsonStore Kivy ?

Related

How do I positon inputed image file in kivymd

I made a simple App that accepts image file input, but wherever an image is inputed it appears horizontally, rather than the original vertical position (what I mean is when an image is inputed it isn't as it normal is, it's orientation changes, I hope you understand.)
Please how do I fix this, so the orientation of the inputed image will be the same as the original orientation. I'd really appreciate your help.
Here's my code:
from kivy.lang import Builder
from kivymd.app import MDApp
from kivy.core.window import Window
from plyer import filechooser
Window.size = (300, 530)
KV = """
MDBoxLayout:
orientation: 'vertical'
MDToolbar:
id: progress_toolbar
title: 'Progress'
ScrollView:
MDGridLayout:
cols: 2
adaptive_height: True
spacing: (10, 15)
padding: [25, 25]
MDLabel:
halign: 'center'
text: 'Before'
MDLabel:
halign: 'center'
text: 'Now'
MDCard:
ripple_behavior: True
orientation: 'vertical'
size_hint_y: None
size: 120, 220
elevation: 15
radius: 8
MDIconButton:
icon: "camera-outline"
user_font_size: "24sp"
pos_hint: {"center_x": .5, "center_y": .5}
on_release: app.file_chooser1()
Image:
id: img1
allow_stretch: True
keep_ratio: False
# size_hint_y: .5
MDCard:
ripple_behavior: True
orientation: 'vertical'
size_hint_y: None
size: 120, 220
elevation: 15
radius: 8
MDIconButton:
icon: "camera-outline"
user_font_size: "24sp"
pos_hint: {"center_x": .5, "center_y": .5}
on_release: app.file_chooser2()
Image:
id: img2
allow_stretch: True
keep_ratio: False
# size_hint_y: .5
MDTextField:
hint_text: 'Date'
width: 100
MDTextField:
hint_text: 'Date'
width: 100
"""
class Example(MDApp):
def build(self):
return Builder.load_string(KV)
def file_chooser1(self):
filechooser.open_file(on_selection=self.selected1)
def file_chooser2(self):
filechooser.open_file(on_selection=self.selected2)
def selected1(self, selection1):
self.root.ids.img1.source = selection1[0]
def selected2(self, selection2):
self.root.ids.img2.source = selection2[0]
Example().run()
Thanks a lot for your effort.
I think you should change this:
from
MDCard:
orientation: 'vertical'
to
MDCard:
orientation: 'horizontal'
please share a screenshot for more help

I don't understand how to keep the same relative size of all the elements when resizing the window

When the application is windowed the button and labels are in the right places, exactly where I want them, but when I view the window in full screen everything moves out of place
I've tried messing around with the padding and height of the box layouts and label properties, but I just getting the broken outcome.
*.py
import kivy
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.image import Image
class LoginReg(BoxLayout):
pass
class LoginApp(App):
def build(self):
return LoginReg()
if __name__== '__main__':
LoginApp().run()
*.kv
#:kivy 1.0
#:import hex kivy.utils.get_color_from_hex
<TextInput>:
size_hint_y: None
height:30
<Label>:
size_hint_y: None
height:30
color: 0,0,0,1
<FlatButton#ButtonBehavior+Label>:
font_size: 18
<LoginReg>:
id: main_win
orientation: "vertical"
spacing: 10
space_x: self.size[0]/3
space_y: 40
#Code for background start
BoxLayout:
id: background
orientation: 'vertical'
canvas.before:
Color:
rgba: hex('#f2f2f2f2')
Rectangle:
size: self.size
pos: self.pos
BoxLayout:
id: header
size_hint_y:None
height: 50
canvas.before:
Color:
rgba: hex('#1A5276')
Rectangle:
size: self.size
pos: self.pos
FlatButton:
text:"Virtual Assistant"
color: (1,1,1,1)
BoxLayout:
orientation: 'vertical'
padding: main_win.space_x, main_win.space_y
BoxLayout:
spacing: 10
orientation: 'vertical'
padding: 50
canvas.before:
Color:
rgba: hex('#111')
Rectangle:
size: self.size
pos: self.pos
Label:
text: "Login: "
TextInput:
hint_text: "Username"
multiline: False
Label:
text: "Password: "
TextInput:
hint_text: "password"
multiline: False
Button:
text:"Login"
size_hint_y: None
height: 60
background_color: (2.08, 2.40, 1.92,1)
Label:
id:sp
size_hint_y:None
height: 200
I am not getting any error messages, I just want to work out how to keep everything relative it its size when resizing the window.
The best way to get everything to keep relative size/position is to use hints. Use size_hint for sizes and pos_hint for positions. Also, don't add unnecessary complexity to your layout. In your posted code, your LoginReg is a BoxLayout, and the only item you have in it is another BoxLayout. Similarly, later in your kv you have another vertical BoxLayout with its only child being another vertical BoxLayout. That is unnecessary complexity. Here is a simpler version of your code that I believe accomplished what you want:
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.floatlayout import FloatLayout
class LoginReg(FloatLayout):
pass
Builder.load_string('''
#:kivy 1.0
#:import hex kivy.utils.get_color_from_hex
<TextInput>:
size_hint_y: None
height:30
<Label>:
size_hint_y: None
height:30
color: 0,0,0,1
<FlatButton#ButtonBehavior+Label>:
font_size: 18
<LoginReg>:
spacing: 10
#Code for background start
canvas.before:
Color:
rgba: hex('#f2f2f2f2')
Rectangle:
size: self.size
pos: self.pos
FlatButton:
id: fb
canvas.before:
Color:
rgba: hex('#1A5276')
Rectangle:
size: self.size
pos: self.pos
pos_hint: {'center_x': 0.5, 'top':1.0}
size_hint_y:None
height: 50
text:"Virtual Assistant"
color: (1,1,1,1)
BoxLayout:
spacing: 10
orientation: 'vertical'
padding: 50
canvas.before:
Color:
rgba: hex('#111')
Rectangle:
size: self.size
pos: self.pos
pos_hint: {'center_x': 0.5, 'top': (root.height - fb.height)/root.height}
size_hint: 0.33, None
size_hint_min_x: 200
height: self.minimum_height
Label:
text: "Login: "
TextInput:
id: ti
hint_text: "Username"
multiline: False
Label:
text: "Password: "
TextInput:
hint_text: "password"
multiline: False
Button:
text:"Login"
size_hint_y: None
height: 60
background_color: (2.08, 2.40, 1.92,1)
''')
class LoginApp(App):
def build(self):
return LoginReg()
if __name__== '__main__':
LoginApp().run()
I have used Builder.load_string instead of a file just for my own convenience.
The important changes are to make LoginReg extend FloatLayout just because it allows more flexibility than a BoxLayout. I have removed any BoxLayouts that only had a single BoxLayout child.
The FlatButton now uses pos_hint to position it at the top of LoginReg.
The BoxLayout inside Loginreg uses pos_hint to center it horizontally, and to position it vertically just below the FlatButton. It also uses size_hint to make its width one third of the width of LoginReg, but with a minimum width of 200. Its height is set to use the minimum height that will contain its children.

Kivy make a grid layout inside a label or button

Is it possible to have a grid like layout inside a Label or a Button in kivy.
I have an app that takes in a CSV file with product information and I would like to populate MainScreen with rows from a CSV file.
Each row should look like this:
In the end the Label or Button should be pressable to open a pop up window for confirmation screen for quantity of the product and verify.
Is it even possible or am I approaching it from the wrong angle?
I do not have any code yet to populate the MainScreen with rows but this is how it looks so far.
To clarify. At this moment I don't need help with importing CSV files, but with the method to display it, that matches the above criteria(picture)
Code so far is as follows:
ATmain.py
from kivy.app import App
from kivy.uix.screenmanager import Screen, ScreenManager
from kivy.core.window import Window
from kivy.lang import Builder
from kivy.properties import StringProperty
Window.clearcolor = (1,1,1,1)
Window.size = (270, 480)
class LoginScreen(Screen):
input = StringProperty("")
class MainScreen(Screen):
username = StringProperty('')
class ScreenManagement(ScreenManager):
pass
presentation = Builder.load_file("app.kv")
class ATApp(App):
presentation = Builder.load_file("app.kv")
def build(self):
return presentation
if __name__ == '__main__':
ATApp().run()
app.kv:
# File name: main.py
#:import FadeTransition kivy.uix.screenmanager.FadeTransition
#:kivy 1.10.1
ScreenManagement:
transition: FadeTransition()
LoginScreen:
id: login
MainScreen:
username: login.input
<LoginScreen>:
name: "login"
canvas:
Color:
rgba: [1,1,1]
Rectangle:
pos: self.pos
size: self.size
FloatLayout:
rows:2
cols:1
background_color: 1,1,1,1
Label:
size_hint: 0.3, 0.05
pos_hint: {"x": 0.5 - 0.3/2, "center_y": 0.4}
text:"Kasutaja"
color: 0,0,0,1
TextInput:
id: input
size_hint: (0.3, None)
height: 30
pos_hint: {"x": 0.5 - 0.3/2, "center_y": 0.3}
multiline: False
Button:
id: confirm_login
text: "Login"
size_hint: 0.15, 0.07
pos_hint: {"x": 0.5 - 0.15/2, "center_y": 0.2}
background_color: 0.9,0.9,0.9,1
on_press: self.background_color = (1,0,0,1)
on_release: root.input = input.text; app.root.current = "main"
<MainScreen>:
name: "main"
canvas:
Rectangle:
pos: self.pos
size: self.size
Label:
id:name
text: root.username
color: (0,0,0,1)
size_hint_y: None
height: 30
size_hint_x: 1
pos_hint: {"right": 1, "top": 1}
BoxLayout:
orientation: "vertical"
size_hint_y: None
size_hint_x: 1
pos_hint_x: None
pos_hint_y: 1
Button:
text: "Item1"
color: (0,0,0,1)
height: self.height
size_hint_y: None
size_hint_x: 1
pos_hint: {"right": 1, "top": 0}
I would be very greatful if anyone could as much as point me in the right direction!
The kivy hack way will be to simply use a GridLayout or any layout for that matter then give your layout button properties so it is clickable like so :
from kivy.behaviors import ButtonBehavior
#then make a clickable grid
class GridButton(GridLayout, ButtonBehaviour):
def __init__(self, **kwargs):
super().__init__(**kwargs)
#Then do whatever you want to do
Another way to do it I guess would be to use the on_touch_down callback and check if the touch is within the widget's bounds

Access data from Kivy Popoup Input

I was trying to look at different examples online to solve this issue but Still cannot figure out. I have an app that calls a popup class. The popup has an input field that does some manipulation to the text in the input field. The manipulated data is stored in a variable inside of the popup class. Now how can the parent widget access the data obtained from this widget. Here is a short example of the code.
KV
<ScreenManagement>:
ScreenManager:
id: manager
size_hint_y: 93
Screen:
name: "Case_info_screen"
id: sc1
FloatLayout:
BoxLayout:
orientation: 'vertical'
BoxLayout:
size_hint_y: 10
canvas.before:
Color:
rgb: 0.17, 0.17, 0.17 # your color here
Rectangle:
pos: self.pos
size: self.size
Label:
text_size: self.size
font_size: 20
valign: 'middle'
height: "75dp"
size_hint_y: None
color: 1,1,1,1
size_hint_x: 75
text: " Case Info"
RelativeLayout:
size_hint_x: 25
Button:
text_size: self.size
halign: 'center'
valign: 'middle'
size_hint: 0.70, 0.6
pos_hint: {'center_x': 0.5, 'center_y': 0.5}
text: 'Automatic Filler'
on_press: root.formfiller()
BoxLayout:
size_hint_y: 5
spacing: 35
LabelCases:
text: ' Name: '
width: '125dp'
size_hint_x: None
TextInput:
id: first_name_input
width: '300dp'
height: '40dp'
size_hint_x: None
font_size: 18
hint_text: 'First Name'
TextInput:
id: last_name_input
width: '300dp'
height: '40dp'
size_hint_x: None
font_size: 18
hint_text: 'Last Name'
<Formfillerpop>:
title: 'Automatic Filler'
size_hint: None, None
size: 600, 600
BoxLayout:
orientation: 'vertical'
Label:
size_hint_y: 20
text: 'Please Paste your text'
markup: True
TextInput:
id: sentence
size_hint_y: 65
BoxLayout:
size_hint_y: 10
orientation: 'horizontal'
Button:
text: 'Analyze'
on_press: root.on_analyze(sentence.text)
Button:
text: 'Close'
on_press: root.closepop()
Python:
class Formfillerpop(Popup):
selection = StringProperty
id = ObjectProperty
def on_analyze(self, selection):
analyze = TextExtractor(selection)
names = analyze.name()
def closepop(self):
self.dismiss()
class ScreenManagement(FloatLayout):
def formfiller(self, *args):
Formfillerpop().open()
class IOApp(App):
def build(self):
return ScreenManagement()
if __name__ == '__main__':
IOApp().run()
Ultimately I want to take the txt from names in the popup and then autopopulate the first name and last name in the main app with the analyzed data
Sorry if this is basic. I am fairly new to Kivy.
You can access popup content using its content property. You can use it to read text property of read underlying TextInput. For example this code binds this property to local popup_text StringProperty, which means that any change in the popup text input will be reflected there:
from kivy.uix.popup import Popup
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
from kivy.app import App
from kivy.lang import Builder
from kivy.properties import StringProperty
Builder.load_string('''
<CustomPopup>:
size_hint: .5, .5
auto_dismiss: False
title: 'Hello world'
BoxLayout:
text_input: text_input
orientation: 'vertical'
TextInput:
id: text_input
Button:
text: 'dismiss'
on_press: root.dismiss()
''')
class CustomPopup(Popup):
pass
class TestApp(App):
popup_text = StringProperty()
def build(self):
l = BoxLayout()
l.add_widget(Button(
text='show_popup', on_press=self.show_popup
))
l.add_widget(Button(
text='print popup text', on_press=self.print_popup_text
))
return l
def show_popup(self, *args):
p = CustomPopup()
p.content.text_input.bind(text=self.setter('popup_text'))
p.open()
def print_popup_text(self, *args):
print(self.popup_text)
if __name__ == '__main__':
TestApp().run()

why is text in Kivy spinner vague / blurry

I have a spinner used to select items as dropdown. The text in the textfield itself is normal. But the text in the spinner items looks blurry/vague, see the attached image. How could I resolve this?
The source file qmonos.py:
from kivy.app import App
from kivy.core.window import Window
from kivy.uix.boxlayout import BoxLayout
class qmonosHome(BoxLayout):
def init_qmonos(self):
self.objtype.text = ''
self.objtype.values = ('Home', 'Work', 'Other', 'Custom')
class qmonosApp(App):
def build(self):
Window.clearcolor = (.95,.95,.95,1)
Window.size = (800, 200)
homeWin = qmonosHome()
homeWin.init_qmonos()
return homeWin
qmonosApp().run()
The kivy file qmonos.kv
# File: qmonos.kv
#:import Factory kivy.factory.Factory
#:set color_button (.5,1,1,1)
#:set color_button_pressed (0.7,0.9,1,1)
#:set color_font (1,1,1,1)
<MySpinnerOption#SpinnerOption>:
background_color: color_button if self.state == 'down' else color_button_pressed
color: color_font
font_size: 12
text_size: self.width - 10, self.height
height: 25
<qmonosHome>:
objtype:objtype
BoxLayout:
orientation: "horizontal"
padding: 10,10,10,10
BoxLayout
orientation: "vertical"
size_hint: 0.5,1
BoxLayout:
orientation: "horizontal"
height: "20dp"
size_hint_y: None
Label:
text: "Hello World"
size_hint: 1,1
size: self.texture_size
halign: 'left'
valign: 'middle'
font_size: 12
color: .3,.3,.3,1
BoxLayout
orientation: "vertical"
size_hint: 0.5,1
padding: 10,0,10,0
BoxLayout:
orientation: "horizontal"
height: "20dp"
size_hint_y: None
Label:
text: "Type Object:"
size_hint: 0.25,1
size: self.texture_size
halign: 'left'
valign: 'middle'
font_size: 12
color: .3,.3,.3,1
Spinner:
id: objtype
text: ''
background_color: color_button if self.state == 'normal' else color_button_pressed
color: color_font
option_cls: Factory.get("MySpinnerOption")
font_size: 12
text_size: self.width - 10, self.height
size_hint: 0.25,1
multiline: False
foreground_color: .3,.3,.3,1
disabled_foreground_color: .3,.3,.3,1
Label:
text: "Hello too"
size_hint: 0.5,1
size: self.texture_size
halign: 'left'
valign: 'middle'
font_size: 12
color: .3,.3,.3,1
This is a known issue in Kivy, that apparently hasn't been fixed yet. Refer to those links for more info on this case: GitHub, Google Groups, Bountysource. They tell that the issue is that the text is not drawn on the whole pixel, but rather on a part of it.
An unexpected solution in your case: mess around with the padding. Is it important for the padding to be exactly 10? Because I've found out that (12, 12, 12, 12) works perfectly and the text is sharp. That's kinda strange, but I hope it works for you. That's as far as I can help you with this problem.
You could address this issue to Kivy devs, but considering it was discovered in 2014, I'm surprised it wasn't fixed.

Resources