Good afternoon people.
I'm building an app that takes information from Firebase, all working beautifully!
The application grew and became too complex to be in a single file, so I'm separating it to make it more readable.
In my code below I take data from Firebase and show it in a list.
I happen to have two pieces of information, a FitImage with source and an MDLabel with text.
After I separated the code I'm getting the return below:
AttributeError: 'ImageCard' object has no attribute 'source'
1 - If I manually inform the image path, it works.
2 - Interestingly the text coming from Firebase works.
I'd appreciate your help trying to figure out why the text works and the image doesn't!
from kivymd.uix.dialog import MDDialog
from kivymd.uix.button import MDFlatButton
from kivy.properties import ListProperty
from kivy.properties import StringProperty
from kivy.uix.screenmanager import Screen
from kivymd.uix.card import MDCard
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
# Imports para trabalhar com Firebase
from config import config
import pyrebase
Builder.load_string("""
<ImageCard#MDCard>
id: ec
size_hint: ('180dp', None)
ripple_behavior: True
image:''
text:''
orientation:'vertical'
FitImage:
pos_hint: {'center_x': .5, 'center_y': .25}
source: './images/user.png' # root.source
size_hint: None, None
width: dp(150)
height: dp(150)
#radius: [99, 99, 99, 99]
MDBoxLayout:
orientation:'horizontal'
MDLabel:
text:root.text
halign:"center"
#bold: True
MDFlatButton:
text: "New Screen Here"
increment_width: "164dp"
on_release: root.show_confirmation_dialog()
<ScreenRecycleView>:
name: 'recycle_view'
FloatLayout:
MDTextField:
id: pesquisa
helper_text: "Escreva um trecho da pesquisa e clique em pesquisar."
helper_text_mode: "on_focus"
size_hint: .99, None
halign: 'center'
multiline: False
hint_text: 'Digite o que procura'
text_validate_unfocus: False
pos_hint: {'center_x': 0.42, 'center_y': 0.84}
padding: dp(15)
#size_hint_x: .75
#on_text: root.on_kv_post(self, self.text)
MDIconButton:
icon: "magnify"
pos_hint: {"center_x": .95, "center_y": 0.84}
on_release: root.on_kv_post(self, pesquisa.text)
#:import get_color_from_hex kivy.utils.get_color_from_hex
MDBoxLayout:
pos_hint: {'center_x': 0.5, 'center_y': 0.3}
RecycleView:
data: root.image_data
viewclass: "ImageCard"
RecycleGridLayout:
cols: 2
default_size: dp(155), dp(200)
padding: dp(5) # Determina o espaçamento entre um widget e outro pelos lados
spacing: dp(5) # Determina o espaçamento entre um widget e outro de cima para baixo
default_size_hint: 1, None ##### Define a largura do widget sempre próximo as bordas
size_hint_y: None ##### Associado a default_size_hint
height: self.minimum_height
#ripple_behavior: True""")
class Content(BoxLayout):
pass
class ImageCard(MDCard):
dialog = None
text = StringProperty()
source = StringProperty()
def show_confirmation_dialog(self):
if not self.dialog:
self.dialog = MDDialog(
#title="Address:",
type="custom",
content_cls=Content(),
buttons=[
MDFlatButton(
text="CANCEL",
theme_text_color="Custom",
text_color=self.theme_cls.primary_color,
),
MDFlatButton(
text="OK",
theme_text_color="Custom",
text_color=self.theme_cls.primary_color,
),
],
)
self.dialog.open()
class ScreenRecycleView(Screen):
image_data = ListProperty()
def on_kv_post(self, base_widget, text="", search=False):
# Inicializando o banco de dados.
self.firebase = pyrebase.initialize_app(config)
self.db = self.firebase.database()
self.produtos = self.db.child("Produtos").get(token='**************************************')
#self.ids.rv3.data = []
self.image_data = []
for produto in self.produtos.each():
if text.upper() in produto.val()['nmproduto']:
if produto.val()['url'] != 'SemUrl':
self.image_data.append(
{"source": produto.val()['url'],
"text": produto.val()['nmproduto']
}
)
else:
self.image_data.append(
{"source": './images/sem_imagem.png',
"text": produto.val()['nmproduto']
}
)
#print(json.dumps(self.ids.rv3.data, indent=4))
I thought!
On ImageCard#MDCard it was like this:
image:'' <<<======
text:''
I modified it to:
source:''
text:''
and solved. Interestingly it worked when the code was mixed up.
Related
I'm trying to combine this recycleview example with this screenmanager example so that the recycleview example can be one of the screens in my app. The app runs but all the control buttons display at the bottom of the UI (They're supposed to be at the top) and are either disabled or obscured, disallowing input. Consequently, the recycleview cannot be populated and/or viewed.
Here's my attempt:
import asyncio
from random import sample, randint
from string import ascii_lowercase
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen, FadeTransition
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.recycleview.views import RecycleDataViewBehavior
kv = '''
#:import FadeTransition kivy.uix.screenmanager.FadeTransition
#:import BoxLayout kivy.uix.boxlayout.BoxLayout
#:import RecycleDataViewBehavior kivy.uix.recycleview.views.RecycleDataViewBehavior
ScreenManagement:
transition: FadeTransition()
ContactsScreen:
name: 'contacts'
MessengerScreen:
name: 'messenger'
<Row#RecycleKVIDsDataViewBehavior+BoxLayout>:
canvas.before:
Color:
rgba: 0.5, 0.5, 0.5, 1
Rectangle:
size: self.size
pos: self.pos
value: ''
Label:
id: name
Label:
text: root.value
<ContactsScreen>:
canvas:
Color:
rgba: 0.3, 0.3, 0.3, 1
Rectangle:
size: self.size
pos: self.pos
rv: rv
orientation: 'vertical'
GridLayout:
cols: 3
rows: 2
size_hint_y: None
height: dp(108)
padding: dp(8)
spacing: dp(16)
Button:
text: 'Populate list'
on_press: root.populate()
Button:
text: 'Sort list'
on_press: root.sort()
Button:
text: 'Clear list'
on_press: root.clear()
BoxLayout:
spacing: dp(8)
Button:
text: 'Insert new item'
on_press: root.insert(new_item_input.text)
TextInput:
id: new_item_input
size_hint_x: 0.6
hint_text: 'value'
padding: dp(10), dp(10), 0, 0
BoxLayout:
spacing: dp(8)
Button:
text: 'Update first item'
on_press: root.update(update_item_input.text)
TextInput:
id: update_item_input
size_hint_x: 0.6
hint_text: 'new value'
padding: dp(10), dp(10), 0, 0
Button:
text: 'Remove first item'
on_press: root.remove()
RecycleView:
id: rv
scroll_type: ['bars', 'content']
scroll_wheel_distance: dp(114)
bar_width: dp(10)
viewclass: 'Row'
RecycleBoxLayout:
default_size: None, dp(56)
default_size_hint: 1, None
size_hint_y: None
height: self.minimum_height
orientation: 'vertical'
spacing: dp(2)
<MessengerScreen>:
Button:
on_release: app.root.current = 'contacts'
text: 'back to the home screen'
font_size: 50
'''
class ContactsScreen(Screen):
def populate(self):
self.rv.data = [
{'name.text': ''.join(sample(ascii_lowercase, 6)),
'value': str(randint(0, 2000))}
for x in range(50)]
def sort(self):
self.rv.data = sorted(self.rv.data, key=lambda x: x['name.text'])
def clear(self):
self.rv.data = []
def insert(self, value):
self.rv.data.insert(0, {
'name.text': value or 'default value', 'value': 'unknown'})
def update(self, value):
if self.rv.data:
self.rv.data[0]['name.text'] = value or 'default new value'
self.rv.refresh_from_data()
def remove(self):
if self.rv.data:
self.rv.data.pop(0)
class MessengerScreen(Screen):
pass
class ScreenManagement(ScreenManager):
pass
presentation = Builder.load_string(kv)
class MainApp(App):
def build(self):
return presentation
def main_runner(self):
async def run_wrapper():
# we don't actually need to set asyncio as the lib because it is
# the default, but it doesn't hurt to be explicit
await self.async_run(async_lib='asyncio')
print('App done')
#self.other_task.cancel()
return asyncio.gather(run_wrapper())
if __name__ == '__main__':
loop = asyncio.get_event_loop()
loop.run_until_complete(MainApp().main_runner())
loop.close()
The trouble seems to come from the <Row#RecycleKVIDsDataViewBehavior+BoxLayout> directive but I can't seem to fix it no matter where I place it.
You can position the Buttons using pos_hint, like this:
GridLayout:
id: grid
pos_hint: {'center_x': 0.5, 'top': 1}
Then, you need to size the RecycleView so that it is not over the Buttons, like this:
RecycleView:
id: rv
size_hint_y: None
height: root.height - grid.height
I'm just trying to add a simple 'ToolBar' but after the tool bar kept aligning to the bottom I found that AnchorLayout: let's me anchor the toolbar to the top. But all my content is now only showing in the bottom half of the screen... I'm not sure why.. Adjusting the 'center_y': does nothing... Does anyone see my issue, I really appreciate it.
main
from kivymd.app import MDApp
from kivymd.uix.floatlayout import MDFloatLayout
from kivymd.uix.dialog import MDDialog
from kivymd.uix.button import MDFlatButton, MDIconButton
from kivy.uix.scrollview import ScrollView
from kivy.uix.screenmanager import Screen, ScreenManager
from PyDictionary import PyDictionary
import sys
import json
import requests
class Manager(ScreenManager):
"""Manages Screens"""
class Main(Screen):
"""main application goes here"""
def close_dialog(self, obj):
self.dialog.dismiss()
def show_data(self):
message = """
This little program was
designed to help re-think
your sentences.
"""
close = MDIconButton(icon="close-circle", on_release=self.close_dialog)
#more = MDIconButton(icon="more")
self.dialog = MDDialog(title="Probably Knot", text=message,
size_hint=(0.5, 1), buttons=[close])
self.dialog.open()
class Analyzer(Screen):
def analyze(self, main): # main is pointing to ---> Main().show_data()
"""Analyse data with PyDictionary"""
sent = main.ids.sentence.text.lower()
wrd = main.ids.word.text.lower()
# Definition Section #
dictionary = PyDictionary()
define_wrd = dictionary.meaning(wrd)
noun = ''
verb = ''
adjective = ''
result = ''
try:
noun = " ".join(define_wrd['Noun'])
result += f"Definition:\n1. {wrd}:\n{noun}\n"
except TypeError or KeyError:
noun = False
print('Noun, is not found in API http://words.bighugelabs.com/api')
try:
verb = " ".join(define_wrd['Verb'])
result += f"2.\n{verb}\n"
except TypeError or KeyError:
verb = False
print('Verb, is not found in API http://words.bighugelabs.com/api')
try:
adjective = " ".join(define_wrd['Adjective'])
result += f"3.\n{adjective}\n"
except TypeError or KeyError:
adjective = False
print('Adjective, is not found in API http://words.bighugelabs.com/api')
if not noun and not verb and not adjective:
error = MDDialog(title="Error", text=f"Word: '{wrd}' is not in\n\n'dictionary'")
error.open()
if wrd != '' and sent != '':
API_KEY = 'a701e74e453ee6695e450310340401f5'
URL = f'http://words.bighugelabs.com/api/2/{API_KEY}/{wrd}/json'
if wrd not in sent:
error = MDDialog(title="Error", text=f"Word: '{wrd}' is not in\n\n'{sent}'")
error.open()
else:
r = requests.get(URL) # get's url json file
j = json.loads(r.text) # loads json into 'j' as a dict
if type(j) == dict: # check is 'j' variable is coming in as a Dict
# holds the new sentences
new = f"{result}\n"
try:
for num, w in enumerate(j['adjective']['syn'], 1):
new += f"{num}: {sent.replace(wrd, w)}\n"
except KeyError:
print(f'Adjective for "{wrd}" is not found.')
try:
for num, w in enumerate(j['noun']['syn'], 1):
new += f"{num}: {sent.replace(wrd, w)}\n"
except KeyError:
print(f'Noun for "{wrd}" is not found.')
try:
for num, w in enumerate(j['verb']['syn'], 1):
new += f"{num}: {sent.replace(wrd, w)}\n"
except KeyError:
print(f'Verb for "{wrd}" is not found.')
class ProbablyKnotApp(MDApp):
def build(self):
self.theme_cls.theme_style = "Dark"
self.theme_cls.primary_palette = "Yellow"
self.theme_cls.primary_hue = "A700"
return Manager()
ProbablyKnotApp().run()
kv file
<Manager>:
Main:
name: 'main'
Analyzer:
name: 'analyzer'
<Main>:
AnchorLayout:
anchor_x: 'center'
anchor_y: 'top'
MDToolbar:
title: "Probably Knot"
pos_hint_y: None
pos_y: 1
md_bg_color: app.theme_cls.accent_color
right_action_items: [["dots-vertical", lambda x: app.callback()]]
MDBoxLayout:
orientation: 'vertical'
MDRectangleFlatButton:
text: "help"
pos_hint: {'center_x': 0.75, 'center_y': 1}
on_release: app.root.get_screen('main').show_data()
MDTextField:
id: sentence
icon_right: "book-open-outline"
icon_right_color: app.theme_cls.primary_color
hint_text: "Enter Sentence"
helper_text: "Write a problem statement to analyze"
helper_text_mode: "on_focus"
pos_hint: {'center_x': 0.5, 'center_y': 0.7}
size_hint_x: None
width: 400
MDTextField:
id: word
icon_right: "lead-pencil"
icon_right_color: app.theme_cls.primary_color
hint_text: "Enter Word"
helper_text: "Write ONE word from the above sentence"
helper_text_mode: "on_focus"
pos_hint: {'center_x': 0.5, 'center_y': 0.6}
size_hint_x: None
width: 400
MDIconButton:
icon: "card-plus"
pos_hint: {'center_x': 0.75, 'center_y': 0.5}
on_release: app.root.get_screen('analyzer').analyze(root)
<Analyzer>:
MDToolbar:
title: "Probably Knot"
md_bg_color: app.theme_cls.accent_color
right_action_items: [["dots-vertical", lambda x: app.callback()]]
MDList:
id: container
The problem is that you are not taking into account the default values for size_hint (1,1) and pos (0,0). So your AnchorLayout fills your Main Screen, because of the default values, but the anchor_y setting puts the MDToolBar at the top of the AnchorLayout.
Similarly, your MDBoxLayout also fills the entire Main Screen, but because the MDRectangleFlatButton and the MDTextField have pre-defined sizes, they don't fill the MDBoxLayout. So they only fill the bottom half of the MDBoxLayout.
So here is a version of your kv (for the Main Screen) that uses pos_hint for the MDToolBar and minimum_height for the MDBoxLayout and actually setting its y value to bump up against the tool bar:
<Main>:
MDToolbar:
id: toolbar
title: "Probably Knot"
pos_hint: {'top':1.0}
md_bg_color: app.theme_cls.accent_color
right_action_items: [["dots-vertical", lambda x: app.callback()]]
MDBoxLayout:
size_hint: 1, None
height: self.minimum_height
y: root.height - toolbar.height - self.height
orientation: 'vertical'
MDRectangleFlatButton:
text: "help"
pos_hint: {'center_x': 0.75, 'top': 1}
on_release: app.root.get_screen('main').show_data()
MDTextField:
id: sentence
icon_right: "book-open-outline"
icon_right_color: app.theme_cls.primary_color
hint_text: "Enter Sentence"
helper_text: "Write a problem statement to analyze"
helper_text_mode: "on_focus"
pos_hint: {'center_x': 0.5, 'top': 0.7}
size_hint_x: None
width: 400
MDTextField:
id: word
icon_right: "lead-pencil"
icon_right_color: app.theme_cls.primary_color
hint_text: "Enter Word"
helper_text: "Write ONE word from the above sentence"
helper_text_mode: "on_focus"
pos_hint: {'center_x': 0.5, 'center_y': 0.6}
size_hint_x: None
width: 400
MDIconButton:
icon: "card-plus"
pos_hint: {'center_x': 0.75, 'center_y': 0.5}
on_release: app.root.get_screen('analyzer').analyze(root)
I have the following code where a Button is added to a Grid Layout everytime the test_press method is called. What I'd like to be able to do is change to a different screen when one of these buttons is pressed, but I'd like each Button that's been created to go to a different screen - which screen it goes to isn't important at the moment. How would I go about implementing something like this?
from kivy.uix.scrollview import ScrollView
from kivy.uix.button import Button
from kivy.core.window import Window
from kivymd.theming import ThemeManager
import kivy
from kivy.app import App
from kivy.properties import ObjectProperty, StringProperty, NumericProperty, ListProperty
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.lang import Builder
from kivy.uix.label import Label
Window.clearcolor = (1,1,1,1)
class Finder(Screen):
layout_profiles = ObjectProperty(None)
def test_press(self):
Btn1 = Button(size_hint_y=None, height=75)
self.layout_profiles.add_widget(Btn1)
class MyApp(App):
theme_cls = ThemeManager()
def build(self):
kv = Builder.load_file("kivy.kv")
sm = WindowManager()
screens = [Finder(name="finder")]
for screen in screens:
sm.add_widget(screen)
sm.current = "information"
return sm
if __name__ == '__main__':
MyApp().run()
kv file:
<Finder>:
name: "finder"
layout_profiles: layout_profiles
NavigationLayout:
id: nav_layout
MDNavigationDrawer:
NavigationDrawerIconButton:
text: "Test"
on_release: app.root.current = "login"
FloatLayout:
MDToolbar:
pos_hint: {'top': 1}
md_bg_color: 0.2, 0.6, 1, 1
left_action_items: [['menu', lambda x: root.ids.nav_layout.toggle_nav_drawer()]]
Label:
background_normal: ""
background_color: 1, 1, 1, 1
color: 0, 0, 0, 1
text: "Holding text"
font_size: 20
multiline: True
pos_hint: {"x": 0.125, "y": 0.7}
text_size: self.width, None
size_hint: 0.75, None
height: self.texture_size[1]
halign: "center"
ScrollView:
size_hint: 0.95, 0.6
pos_hint: {"x": 0.025, "top": 0.65, "bottom": 0.2}
do_scroll_x: False
GridLayout:
cols: 1
id: layout_profiles
size_hint_y: None
spacing: 10
height: self.minimum_height
canvas:
Color:
rgba: (1, 1, 1, 1)
Rectangle:
size: self.size
pos: self.pos
BoxLayout:
cols: 1
Button:
text: "Add widget"
size_hint: 0.5, 0.1
pos_hint: {"x": 0.5, "top": 0.1}
on_release: root.test_press()
Also apologies if the title (or description!) isn't that clear, I wasn't sure how to describe it.
The "Add widget" Button is just there to mimic the eventual goal where the buttons will be added dependent on some information feeding in from a database.
I want to hide one widget and show another on button's click. I do it by changing opacity form 1 to 0 and from 0 to 1. The firt widget becomes invisible, but the second is not showing.
This is my python file:
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.properties import NumericProperty
from kivy.config import Config
Config.set('graphics', 'width', '1920')
Config.set('graphics', 'height', '1080')
Config.set('graphics', 'fullscreen', 1)
class FirstScreen(Screen):
pass
class SecondScreen(Screen):
pass
class MyScreenManager(ScreenManager):
pass
class PasswordEntryWidget(BoxLayout):
def checkPswd(instance, pswd):
if (pswd == "123"):
instance.parent.opacity = 0
instance.parent.disabled = True
instance.parent.parent.ids.settingsWgt.opacity = 1.0
#print(instance.parent.parent.ids.settingsWgt.size_hint)
class SettingsEntryWidget(BoxLayout):
def checkPswd(instance, pswd):
if (pswd == "123"):
print ("It's OK!")
class MyApp(App):
def build(self):
return MyScreenManager()
if __name__ == '__main__':
MyApp().run()
This is my.kv:
#:kivy 1.11.1
#:include loginWidgets.kv
<MyScreenManager>:
FirstScreen:
SecondScreen:
<FirstScreen>:
name: "FirstScreen"
canvas.before:
Rectangle:
pos: self.pos
size: self.size
source: 'img/background.png'
FloatLayout:
size: root.size
PasswordEntryWidget:
id: passwordWgt
size_hint: 0.2, 0.1
pos_hint: {'top': 0.35, 'right': 0.7}
SettingsEntryWidget:
id: settingsWgt
opacity: 0
disabled: True
size_hint: 0.2, 0.32
pos_hint: {'top': 0.35, 'right': 0.95}
<SecondScreen>:
name: "SecondScreen"
Label:
color: 1,1,1,1
font_size: 10
center_x: root.width/4
top: root.top - 50
text: "Lalalala"
And this is loginWidgets.kv:
#:kivy 1.11.1
<PasswordEntryWidget>:
orientation: "vertical"
spacing: 20
#padding: 50
TextInput:
id: adminPswdLine
multiline: False
password: True
size_hint_y: None
height: 30
font_size: self.height - 10
Button:
id: "takeAdminPswd"
size_hint_x: 0.5
pos_hint: {'center_x': 0.5}
on_press: root.checkPswd(adminPswdLine.text)
<SettingsEntryWidget>:
orientation: "vertical"
spacing: 20
#padding: 50
TextInput:
id: host
padding: [5, 2, 0, 5]
text: ""
multiline: False
password: False
size_hint_y: None
height: 30
font_size: self.height - 10
Button:
id: "takeSettings"
size_hint_x: 0.5
pos_hint: {'center_x': 0.5}
on_press: root.checkPswd(adminPswdLine.text)
As I said, the first part works well. PasswordWgt hide perfectly, but SettingsWgt doesn't become visible. When I print it's opacity after - it gives 1, so widget must be visible, but it's not. I checked ids and what elements are there and needed widget is there with this id.
Is it a bug or I do something wrong?
The problem is that your are changing the opacity of the container (FloatLayout) instead of the PasswordEntryWidget. Just change:
class PasswordEntryWidget(BoxLayout):
def checkPswd(instance, pswd):
if (pswd == "123"):
instance.parent.opacity = 0
instance.parent.disabled = True
instance.parent.parent.ids.settingsWgt.opacity = 1.0
to:
class PasswordEntryWidget(BoxLayout):
def checkPswd(instance, pswd):
if (pswd == "123"):
instance.opacity = 0
instance.disabled = True
instance.parent.parent.ids.settingsWgt.opacity = 1.0
and I think it will work as you desire.
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