How to add multiple widget at the same time to a scrollview? - python-3.x

I'm new at kivy, so I'm working on a test app. I want to create a screen with ScrollView and I want to add multiple things to a 'line' in the ScrollView, a text (description) and an image.
I have tried this way:
class PresentUploadedData(Screen):
container = ObjectProperty(None)
def __init__(self, **kwargs):
super(PresentUploadedData, self).__init__(**kwargs)
Clock.schedule_once(self.setup_scrollview, 1)
def setup_scrollview(self, dt):
self.container.bind(minimum_height=self.container.setter('height'))
self.add_text_inputs()
def add_text_inputs(self):
for x in range(30):
self.container.add_widget(Label(text="Label {}".format(x), size_hint_y=None, height=40, color= [128,0,0,1]))
self.container.add_widget(Image(source='test.jpg', size_hint=(None, None,), width=50, height=50))
with this .kv file:
<PresentUploadedData>:
name: "presentupload"
message: send
container: container
canvas:
Color:
rgba: 1,1,1,1
Rectangle:
size: self.size
pos: self.pos
GridLayout:
rows: 3
cols: 1
spacing: 5
padding: 5
font_name: "Calibri"
background_color: 1,1,1, 1
ScrollView:
background_color: 1,1,1, 1
size_hint: (1, .9)
bar_width: 10
bar_color: 128,0,0,0.7
bar_inactive_color: 128,0,0,1
effect_cls: "ScrollEffect"
scroll_type: ['bars', 'content']
color: 128,0,0,1
StackLayout:
id: container
size_hint_y: None
color: 128,0,0,1
GridLayout:
cols: 2
BoxLayout:
spacing: 5
size_hint: .7, .1
Button:
text: "< BACK"
id: send
color: 0, 0, 0, 1
background_color: .88,.88,.88, 1
size_hint: .2, 1
on_release:
app.root.current = "main"
root.manager.transition.direction = "right"
But I've got ScrollView accept only one widget Exception.
Why I got this, and how can I resolve this?

There is an error in .kvfile:
GridLayout:
cols: 2
This is useless.
The problem can be solved with one more for inside the for loop:
row = [Label(text="Label {}".format(x), size_hint_y=None, height=50, color= [128,0,0,1]), Image(source='test.jpg', size_hint=(None, None,), width=50, height=50)]
for r in row:
self.container.add_widget(r)
But this also didn't put the things near each other, just let them be there.

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'

Customise Kivy settings panel by redefining style.kv

I am using the default Kivy Settings widget to create a settings screen for my app. I don't want to build a custom settings widget from scratch, but I would like to customise simple properties like the text size of each item and the colour of the "close" button.
Based on the Kivy docs and the answer to this question I understand that I need to modify the styles for the different Settings class widgets that are defined in style.kv. For example, I have been able to add the following to the top of my main.py to redefine the style of the MenuSidebar widget and change the size and colour of the settings "close" button:
from kivy.lang import Builder
Builder.load_string('''
<-MenuSidebar>:
size_hint_x: None
width: '200dp'
buttons_layout: menu
close_button: button
GridLayout:
pos: root.pos
cols: 1
id: menu
padding: 5
canvas.after:
Color:
rgb: .2, .2, .2
Rectangle:
pos: self.right - 1, self.y
size: 1, self.height
Button:
text: 'Close'
id: button
size_hint: None, None
width: root.width - dp(20)
height: max(50, self.texture_size[1] + dp(20))
pos: root.x + dp(10), root.y + dp(10)
font_size: '30sp'
Following a similar approach, I now want to modify the style of each setting item so that the text colour is red. I add the following into Builder.load_string() at the top of my main.py to redefine the style of the SettingItem widget:
<-SettingItem>:
size_hint: .25, None
height: labellayout.texture_size[1] + dp(10)
content: content
canvas:
Color:
rgba: 47 / 255., 167 / 255., 212 / 255., self.selected_alpha
Rectangle:
pos: self.x, self.y + 1
size: self.size
Color:
rgb: .2, .2, .2
Rectangle:
pos: self.x, self.y - 2
size: self.width, 1
BoxLayout:
pos: root.pos
Label:
size_hint_x: .66
id: labellayout
markup: True
text: u'{0}\\n[size=13sp][color=999999]{1}[/color][/size]'.format(root.title or '', root.desc or '')
font_size: '15sp'
color: [1, 0 , 0 , 1]
text_size: self.width - 32, None
BoxLayout:
id: content
size_hint_x: .33
Everything works as expected, however the value of each setting item disappears.
I have tried everything I can think off, but I can't work out how to modify the appearance of the settings screen without losing the actual value of each setting item, or messing up the whole layout of the settings screen. Can anyone advise how I can achieve my goal?
Here is a minimal reproducible example illustrating the issue that is based on the Kivy Settings example
from kivy.app import App
from kivy.uix.settings import SettingsWithSidebar
from kivy.logger import Logger
from kivy.lang import Builder
kv = '''
BoxLayout:
orientation: 'vertical'
Button:
text: 'Configure app (or press F1)'
on_release: app.open_settings()
Label:
id: label
text: 'Hello'
<-MenuSidebar>:
size_hint_x: None
width: '200dp'
buttons_layout: menu
close_button: button
GridLayout:
pos: root.pos
cols: 1
id: menu
padding: 5
canvas.after:
Color:
rgb: .2, .2, .2
Rectangle:
pos: self.right - 1, self.y
size: 1, self.height
Button:
text: 'Close'
id: button
size_hint: None, None
width: root.width - dp(20)
height: max(50, self.texture_size[1] + dp(20))
pos: root.x + dp(10), root.y + dp(10)
font_size: '30sp'
color: [1, 0 , 0, 1]
<-SettingItem>:
size_hint: .25, None
height: labellayout.texture_size[1] + dp(10)
content: content
canvas:
Color:
rgba: 47 / 255., 167 / 255., 212 / 255., self.selected_alpha
Rectangle:
pos: self.x, self.y + 1
size: self.size
Color:
rgb: .2, .2, .2
Rectangle:
pos: self.x, self.y - 2
size: self.width, 1
BoxLayout:
pos: root.pos
Label:
size_hint_x: .66
id: labellayout
markup: True
text: u'{0}\\n[size=13sp][color=999999]{1}[/color][/size]'.format(root.title or '', root.desc or '')
font_size: '15sp'
color: [1, 0 , 0 , 1]
text_size: self.width - 32, None
BoxLayout:
id: content
size_hint_x: .33
'''
json = '''
[
{
"type": "string",
"title": "Label caption",
"desc": "Choose the text that appears in the label",
"section": "My Label",
"key": "text"
},
{
"type": "numeric",
"title": "Label font size",
"desc": "Choose the font size the label",
"section": "My Label",
"key": "font_size"
}
]
'''
class MyApp(App):
def build(self):
self.settings_cls = SettingsWithSidebar
root = Builder.load_string(kv)
label = root.ids.label
label.text = self.config.get('My Label', 'text')
label.font_size = float(self.config.get('My Label', 'font_size'))
return root
def build_config(self, config):
config.setdefaults('My Label', {'text': 'Hello', 'font_size': 20})
def build_settings(self, settings):
settings.add_json_panel('My Label', self.config, data=json)
def on_config_change(self, config, section, key, value):
Logger.info("main.py: App.on_config_change: {0}, {1}, {2}, {3}".format(
config, section, key, value))
if section == "My Label":
if key == "text":
self.root.ids.label.text = value
elif key == 'font_size':
self.root.ids.label.font_size = float(value)
def close_settings(self, settings=None):
Logger.info("main.py: App.close_settings: {0}".format(settings))
super(MyApp, self).close_settings(settings)
MyApp().run()
Add this to your kv string:
<SettingString>:
Label:
text: root.value or ''
pos: root.pos
font_size: '15sp'
color: 1,0,0,1
Color obviously can be whatever you want.
this only works for the settings string, if you use other settings objects modify them in a similar way :)

Kivy - How to Size Embedded Anchor Layouts?

I would like to build the following simple design in a .kv file.
It is made of 3 parts :
One top-left Anchor Layout which is made up of a Grid Layout of 3 columns. I want its width to be equal to 20% of the window's with and its height to be equal to 75% of the window's height.
One top-right Anchor Layout which is made up of a vertically-oriented Box Layout. I want its width to be equal to 80% of the window's with and its height to be equal to 75% of the window's height.
One bottom-left Anchor Layout which is empty for the moment. I want its height to be 25% of the window's height.
These three parts are themselves included in an AnchorLayout.
I tried to translate this design into a .kv file as follows.
#:kivy 1.11.1
<Example>:
anchor_x: "center"
anchor_y: "center"
AnchorLayout:
anchor_x: "left"
anchor_y: "top"
size_hint: (0.2, 0.75)
GridLayout:
cols: 3
Button:
text: "X"
Button:
text: "X"
Button:
text: "X"
Button:
text: "X"
Button:
text: "X"
Button:
text: "X"
AnchorLayout:
anchor_x: "right"
anchor_y: "top"
size_hint: (0.8, 0.75)
BoxLayout:
orientation: "vertical"
Label:
text: "HELLO..."
Label:
text: "WORLD..."
AnchorLayout:
anchor_x: "left"
anchor_y: "bottom"
size_hint: (1, 0.25)
Label:
text: "FOOTER"
In case it matters, here is the code of my .py file as well.
# Importing Kivy
import kivy
kivy.require("1.11.1")
# Importing kivy libraries
from kivy.app import App
from kivy.uix.anchorlayout import AnchorLayout
from kivy.lang import Builder
# Importing external libraries
# Import kv files
Builder.load_file("example.kv")
# Root widget of the application
class Example(AnchorLayout):
pass
# Application class
class TestApp(App):
def build(self, **kwargs):
return Example()
# Launch the application
if __name__=="__main__":
app = TestApp()
app.run()
The output does not look as I expected as shown on the picture below :
I don't get it. Because the AnchorLayout is a subclass of the Widget class and is itself included within a Layout, its size_hint property should enable me to define its size.
What am I missing here ? Thanks in advance!
Problem - design centered
The design is placed in the center.
Root Cause
The root is an AnchorLayout with value 'center' for both anchor_x and anchor_y. Therefore, all its children (the AnchorLayouts) are placed in respect to the root.
Below is a view of your design in different colours for visualization.
AnchorLayout
The AnchorLayout aligns its children to a border (top, bottom, left, right) or center.
Solution
There are three possible solutions to your design. The preference is method 1.
Method 1 - No AnchorLayouts
This method replace all AnchorLayouts with BoxLayouts. It use one less AnchorLayout widget which makes the app more resource efficient i.e. use less memory and the app is smaller.
Snippets - Method 1
<Example>:
orientation: 'vertical'
BoxLayout:
...
GridLayout: # left box
...
BoxLayout: # right box
...
BoxLayout: # footer
...
Method 2 - BoxLayout as root
This method replace the root widget with BoxLayout and realign the left box.
Snippets - Method 2
<Example>:
orientation: 'vertical'
AnchorLayout:
...
GridLayout: # left box
...
AnchorLayout: # right box
...
AnchorLayout: # footer
...
Method 3
This method add a BoxLayout as a child of the root, and the rest of the AnchorLayout as children of the BoxLayout.
Snippets - Method 3
<Example>:
anchor_x: "center"
anchor_y: "center"
BoxLayout:
orientation: 'vertical'
AnchorLayout:
...
GridLayout: # left box
...
AnchorLayout: # right box
...
AnchorLayout: # footer
...
Example
Method 1 - No AnchorLayouts
main.py
from kivy.base import runTouchApp
from kivy.lang import Builder
runTouchApp(Builder.load_string("""
BoxLayout:
orientation: 'vertical'
BoxLayout:
size_hint: 1, 0.75
GridLayout:
size_hint: 0.2, 1
canvas.before:
Color:
rgba: 1, 0, 0, 1
Rectangle:
size: self.size
pos: self.pos
cols: 3
row_force_default: True
row_default_height: 40
Button:
text: "X"
Button:
text: "X"
Button:
text: "X"
Button:
text: "X"
Button:
text: "X"
Button:
text: "X"
BoxLayout:
orientation: 'vertical'
canvas.before:
Color:
rgba: 0, 1, 0, 1
Rectangle:
size: self.size
pos: self.pos
Label:
text: "HELLO..."
Label:
text: "WORLD..."
BoxLayout:
size_hint: 1, 0.25
canvas.before:
Color:
rgba: 0, 0, 1, 1
Rectangle:
size: self.size
pos: self.pos
Label:
text: "FOOTER"
"""))
Output: Method 1 - No AnchorLayouts
Method 2 - BoxLayout as root
main.py
from kivy.base import runTouchApp
from kivy.lang import Builder
runTouchApp(Builder.load_string("""
BoxLayout:
orientation: 'vertical'
AnchorLayout:
size_hint: 1, 0.75
anchor_x: 'left'
anchor_y: 'top'
GridLayout:
size_hint: 0.2, 1
canvas.before:
Color:
rgba: 1, 0, 0, 1
Rectangle:
size: self.size
pos: self.pos
cols: 3
row_force_default: True
row_default_height: 40
Button:
text: "X"
Button:
text: "X"
Button:
text: "X"
Button:
text: "X"
Button:
text: "X"
Button:
text: "X"
AnchorLayout:
anchor_x: 'right'
anchor_y: 'top'
BoxLayout:
orientation: 'vertical'
size_hint: 0.8, 1
canvas.before:
Color:
rgba: 0, 1, 0, 1
Rectangle:
size: self.size
pos: self.pos
Label:
text: "HELLO..."
Label:
text: "WORLD..."
AnchorLayout:
size_hint: 1, 0.25
anchor_x: 'left'
anchor_y: 'bottom'
canvas.before:
Color:
rgba: 0, 0, 1, 1
Rectangle:
size: self.size
pos: self.pos
Label:
text: "FOOTER"
"""))
Output: Method 2 - BoxLayout as root
Changing the Example class to extend FloatLayout instead of AnchorLayout allows more control of its children. With that change to Example, here is a kv that looks more like what you want:
<Example>:
AnchorLayout:
anchor_x: "center"
anchor_y: "top"
size_hint: (0.2, 0.75)
pos_hint: {'x':0, 'top':1}
GridLayout:
cols: 3
Button:
text: "X"
Button:
text: "X"
Button:
text: "X"
Button:
text: "X"
Button:
text: "X"
Button:
text: "X"
AnchorLayout:
anchor_x: "center"
anchor_y: "top"
size_hint: (0.8, 0.75)
pos_hint: {'right':1, 'top':1}
BoxLayout:
orientation: "vertical"
Label:
text: "HELLO..."
Label:
text: "WORLD..."
AnchorLayout:
anchor_x: "center"
anchor_y: "bottom"
size_hint: (1, 0.25)
pos_hint: {'x':0, 'y':0}
Label:
text: "FOOTER"

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

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