why is text in Kivy spinner vague / blurry - spinner

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.

Related

Where should methods be placed; ids vs NumericProperty; kivy

I have a very basic kivy code. I have the .py file and the .kv file. The questions are: where should the methods be placed? In this example the 2 methods that interact are 'def GetTicker(ticker):' and 'def GetTickers(self):'. I have placed both outside of any class, because I could not get the code to work otherwise; however I think the proper way to code would be to place them inside the 'app' class.
As an aside I am very confused about where/when the 'self' should be passed. I'm working by trial and error here.
Then there is the 'NumericProperty'. I read here that when it is updated, it automatically updates the widgets that are associated with it. It doesn't for me, therefore I had to create Id's for some labels; but the id's won't work at the beginning of the run, only on update.
I'm using python 3.9 and kivy 2.0.0, PyCharm 2021.3.1 (Community Edition) on win10 box.
Any and all assistance will be greatly appreciated.
Ray
the .py file
from kivy.app import App
from kivy.properties import NumericProperty
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.textinput import TextInput
from kivy.core.window import Window
Window.size = (300, 300)
import time
from yahoo_fin.stock_info import get_live_price # This API only gets the live price
from yahoo_fin import stock_info as si # This is SLOWER than the above API, buts gets more info
class MyBoxLayout(BoxLayout):
def __init__(self, **kwargs):
super().__init__(**kwargs)
def press(self):
name = self.ids.ticker_name.text.upper()
self.ids.ticker_value.text = self.GetTicker(name)
def update(self):
#GetTickers(self) # This won't work here :(
self.ids.mydow_price.text, self.ids.mydow_chg = self.GetTicker("^DJI")
self.ids.mysp_price.text, self.ids.mysp_chg = self.GetTicker("^GSPC")
self.ids.mynasdaq_price.text, self.ids.mynasdaq_chg.text = self.GetTicker("^IXIC")
self.ids.myeuro_price, self.ids.myeuro_chg.text = self.GetTicker("EURUSD=X")
#print(self.ids.amazon_id.text)
class MyOtherBoxlayout(BoxLayout):
pass
class MyTicker(TextInput):
pass
class gridlayout(GridLayout):
pass
def GetTicker(ticker):
# data = get_live_price(ticker)
data = si.get_quote_table(ticker)
price = data['Quote Price']
change = price - data['Previous Close']
# print("Price: %.3f" % price)
# print("Change: %.3f" % change)
return [str("%s" % format(price, ',.3f')), str("%s" % format(change, ',.3f'))]
def GetTickers(self):
self.dow_price, self.dow_chg = self.GetTicker("^DJI")
self.sp_price, self.sp_chg = self.GetTicker("^GSPC")
self.nasdaq_price, self.nasdaq_chg = self.GetTicker("^IXIC")
self.euro_price, self.euro_chg = self.GetTicker("EURUSD=X")
# This is the app class
class StockTickerApp(App):
def __init__(self, **kwargs):
super().__init__(**kwargs)
App.title = "Ray's Stock Ticker"
dow_price = NumericProperty(0.00)
dow_chg = NumericProperty(0.00)
sp_price = NumericProperty(0.00)
sp_chg = NumericProperty(0.00)
nasdaq_price = NumericProperty(0.00)
nasdaq_chg = NumericProperty(0.00)
euro_price = NumericProperty(0.00)
euro_chg = NumericProperty(0.00)
start_time = time.time()
self.GetTickers()
end_time = time.time()
print (end_time - start_time)
# and its run here
StockTickerApp().run()
the .kv file
MyBoxLayout:
<MYLabel#ButtonBehavior+Label>: # this is something I found that helps make a label behave
# like a button.
<MyBoxLayout>:
canvas.before:
Color:
rgba: (153/255, 255/255, 255/255, 1)
Rectangle:
pos: self.pos
size: self.size
padding: ("15dp", "15dp", "15dp", "15dp") #left, top, right, bottom
spacing: "10dp"
orientation: "vertical"
#
# 1st widget
#
Label:
text: "Stocks Ticker"
size_hint: 1, .1
#pos_hint: {"top": 1}
color:0,0,0,1
#
# 2nd widget
#
BoxLayout:
canvas.before:
Color:
rgba: (19/255,202/255,55/255,1) # lime more intense
Rectangle:
pos: self.pos
size: self.size
padding: ("10dp", "0dp", "15dp", "0dp")
spacing: "20dp"
orientation: "horizontal"
size_hint: 1, .4
#pos_hint: {"center": .5}
Label:
text: " Enter Stock"
size_hint: .6, .5
pos_hint: {"center_X":.5, "top": .7}
color: 72/255,89/255,89/255,1
MyTicker: # this is a textinput widget
id: ticker_name
text: ""
size_hint: .6, .6
pos_hint: {"top": .8}
Label:
id: ticker_value
#text: " Enter Stock"
size_hint: .5, .1
color: 0,0,0,1
pos_hint: {"top":.5, "center": 1}
#
# 3rd widget
#
BoxLayout:
size_hint: 1, .3
Button:
#id: "Find_Value"
text: "Find Value"
on_press: root.press()
#
# 4th widget
#
gridlayout:
canvas.before:
Color:
rgba: (19/255,202/255,55/255,1) # lime more intense
Rectangle:
pos: self.pos
size: self.size
rows: 4
cols: 3
padding: "10dp"
MYLabel:
color: 72/255,89/255,89/255,1
text: "Dow"
text_size: self.size
halign: 'left'
on_press: root.update()
MYLabel:
id: mydow_price
color: 0,0,0,1
text: app.dow_price
text_size: self.size
halign: 'right'
on_press: root.update()
MYLabel:
id: mydow_chg
color: 0,0,0,1
text: app.dow_chg
text_size: self.size
halign: 'right'
on_press: root.update()
MYLabel:
text: "S&P 500"
color: 72/255,89/255,89/255,1
text_size: self.size
halign: 'left'
on_press: root.update()
MYLabel:
id: mysp_price
text: app.sp_price
color: 0,0,0,1
text_size: self.size
halign: 'right'
MYLabel:
id: mysp_chg
text: app.sp_chg
color: 0,0,0,1
text_size: self.size
halign: 'right'
MYLabel:
text: "Nasdaq"
color: 72/255,89/255,89/255,1
text_size: self.size
halign: 'left'
on_press: root.update()
MYLabel:
id: mynasdaq_price
text: app.nasdaq_price
color: 0,0,0,1
text_size: self.size
halign: 'right'
MYLabel:
id: mynasdaq_chg
text: app.nasdaq_chg
color: 0,0,0,1
text_size: self.size
halign: 'right'
MYLabel:
text: "Euro/USD"
color: 72/255,89/255,89/255,1
text_size: self.size
halign: 'left'
on_press: root.GetTickers()
MYLabel:
id: myeuro_price
text: app.euro_price
color: 0,0,0,1
text_size: self.size
halign: 'right'
MYLabel:
id: myeuro_chg
text: app.euro_chg
color: 0,0,0,1
text_size: self.size
halign: 'right'

How do I save user's input in KivyMD [duplicate]

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 ?

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.

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()

Resources