How can I search in recycleview with updated review .I can also search now. But when I type 3 alphabets in txt_input it search for the same result. and gives the list which contains those 3 alphabets.
But i want to make as a search engine. so if I type "TAT" it will show me TATA MOTORS PVT LTD,Tata Elxsi Limited,Tata Steel Limited,etc. But when I type "TATA MO" it doesnot update the recycleview with new search suggestions.
How can I achieve that kind of updated result every time add alphabets?
test.py file
from kivy.app import App
from kivy.uix.textinput import TextInput
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.floatlayout import FloatLayout
from kivy.properties import NumericProperty, ListProperty, BooleanProperty, ObjectProperty, StringProperty
from kivy.uix.recycleview import RecycleView
from kivy.uix.recyclegridlayout import RecycleGridLayout
from kivy.uix.recycleview.views import RecycleDataViewBehavior
from kivy.uix.label import Label
from kivy.uix.recycleboxlayout import RecycleBoxLayout
from kivy.uix.behaviors import FocusBehavior
from kivy.uix.recycleview.layout import LayoutSelectionBehavior
import pandas as pd
Builder.load_string('''
<Body>:
name: 'body_screen'
canvas:
Color:
rgba:(1, 1, 1, 1)
Rectangle:
# pos: self.pos
size: self.size
<DropDownWidget>:
name: 'DropDownWidget'
canvas:
Color:
rgba:(1, 1, 1, 1)
Rectangle:
# pos: self.pos
size: self.size
# orientation: 'vertical'
spacing: 20
txt_input: txt_input
rv: rv
# txt_input1: txt_input1
MyTextInput:
id: txt_input1
pos: 400,300
size_hint_y: None
height: 50
MyTextInput:
id: txt_input
hint_text:'Enter here'
size_hint_y: None
height: 50
RV:
id: rv
<MyTextInput>:
name: 'MyTextInput'
readonly: False
multiline: False
<SelectableLabel>:
name: 'SelectableLabel'
id: SelectableLabel
# Draw a background to indicate selection
color: 0,0,0,1
canvas.before:
Color:
rgba: (0, 0, 1, .5) if self.selected else (1, 1, 1, 1)
Rectangle:
# pos: self.pos
size: self.size
<RV>:
canvas:
Color:
rgba: 0,0,0,.2
Line:
rectangle: self.x +1 , self.y, self.width - 2, self.height -2
bar_width: 10
scroll_type:['bars']
viewclass: 'SelectableLabel'
SelectableRecycleBoxLayout:
default_size: None, dp(20)
default_size_hint: 1, None
size_hint_y: None
height: self.minimum_height
orientation: 'vertical'
multiselect: False
''')
class SelectableRecycleBoxLayout(FocusBehavior, LayoutSelectionBehavior,
RecycleBoxLayout):
''' Adds selection and focus behaviour to the view. '''
class SelectableLabel(RecycleDataViewBehavior,Label):
''' Add selection support to the Label '''
index = None
selected = BooleanProperty(False)
selectable = BooleanProperty(True)
txt_input1 = ObjectProperty(None)
txt_input = ObjectProperty(None)
def refresh_view_attrs(self, rv, index, data):
''' Catch and handle the view changes '''
self.index = index
return super(SelectableLabel, self).refresh_view_attrs(
rv, index, data)
def on_touch_down(self, touch):
''' Add selection on touch down '''
if super(SelectableLabel, self).on_touch_down(touch):
return True
if self.collide_point(*touch.pos) and self.selectable:
return self.parent.select_with_touch(self.index, touch)
def apply_selection(self, rv, index, is_selected):
''' Respond to the selection of items in the view. '''
self.selected = is_selected
if is_selected:
App.get_running_app().root.widget_1.ids.txt_input1.text = str(rv.data[index].get("text"))
class RV(RecycleView):
def __init__(self, **kwargs):
super(RV, self).__init__(**kwargs)
class DropDownWidget(BoxLayout):
txt_input = ObjectProperty()
rv = ObjectProperty()
txt_input1 = ObjectProperty()
class MyTextInput(TextInput):
txt_input = ObjectProperty()
txt_input1 = ObjectProperty(None)
flt_list = ObjectProperty()
word_list = ListProperty()
# this is the variable storing the number to which the look-up will start
starting_no = NumericProperty(3)
suggestion_text = ''
def __init__(self, **kwargs):
super(MyTextInput, self).__init__(**kwargs)
def on_text(self, instance, value):
# find all the occurrence of the word
self.parent.ids.rv.data = []
matches = [self.word_list[i] for i in range(len(self.word_list)) if
self.word_list[i][:self.starting_no] == value[:self.starting_no]]
# display the data in the recycleview
display_data = []
for i in matches:
display_data.append({'text': i})
self.parent.ids.rv.data = display_data
# ensure the size is okay
if len(matches) <= 10:
self.parent.height = (50 + (len(matches) * 20))
else:
self.parent.height = 240
def keyboard_on_key_down(self, window, keycode, text, modifiers):
if self.suggestion_text and keycode[1] == 'tab':
self.insert_text(self.suggestion_text + ' ')
return True
return super(MyTextInput, self).keyboard_on_key_down(window, keycode, text, modifiers)
class Body(FloatLayout):
def __init__(self, **kwargs):
f = pd.read_csv("stoploss.csv")
fl = len(f.index)
file = pd.DataFrame(f, columns=['Stock Symbol', 'Purchase Price', 'Stock Name', 'Stop Loss(%)'])
j = 0
wl = []
for i in range(fl):
for index in range(1):
columnSeriesObj = file.iloc[:, 2]
# pp = iter(columnSeriesObj.values)
# pp1 = next(pp)
# print(pp1)
wl.append(columnSeriesObj.values[i])
tp = tuple(wl)
print(str(tp))
# def convertTuple(tup):
# str = ''.join(tup)
# return str
# print(convertTuple(tp))
super(Body, self).__init__(**kwargs)
self.widget_1 = DropDownWidget(pos_hint={'center_x': .5, 'center_y': .5},
size_hint=(None, None), size=(600, 60))
self.widget_1.ids.txt_input.word_list = wl
self.widget_1.ids.txt_input.starting_no = 3
self.add_widget(self.widget_1)
class MyApp(App):
def build(self):
return Body()
if __name__ == "__main__":
MyApp().run()
here i am answering my own question.I found the solution from google kivy groups.
change change of code will do the thing.
change the code from:
matches = [self.word_list[i] for i in range(len(self.word_list)) if
self.word_list[i][:self.starting_no] == value[:self.starting_no]]
to:
matches = [word for word in self.word_list
if word[:len(value)].lower() == value[:len(value)].lower()]
Related
I have a recycleview of several thousand songs. I want to force a selection when I shuffle songs. I can force scrolling to the selected song by setting scroll_y but I cannot seem to get the item in the recycleview to display as selected as with the basic kivy recycleview example where you click on an item and it changes background color.
I have a basic example. If you click it should start the random item selection every 0.5 sec and print out the rv.data showing that the items have 'selected': True.
I've tried setting key_selection: 'selected' and I've also set 'selected': True in the recycleview.data.
MPROSRVbug.kv
<Manachan>:
id: manachanID
SelectionScreen:
id: selectscreenID
name: 'selectscreen'
manager: 'manachanID'
<SelectionScreen>:
id: selectionscreenid
BoxLayout:
orientation: 'horizontal'
Video:
id: previewVideo
SongList:
id: songlistid
<SongList>
cols: 1
size_hint_x: 1
BoxLayout:
size_hint: (1,.1)
orientation: 'vertical'
Label:
id: songtitle
canvas.before:
Color:
rgba: (.3, .3, .3, 1)
Rectangle:
pos: self.pos
size: self.size
RV:
id: recycle_grid1
size_hint_x: 1
<RV>:
viewclass: 'SongLinkButton'
SelectableRecycleBoxLayout:
id: recycle_grid2
default_size: None, dp(120)
default_size_hint: 1, None
size_hint_y: None
height: self.minimum_height
orientation: 'vertical'
<SongLinkButton>:
id: songbutton
orientation: 'horizontal'
height: '80dp'
# Draw a background to indicate selection
canvas.before:
Color:
rgba: (.0, 0.9, .1, .3) if self.selected else (0, 0, 0, 1)
Rectangle:
pos: self.pos
size: self.size
Label:
id: textinfo
text_size: self.width, None
MPROSRVbug.py
#MUSIC PLAYER RANDOM ORDERED SORT
import os, sys
from random import *
songDict = {}
songVal = {}
i = 0
for mp3file in ["1","9","7k","r","j","i","7","g","a","2",]:
songDict[i] = mp3file
songVal[str(mp3file)] = 0
i += 1
if i > 7:
break
import kivy
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.label import Label
from kivy.uix.recycleview import RecycleView
from kivy.uix.behaviors import FocusBehavior
from kivy.uix.recycleview.layout import LayoutSelectionBehavior
from kivy.uix.recycleboxlayout import RecycleBoxLayout
from kivy.uix.recycleview.views import RecycleKVIDsDataViewBehavior
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.gridlayout import GridLayout
from kivy.properties import *
from kivy.core.audio import SoundLoader
from kivy.uix.scrollview import ScrollView
from kivy.clock import Clock
import traceback
class RV(RecycleView):
def __init__(self, **kwargs):
super(RV, self).__init__(**kwargs)
#set self.data:
self.data = [{'textinfo.text': x, 'selected': False} for x in [songDict[y] for y in songDict]]
print("self.data item?", self.data[0], len(self.data))
def scroll_to_index(self, index):
box = self.children[0]
pos_index = (box.default_size[1] + box.spacing) * index
scroll = self.convert_distance_to_scroll(
0, pos_index - (self.height * 0.5))[1]
if scroll > 1.0:
scroll = 1.0
elif scroll < 0.0:
scroll = 0.0
self.scroll_y = 1.0 - scroll
def NextSong(self, *args):
rvRef = App.get_running_app().root.get_screen('selectscreen').ids["songlistid"].ids["recycle_grid1"]
randPickInt = randint(0,len(rvRef.data)-1)
for d in rvRef.data:
if d['textinfo.text'] == songDict[randPickInt]:
d['selected'] = True
dictElement = d
target = os.path.normpath(rvRef.data[randPickInt]['textinfo.text'])
App.get_running_app().root.get_screen('selectscreen').ids["songlistid"].ids["songtitle"].text = target
targettextOG = rvRef.data[randPickInt]['textinfo.text']
#PLAN: apply_selection always triggers when reycycleview refreshes, so set a global var of the selected guy. within the widget, if the name is the same as the selected guy, make yourself selected
global curSelectedSong
curSelectedSong = rvRef.data[randPickInt]['textinfo.text']
counter = 0
for d in rvRef.data:
#remove all previously selected
if d['selected']:
d['selected'] = False
#if we found the song, change to selected
if d['textinfo.text'] == targettextOG:
#print("VERSING", d['textinfo.text'], targettextOG, d['textinfo.text'] == targettextOG)
d['selected'] = True
#print("so has d updated?", d)
rvRef.data[counter] = d
print("updated rvRef.data", rvRef.data[counter])
counter += 1
print("WHAT IS RV DATA?", rvRef.data)
App.get_running_app().root.get_screen('selectscreen').ids["songlistid"].ids["recycle_grid1"].scroll_to_index(randPickInt)
rvRef.refresh_from_data()
class SelectableRecycleBoxLayout(FocusBehavior, LayoutSelectionBehavior,
RecycleBoxLayout):
''' Adds selection and focus behaviour to the view. '''
def __init__(self, **kwargs):
super(SelectableRecycleBoxLayout, self).__init__(**kwargs)
def WeightedChoice():
pass
class SongLinkButton(RecycleKVIDsDataViewBehavior,BoxLayout,Label):
''' Add selection support to the Label '''
index = None
selected = BooleanProperty(False)
selectable = BooleanProperty(True)
def __init__(self, **kwargs):
super(SongLinkButton, self).__init__(**kwargs)
def refresh_view_attrs(self, rv, index, data):
''' Catch and handle the view changes '''
self.index = index
return super(SongLinkButton, self).refresh_view_attrs(
rv, index, data)
def on_touch_down(self, touch):
''' Add selection on touch down '''
if super(SongLinkButton, self).on_touch_down(touch):
return True
if self.collide_point(*touch.pos) and self.selectable:
return self.parent.select_with_touch(self.index, touch)
def apply_selection(self, rv, index, is_selected):
global curSelectedSong
try:
if curSelectedSong == rv.data[index]["textinfo.text"]:
self.selected == True
except:
pass
global soundObj
''' Respond to the selection of items in the view. '''
self.selected = is_selected
if is_selected and App.get_running_app().root.current == 'selectscreen':
target = os.path.normpath(rv.data[index]['textinfo.text'])
Clock.schedule_interval(App.get_running_app().root.get_screen('selectscreen').ids["songlistid"].ids["recycle_grid1"].NextSong, 1)
App.get_running_app().root.get_screen('selectscreen').ids["songlistid"].ids["songtitle"].text = target
else:
pass
class Manachan(ScreenManager):
pass
class SongList(GridLayout):
pass
class SelectionScreen(Screen):
pass
class MyApp(App):
def build(self):
self.load_kv('MPROSRVbug.kv')
self.title = "Music Player Random Ordered Sort by Pengindoramu"
return Manachan()
if __name__ == '__main__':
MyApp().run()
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I am converting my code from kivy to kivymd. But it is not showing anything on screen. I am not able to find the issue... How can I run it..I am using pycharm.
it was working fine in the kivy code...I looked at some examples of kivymd and then converted it.
and If my question is in apropriate please someone edit it
.py code
from kivy.lang import Builder
from kivymd.app import MDApp
from kivy.uix.popup import Popup
from kivy.uix.widget import Widget
from kivy.properties import ObjectProperty
from kivymd.uix.boxlayout import MDBoxLayout
from kivymd.uix.gridlayout import MDGridLayout
from kivymd.uix.button import MDFlatButton
import sys, time, threading
import pyrebase
from kivymd.uix.screen import MDScreen
from kivy.uix.screenmanager import ScreenManager, Screen
from datetime import datetime, timedelta
import pandas_datareader.data as web
from kivymd.theming import ThemeManager
import pandas as pd
from kivymd.icon_definitions import md_icons
from kivy.utils import get_color_from_hex
import webbrowser
from kivymd.uix.screen import Screen
from kivymd.uix.list import MDList, ThreeLineListItem, ThreeLineAvatarIconListItem, OneLineListItem
from kivymd.uix.list import IconLeftWidget, ImageLeftWidget
from kivy.uix.scrollview import ScrollView
from kivy.uix.button import Button
from kivymd.uix.card import MDCardSwipe
from kivy.properties import ObjectProperty
import csv
from os import path
from kivy.uix.image import Image
from kivy.app import App
from kivy.uix.textinput import TextInput
from kivy.lang import Builder
from kivy.uix.gridlayout import GridLayout
from kivy.uix.floatlayout import FloatLayout
from kivy.properties import NumericProperty, ListProperty, BooleanProperty, ObjectProperty, StringProperty
from kivy.uix.recycleview import RecycleView
from kivy.uix.recyclegridlayout import RecycleGridLayout
from kivy.uix.recycleview.views import RecycleDataViewBehavior
from kivy.uix.label import Label
import re
from kivy.uix.behaviors import FocusBehavior
from kivy.uix.recycleview.layout import LayoutSelectionBehavior
import pandas as pd
from kivy.clock import Clock
from functools import partial
from kivymd.uix.dialog import MDDialog
from kivymd.uix.textfield import MDTextField, MDTextFieldRound
from kivymd.uix.label import MDLabel
from kivymd.toast import toast
from kivy.core.window import Window
Window.size = (300, 500)
username = ''
class SelectableRecycleBoxLayout(FocusBehavior, LayoutSelectionBehavior,
RecycleGridLayout):
''' Adds selection and focus behaviour to the view. '''
class SelectableLabel(RecycleDataViewBehavior, MDLabel):
''' Add selection support to the Label '''
index = None
selected = BooleanProperty(False)
selectable = BooleanProperty(True)
txt_input = ObjectProperty(None)
stock_name = ObjectProperty(None)
stock_symbol = ObjectProperty(None)
purchase_price = ObjectProperty(None)
stop_loss = ObjectProperty(None)
highlight = ListProperty([1, 1, 1, 1])
def refresh_view_attrs(self, rv, index, data):
''' Catch and handle the view changes '''
self.index = index
return super(SelectableLabel, self).refresh_view_attrs(
rv, index, data)
def on_touch_down(self, touch):
''' Add selection on touch down '''
if super(SelectableLabel, self).on_touch_down(touch):
return True
if self.collide_point(*touch.pos) and self.selectable:
return self.parent.select_with_touch(self.index, touch)
def apply_selection(self, rv, index, is_selected):
''' Respond to the selection of items in the view. '''
self.selected = is_selected
if is_selected:
# App.get_running_app().root.widget_1.ids.txt_input1.text = str(rv.data[index].get("text"))
xx = str(rv.data[index].get("text"))
if (xx.find('(NSI)') != -1):
x, y = xx.split(" (NSI)")
add_sym = '.NS'
else:
x, y = xx.split(" (BSE)")
add_sym = '.BO'
print(xx)
print(x)
App.get_running_app().root.get_screen('body_screen').widget_1.ids.stock_name.text = x
f = pd.read_csv("Stock Tickers.csv", encoding="ISO-8859-1", engine='python')
fl = len(f.index)
file = pd.DataFrame(f, columns=['Symbols', 'Name', 'Exchange'])
for i in range(fl):
for index in range(1):
columnSeriesObj_sym = file.iloc[:, 0]
columnSeriesObj1 = file.iloc[:, 1]
columnSeriesObj_ex = file.iloc[:, 2]
before_sym, b = columnSeriesObj_sym.values[i].split('.')
if columnSeriesObj1.values[i] == App.get_running_app().root.get_screen(
'body_screen').widget_1.ids.stock_name.text:
App.get_running_app().root.get_screen(
'body_screen').widget_1.ids.stock_symbol.text = before_sym + add_sym
class RV(RecycleView):
def __init__(self, **kwargs):
super(RV, self).__init__(**kwargs)
class DropDownWidget(MDBoxLayout):
txt_input = ObjectProperty(None)
rv = ObjectProperty(None)
stock_name = ObjectProperty(None)
stock_symbol = ObjectProperty(None)
purchase_price = ObjectProperty(None)
stop_loss = ObjectProperty(None)
def back(self):
self.clear_texts()
MDApp.get_running_app().root.transition.direction = 'right'
MDApp.get_running_app().root.current = 'option_screen'
def clear_texts(self):
App.get_running_app().root.get_screen('body_screen').widget_1.ids.txt_input.text = ""
App.get_running_app().root.get_screen('body_screen').widget_1.ids.stock_name.text = ""
App.get_running_app().root.get_screen('body_screen').widget_1.ids.stock_symbol.text = ""
App.get_running_app().root.get_screen('body_screen').widget_1.ids.purchase_price.text = ""
App.get_running_app().root.get_screen('body_screen').widget_1.ids.stop_loss.text = ""
def btn_input(self):
if App.get_running_app().root.get_screen('body_screen').widget_1.ids.stock_name.text == '':
toast('Please Select Stock')
elif App.get_running_app().root.get_screen('body_screen').widget_1.ids.stock_symbol.text == '':
toast('Please Select Stock')
elif App.get_running_app().root.get_screen('body_screen').widget_1.ids.purchase_price.text == '':
toast('Please Enter Purchase Price')
elif App.get_running_app().root.get_screen('body_screen').widget_1.ids.stop_loss.text == '':
toast('Please Enter Stoploss')
elif float(App.get_running_app().root.get_screen('body_screen').widget_1.ids.stop_loss.text) <= 100:
print("Stock Name:", App.get_running_app().root.get_screen('body_screen').widget_1.ids.stock_name.text,
"Stock Symbol:", App.get_running_app().root.get_screen('body_screen').widget_1.ids.stock_symbol.text)
print("Purchase Price:",
App.get_running_app().root.get_screen('body_screen').widget_1.ids.purchase_price.text,
"Stop Loss(%):", App.get_running_app().root.get_screen('body_screen').widget_1.ids.stop_loss.text)
# write data to csv file
file_name ="stoploss.csv"
if path.exists(file_name):
with open(file_name, "a+", newline='')as newFile:
fieldnames = ["Stock Name", "Stock Symbol", "Purchase Price", "Stop Loss(%)"]
newFileWriter = csv.DictWriter(newFile, fieldnames=fieldnames)
newFileWriter.writerow({"Stock Name": App.get_running_app().root.get_screen(
'body_screen').widget_1.ids.stock_name.text,
"Stock Symbol": App.get_running_app().root.get_screen(
'body_screen').widget_1.ids.stock_symbol.text,
"Purchase Price": App.get_running_app().root.get_screen(
'body_screen').widget_1.ids.purchase_price.text,
"Stop Loss(%)": App.get_running_app().root.get_screen(
'body_screen').widget_1.ids.stop_loss.text})
else:
myFile = open(file_name, 'w+', newline='')
myData = [["Stock Name", "Stock Symbol", "Purchase Price", "Stop Loss(%)"],
[App.get_running_app().root.get_screen('body_screen').widget_1.ids.stock_name.text,
App.get_running_app().root.get_screen('body_screen').widget_1.ids.stock_symbol.text,
App.get_running_app().root.get_screen('body_screen').widget_1.ids.purchase_price.text,
App.get_running_app().root.get_screen('body_screen').widget_1.ids.stop_loss.text]]
with myFile:
writer = csv.writer(myFile)
writer.writerows(myData)
self.clear_texts()
else:
App.get_running_app().root.get_screen('body_screen').widget_1.ids.stop_loss.text = ''
toast(text='The Stoloss should be less then 100%')
class MyTextInput(MDTextFieldRound):
txt_input = ObjectProperty(None)
flt_list = ObjectProperty()
word_list = ListProperty()
stock_name = ObjectProperty(None)
stock_symbol = ObjectProperty(None)
purchase_price = ObjectProperty(None)
stop_loss = ObjectProperty(None)
# this is the variable storing the number to which the look-up will start
starting_no = NumericProperty()
suggestion_text = ''
def __init__(self, **kwargs):
super(MyTextInput, self).__init__(**kwargs)
def on_text(self, instance, value):
# find all the occurrence of the word
self.parent.parent.parent.ids.rv.data = []
if len(value) != 0:
matches = [word for word in self.word_list if word.lower().find(value.lower()) != -1]
# display the data in the recycleview
display_data = []
for i in matches:
display_data.append({'text': i})
self.parent.parent.parent.ids.rv.data = display_data
# ensure the size is okay
if len(matches) <= 10:
self.parent.height = (50 + (len(matches) * 20))
else:
self.parent.height = 250
def keyboard_on_key_down(self, window, keycode, text, modifiers):
if self.suggestion_text and keycode[1] == 'tab':
self.ids.rv.refresh_from_data()
self.insert_text(self.suggestion_text + ' ')
return True
return super(MyTextInput, self).keyboard_on_key_down(window, keycode, text, modifiers)
class Body1(MDScreen):
def build(self):
f = pd.read_csv("Stock Tickers.csv", encoding="ISO-8859-1", engine='python')
fl = len(f.index)
file = pd.DataFrame(f, columns=['Symbols', 'Name', 'Exchange'])
wl = []
for i in range(fl):
for index in range(1):
columnSeriesObj = file.iloc[:, 1]
self.columnSeriesObj_ex = file.iloc[:, 2]
wl.append(columnSeriesObj.values[i] + " (" + self.columnSeriesObj_ex.values[i] + ")")
tp = tuple(wl)
self.widget_1 = DropDownWidget()
self.widget_1.ids.txt_input.word_list = wl
self.widget_1.ids.txt_input.starting_no = 3
self.add_widget(self.widget_1)
sm = ScreenManager()
sm.add_widget(Body1(name='body_screen1'))
class stockinput1App(MDApp):
def build(self):
kv = Builder.load_file("ss.kv")
return kv
if __name__ == "__main__":
stockinput1App().run()
.kv code
ScreenManager:
Body1:
<Body1>:
on_enter:root.build()
name: 'body_screen1'
canvas.before:
Color:
rgba: 155/255, 159/255, 250/255, 1
Rectangle:
pos: self.pos
size: self.size
<DropDownWidget>:
canvas.before:
Color:
rgba: 155/255, 159/255, 250/255, 1
Rectangle:
pos: self.pos
size: self.size
cols:1
id: DropDownWidget
stock_name: stock_name
stock_symbol: stock_symbol
purchase_price: purchase_price
stop_loss: stop_loss
txt_input: txt_input
rv: rv
orientation:'vertical'
spacing: '20dp'
MDToolbar:
title:'Add Stock'
type: "top"
size_hint_y:0.1
pos_hint: {'top':1.0}
left_action_items: [["arrow-left", lambda x: root.back()]]
md_bg_color:152/255,87/255,189/255,1
elevation:10
MDBoxLayout:
spacing:'5dp'
orientation:'vertical'
MDCard:
md_bg_color:155/255, 159/255, 250/255, 1
pos_hint: {'center_x': .5, 'center_y': .5}
elevation:0
orientation:'vertical'
spacing:'10dp'
MyTextInput:
id: txt_input
hint_text: "Search"
icon_right: "magnify"
icon_right_color:1,1,1,1
pos_hint: {'center_x': .5, 'center_y': .5}
size_hint:.9,.2
line_color_normal:184/255,187/255,252/255,1
normal_color:1,1,1,0
RV:
id: rv
pos_hint: {'center_x': .5, 'center_y': .5}
size_hint:1,0.6
MDCard:
md_bg_color:155/255, 159/255, 250/255, 1
orientation:'horizontal'
pos_hint: {'center_x': .5, 'center_y': .5}
size_hint:.9,.4
elevation:0
MDTextField:
id: stock_name
hint_text: "Stock Name"
readonly: True
multiline:True
mode:'rectangle'
required: True
outline_color:184/255,187/255,252/255,1
size:.5,.3
MDCard:
orientation:'horizontal'
pos_hint: {'center_x': .5, 'center_y': .5}
size_hint:.9,.4
elevation:0
md_bg_color:155/255, 159/255, 250/255, 1
MDTextField:
id: stock_symbol
hint_text: "Stock Symbol"
readonly: True
multiline:False
mode:'rectangle'
required: True
pos_hint: {'center_x': .5, 'center_y': .5}
line_color_normal:184/255,187/255,252/255,1
MDCard:
orientation:'horizontal'
pos_hint: {'center_x': .5, 'center_y': .5}
size_hint:.9,.4
elevation:0
md_bg_color:155/255, 159/255, 250/255, 1
MDTextField:
id: purchase_price
hint_text: "Purchase Price"
input_filter: 'float'
multiline:False
mode:'rectangle'
required: True
line_color_normal:184/255,187/255,252/255,1
size:.5,.3
MDCard:
orientation:'horizontal'
pos_hint: {'center_x': .5, 'center_y': .5}
size_hint:.9,.4
elevation:0
md_bg_color:155/255, 159/255, 250/255, 1
MDTextField:
id: stop_loss
hint_text: "Stop Loss(%)"
input_filter: 'float'
max_text_length: 3
multiline:False
mode:'rectangle'
required: True
size:.5,.3
color_mode: 'custom'
line_color_normal:1,1,1,1
MDCard:
pos_hint: {'center_x': .5, 'center_y': .5}
size_hint:.5,.5
elevation:0
md_bg_color:155/255, 159/255, 250/255, 1
MDRaisedButton:
text:"Submit"
pos_hint: {'center_x': .5, 'center_y': .6}
size_hint:.5,.7
md_bg_color:40/255, 44/255, 177/255, 1
elevation:15
on_press: root.btn_input()
<MyTextInput>:
id: MyTextInput
mode:'rectangle'
readonly: False
multiline: False
<SelectableLabel>:
id: SelectableLabel
multiline: True
# Draw a background to indicate selection
canvas:
Color:
rgba: (218/255,112/255,214/255,.6) if self.selected else (1, 1, 1, 0.5)
Rectangle:
pos: self.pos if self.selected else (0,0)
size: self.size if self.selected else (0,0)
halign:'center'
<RV>:
canvas:
Color:
rgba: 1,1,1,1
Line:
width: 1.1
rectangle: self.x , self.y, self.width, self.height
height: 10
bar_width: 20
scroll_type:['bars']
viewclass: 'SelectableLabel'
SelectableRecycleBoxLayout:
cols:1
row_default_height: 30
row_force_default:True
default_size: self.size, dp(20)
default_size_hint: 1, None
size_hint_y: None
height: 300
multiselect: False
I am sharing the link to csv ,py,kv files ... here
A bug in Kivy results in the on_enter event not being dispatched for the initial Screen in a ScreenManager, so your build() method is never called. A work around is to call it yourself:
class stockinput1App(MDApp):
def build(self):
kv = Builder.load_file("ss.kv")
kv.get_screen('body_screen1').build()
return kv
Another note: Not technically an error, but the lines:
sm = ScreenManager()
sm.add_widget(Body1(name='body_screen1'))
are creating a a second instance of ScreenManager and two instances of Body1. All of which are then ignored. These lines can be removed. The entire GUI is actually built by the call to Builder.load_file().
I'm new on kivy.I'm trying to change text input value (the string value that is shown in TextInput box) from another class, But nothing passes.
I have following widgets in class MyFirstScreen:
One RecycleView with multiple items (each item is a dictionary)
Two TextInputs
What I want to do: When each items in RecycleView selected, TextInputs should be update and load with corresponding values of selected item's dictionary.
But when i try to access current TextInput's value from another class (class SelectableLabel):
class SelectableLabel(RecycleDataViewBehavior, Label):
#...
def update_text_inputs(self, *kwarg):
my_text_input = MyFirstScreen().ids.system_name_text_input_id #<--i can access to widget
print("my_print_val is:", my_text_input.text) #<--but widget's current text value is : ''
my_text_input.text = "Updated Value"
I can access to my_text_input widget but its text (my_text_input.text) is an empty string ('').Furthermore when i change the value of my_text_input.text, nothing happens in TextInput's box.
Does anyone know what am I doing wrong here or how to make this work? Thank you in advance...
Here is my .py code:
from kivy.app import App
from kivy.lang import Builder
from kivy.properties import ObjectProperty
from kivy.uix.label import Label
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.recycleview import RecycleView
from kivy.uix.recycleview.views import RecycleDataViewBehavior
from kivy.properties import BooleanProperty
from kivy.uix.recycleboxlayout import RecycleBoxLayout
from kivy.uix.behaviors import FocusBehavior
from kivy.uix.recycleview.layout import LayoutSelectionBehavior
class Manager(ScreenManager):
def __init__(self, **kwargs):
super().__init__(**kwargs)
class MyFirstScreen(Screen):
system_name_text_input_id = ObjectProperty(None)
def __init__(self, **kwarg):
super().__init__(**kwarg)
print("__init__ of MyFirstScreen is Called")
def get_text_inputs(self):
ret_val = self.ids.system_name_text_input_id.text
print("get_text_input is called, ret_val:", ret_val)
return ret_val
class RecycleViewWidget(RecycleView):
def __init__(self, **kwargs):
super(RecycleViewWidget, self).__init__(**kwargs)
self.items_of_rv = []
for i in range(1, 21):
self.items_of_rv.append(
{"color": (0, 0, 0, 1), "font_size": "20", "text": f"User {i}",
"user_id": f"{100 * i}"})
self.data = [item for item in self.items_of_rv]
class SelectableRecycleBoxLayout(FocusBehavior, LayoutSelectionBehavior, RecycleBoxLayout):
""" Adds selection and focus behaviour to the view. """
class SelectableLabel(RecycleDataViewBehavior, Label):
""" Add selection support to the Label """
index = None
selected = BooleanProperty(False)
selectable = BooleanProperty(True)
def refresh_view_attrs(self, rv, index, data):
""" Catch and handle the view changes """
self.index = index
return super(SelectableLabel, self).refresh_view_attrs(rv, index, data)
def on_touch_down(self, touch):
""" Add selection on touch down """
if super(SelectableLabel, self).on_touch_down(touch):
return True
if self.collide_point(*touch.pos) and self.selectable:
return self.parent.select_with_touch(self.index, touch)
def apply_selection(self, rv, index, is_selected):
""" Respond to the selection of items in the view. """
self.selected = not is_selected
if is_selected:
rv.data[index].update({'color': (1, 1, 1, 1)})
self.refresh_view_attrs(RecycleViewWidget(), index, rv.data[index])
print("selection changed to {0}".format(rv.data[index]))
self.update_text_inputs()
else:
if rv.data[index].get("color") == (1, 1, 1, 1):
rv.data[index].update({'color': (0, 0, 0, 1)})
self.refresh_view_attrs(RecycleViewWidget(), index, rv.data[index])
self.selected = not self.selected
def update_text_inputs(self, *kwarg):
my_text_input = MyFirstScreen().ids.system_name_text_input_id#<--i can access to widget
print("my_print_val is:", my_text_input.text)#<--but widget's current text value is : ''
# my_text_input.text = "Updated Value"
main_style = Builder.load_file("test.kv")
class MyApp(App):
def __init__(self, **kwargs):
super().__init__(**kwargs)
def build(self):
return main_style
if __name__ == '__main__':
MyApp().run()
And my .kv code:
Manager:
MyFirstScreen:
<SelectableLabel>:
canvas.before:
Color:
rgba: (0, 0, 1, 1) if self.selected else (1, 1, 1, 1)
Rectangle:
pos: self.pos
size: self.size
<RecycleViewWidget>:
viewclass: 'SelectableLabel'
SelectableRecycleBoxLayout:
default_size: None, dp(56)
default_size_hint: 1, None
size_hint_y: None
height: self.minimum_height
orientation: 'vertical'
<MyFirstScreen>:
name: 'system_setup_page'
system_name_text_input_id:system_name_text_input_id
GridLayout:
cols: 2
BoxLayout:
cols: 1
padding: 20
RecycleViewWidget:
FloatLayout:
Label:
size_hint: None, None
text: "Name:"
font_size: 22
pos_hint: {'center': (20/100, 90/100)}
TextInput:
id: system_name_text_input_id
size_hint: None, None
hint_text: "Type Your Name..."
size: 200, 30
multiline: False
pos_hint: {'center': (65/100, 90/100)}
on_text: root.get_text_inputs()
Label:
size_hint: None, None
text: "User ID:"
font_size: 20
pos_hint: {'center': (20/100, 70/100)}
TextInput:
size_hint: None, None
size: 200, 30
hint_text: "Type Your ID..."
pos_hint: {'center': (65/100, 70/100)}
Problem is because using MyFirstScreen() in update_text_inputs() you create new instance of class MyFirstScreen but you have to use existing instance.
It should be better way to get it but at this moment my only idea is to use parent for this .
Because there are many widgets between these elements so it needs many parent:
my_text_input = self.parent.parent.parent.parent.parent.system_name_text_input_id
I found it using print(self.parent), next print(self.parent.parent), etc.
def update_text_inputs(self, *kwarg):
#print('parent:', self.parent.parent.parent.parent.parent.system_name_text_input_id)
#print('parent:', self.parent.parent.parent.parent.parent.system_name_text_input_id.text)
my_text_input = self.parent.parent.parent.parent.parent.system_name_text_input_id
print("my_print_val is:", my_text_input.text)
my_text_input.text = "Updated Value"
So, I'm trying to create a list that pulls from a mysql database that displays an order # as a button and a new window expands to display the order numbers items/subitems with checkboxes to have checked when an item is selected. I have the window to pop up; however, nothing populates and my query prints out information/list. After all boxes are checked and a Finish button is clicked on, it will remove the order from the list to show it has been worked on. I found this on the forums; however, it's not pulling anything for me:
How to fetch data from database and show in table in kivy+python
Thank you!
main.py
import pymysql
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.recycleview.views import RecycleDataViewBehavior
from kivy.uix.button import Button
from kivy.properties import BooleanProperty, ListProperty, StringProperty, ObjectProperty
from kivy.uix.recyclegridlayout import RecycleGridLayout
from kivy.uix.behaviors import FocusBehavior
from kivy.uix.recycleview.layout import LayoutSelectionBehavior
from kivy.uix.popup import Popup
orderNum = "1"
class TextInputPopup(Popup):
obj = ObjectProperty(None)
obj_text = StringProperty("")
def __init__(self, obj, **kwargs):
super(TextInputPopup, self).__init__(**kwargs)
self.obj = obj
self.obj_text = obj.text
class SelectableRecycleGridLayout(FocusBehavior, LayoutSelectionBehavior,
RecycleGridLayout):
''' Adds selection and focus behaviour to the view. '''
class SelectableButton(RecycleDataViewBehavior, Button):
''' Add selection support to the Button '''
index = None
selected = BooleanProperty(False)
selectable = BooleanProperty(True)
def refresh_view_attrs(self, rv, index, data):
''' Catch and handle the view changes '''
self.index = index
return super(SelectableButton, self).refresh_view_attrs(rv, index, data)
def on_touch_down(self, touch):
''' Add selection on touch down '''
if super(SelectableButton, self).on_touch_down(touch):
return True
if self.collide_point(*touch.pos) and self.selectable:
return self.parent.select_with_touch(self.index, touch)
def apply_selection(self, rv, index, is_selected):
''' Respond to the selection of items in the view. '''
self.selected = is_selected
def on_press(self):
popup = TextInputPopup(self)
popup.open()
def update_changes(self, txt):
self.text = txt
class RV(BoxLayout):
data_items = ListProperty([])
def __init__(self, **kwargs):
super(RV, self).__init__(**kwargs)
self.get_order()
def get_order(self):
connection = pymysql.connect(host='localhost', user='root',passwd='password', db='Shop')
cursor = connection.cursor()
cursor.execute("SELECT itemName, ITEM FROM order_list WHERE orderID=%s", (orderNum,))
rows = cursor.fetchall()
# create data_items
for row in rows:
for col in row:
self.data_items.append(col)
class TestApp(App):
title = "Kivy RecycleView & pymysql Demo"
def build(self):
return RV()
if __name__ == "__main__":
TestApp().run()
kivy.kv
#:kivy 1.10.0
<TextInputPopup>:
title: "Popup"
size_hint: None, None
size: 400, 400
auto_dismiss: False
BoxLayout:
orientation: "vertical"
TextInput:
id: txtinput
text: root.obj_text
Button:
size_hint: 1, 0.2
text: "Finish"
on_release:
root.obj.update_changes(txtinput.text)
root.dismiss()
Button:
size_hint: 1, 0.2
text: "Cancel Changes"
on_release: root.dismiss()
<SelectableButton>:
# Draw a background to indicate selection
canvas.before:
Color:
rgba: (.0, 0.9, .1, .3) if self.selected else (0, 0, 0, 1)
Rectangle:
pos: self.pos
size: self.size
<RV>:
BoxLayout:
orientation: "vertical"
GridLayout:
size_hint: 1, None
size_hint_y: None
height: 25
cols: 2
Label:
text: "Order Number"
BoxLayout:
RecycleView:
viewclass: 'SelectableButton'
data: [{'text': str(x)} for x in root.data_items]
SelectableRecycleGridLayout:
cols: 2
default_size: None, dp(26)
default_size_hint: 1, None
size_hint_y: None
height: self.minimum_height
orientation: 'vertical'
multiselect: True
touch_multiselect: True
Here's my list that pulls information and uses a print function:
('Sub', 'Italian')
('Sub', 'Meatball')
('Drink', 'Apple Juice')
('Side', 'Salad')
('Soup', 'Chicken and rice')
What I have and What I'm Trying to Achieve
menu.py
from kivy.app import App
from kivy.uix.dropdown import DropDown
from kivy.lang import Builder
class CustDrop(DropDown):
def __init__(self, **kwargs):
super(CustDrop, self).__init__( **kwargs)
self.select('')
kv_str = Builder.load_string('''
BoxLayout:
orientation: 'vertical'
BoxLayout:
canvas.before:
Rectangle:
pos: self.pos
size: self.size
Color:
rgb: (1,1,1)
size_hint_y:1
Button:
id: btn
text: 'user'
on_release: dropdown.open(self)
#size_hint_y: None
#height: '48dp'
CustDrop:
id: dropdown
Button:
text: 'List User'
size_hint_y: None
height: '48dp'
Label:
size_hint_x: 4
Label:
size_hint_y: 9
''')
class ExampleApp(App):
def build(self):
return kv_str
if __name__ =='__main__':
ExampleApp().run()
user.py
import kivy
kivy.require('1.9.0') # replace with your current kivy version !
import sqlite3 as lite
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import BooleanProperty, ListProperty, StringProperty, ObjectProperty,NumericProperty
from kivy.lang import Builder
from kivy.uix.recycleview.views import RecycleDataViewBehavior
from kivy.uix.button import Button
from kivy.uix.recyclegridlayout import RecycleGridLayout
from kivy.uix.behaviors import FocusBehavior
from kivy.uix.recycleview.layout import LayoutSelectionBehavior
from kivy.uix.popup import Popup
from kivy.core.window import Window
Window.size = (500, 500)
#con = lite.connect('user.db')
#con.text_factory = str
#cur = con.cursor()
class SelectableRecycleGridLayout(FocusBehavior, LayoutSelectionBehavior,
RecycleGridLayout):
''' Adds selection and focus behaviour to the view. '''
class SelectableButton(RecycleDataViewBehavior, Button):
''' Add selection support to the Button '''
index = None
selected = BooleanProperty(False)
selectable = BooleanProperty(True)
def refresh_view_attrs(self, rv, index, data):
''' Catch and handle the view changes '''
self.index = index
return super(SelectableButton, self).refresh_view_attrs(rv, index, data)
def on_touch_down(self, touch):
''' Add selection on touch down '''
if super(SelectableButton, self).on_touch_down(touch):
return True
if self.collide_point(*touch.pos) and self.selectable:
return self.parent.select_with_touch(self.index, touch)
def apply_selection(self, rv, index, is_selected):
''' Respond to the selection of items in the view. '''
self.selected = is_selected
def on_press(self,*args):
popup = TextInputPopup(self)
popup.open()
def update_changes(self):
self.text = txt
class RV(BoxLayout):
data_items = ListProperty([])
def __init__(self, **kwargs):
super(RV, self).__init__(**kwargs)
self.get_users()
def get_users(self):
# cur.execute("SELECT * FROM `users` order by id asc")
# rows = cur.fetchall()
rows = [(1, 'Yash', 'Chopra'),(2, 'amit', 'Kumar')]
for row in rows:
for col in row:
self.data_items.append(col)
class ListUser(App):
title = "Users"
def build(self):
self.root = Builder.load_file('user.kv')
return RV()
if __name__ == '__main__':
ListUser().run()
user.kv
#:kivy 1.10.0
<SelectableButton>:
# Draw a background to indicate selection
canvas.before:
Color:
rgba: (.0, 0.9, .1, .3) if self.selected else (0, 0, 0, 1)
Rectangle:
pos: self.pos
size: self.size
<RV>:
BoxLayout:
orientation: "vertical"
GridLayout:
size_hint: 1, None
size_hint_y: None
height: 25
cols: 3
Label:
text: "ID"
Label:
text: "First Name"
Label:
text: "Last Name"
BoxLayout:
RecycleView:
viewclass: 'SelectableButton'
data: [{'text': str(x)} for x in root.data_items]
SelectableRecycleGridLayout:
cols: 3
default_size: None, dp(26)
default_size_hint: 1, None
size_hint_y: None
height: self.minimum_height
orientation: 'vertical'
multiselect: True
touch_multiselect: True
I have two file menu.py and user.py. menu.py file show menu and user.py shows list of user..
when i run menu.py then shows user menu on top .When i click on user then 'list user' show(submenu of user).When i click on 'list user' then user list should show in current window.Menu will be on top and user-list show in same window(under menu).
To dsiplay the user list in the same window, combine both Python scripts and kv files into one. Please refer to the example below for details.
Example
mainmenu.py
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.dropdown import DropDown
from kivy.properties import BooleanProperty, ListProperty, StringProperty, ObjectProperty
from kivy.uix.recycleview.views import RecycleDataViewBehavior
from kivy.uix.button import Button
from kivy.uix.recyclegridlayout import RecycleGridLayout
from kivy.uix.behaviors import FocusBehavior
from kivy.uix.recycleview.layout import LayoutSelectionBehavior
from kivy.uix.popup import Popup
import sqlite3 as lite
dbPath = "/home/iam/dev/SQLite/sampleDB/ChinookDB/"
#con = lite.connect('user.db')
con = lite.connect(dbPath + "chinook.db")
#con.text_factory = str
cur = con.cursor()
class MessageBox(Popup):
obj = ObjectProperty(None)
obj_text = StringProperty("")
def __init__(self, obj, **kwargs):
super(MessageBox, self).__init__(**kwargs)
self.obj = obj
self.obj_text = obj.text
class SelectableRecycleGridLayout(FocusBehavior, LayoutSelectionBehavior,
RecycleGridLayout):
''' Adds selection and focus behaviour to the view. '''
class SelectableButton(RecycleDataViewBehavior, Button):
''' Add selection support to the Button '''
index = None
selected = BooleanProperty(False)
selectable = BooleanProperty(True)
def refresh_view_attrs(self, rv, index, data):
''' Catch and handle the view changes '''
self.index = index
return super(SelectableButton, self).refresh_view_attrs(rv, index, data)
def on_touch_down(self, touch):
''' Add selection on touch down '''
if super(SelectableButton, self).on_touch_down(touch):
return True
if self.collide_point(*touch.pos) and self.selectable:
return self.parent.select_with_touch(self.index, touch)
def apply_selection(self, rv, index, is_selected):
''' Respond to the selection of items in the view. '''
self.selected = is_selected
def on_press(self):
popup = MessageBox(self)
popup.open()
def update_changes(self, txt):
self.text = txt
class RV(BoxLayout):
data_items = ListProperty([])
def __init__(self, **kwargs):
super(RV, self).__init__(**kwargs)
self.get_users()
def get_users(self):
cur.execute("SELECT CustomerId, FirstName, LastName FROM 'customers' order by CustomerId asc")
rows = cur.fetchall()
for row in rows:
for col in row:
self.data_items.append(col)
class CustDrop(DropDown):
def __init__(self, **kwargs):
super(CustDrop, self).__init__(**kwargs)
self.select('')
class MainMenu(BoxLayout):
users = ObjectProperty(None)
dropdown = ObjectProperty(None)
def display_users(self):
# rv = RV()
self.dropdown.dismiss()
self.users.add_widget(RV())
class MainMenuApp(App):
title = "Example"
def build(self):
return MainMenu()
if __name__ == '__main__':
MainMenuApp().run()
mainmenu.kv
#:kivy 1.10.0
<MessageBox>:
title: "Popup"
size_hint: None, None
size: 400, 400
auto_dismiss: False
BoxLayout:
orientation: "vertical"
TextInput:
id: txtinput
text: root.obj_text
Button:
size_hint: 1, 0.2
text: "Save Changes"
on_release:
root.obj.update_changes(txtinput.text)
root.dismiss()
Button:
size_hint: 1, 0.2
text: "Cancel Changes"
on_release: root.dismiss()
<SelectableButton>:
# Draw a background to indicate selection
canvas.before:
Color:
rgba: (.0, 0.9, .1, .3) if self.selected else (0, 0, 0, 1)
Rectangle:
pos: self.pos
size: self.size
<RV>:
BoxLayout:
orientation: "vertical"
GridLayout:
size_hint: 1, None
size_hint_y: None
height: 25
cols: 3
Label:
text: "ID"
Label:
text: "First Name"
Label:
text: "Last Name"
BoxLayout:
RecycleView:
viewclass: 'SelectableButton'
data: [{'text': str(x)} for x in root.data_items]
SelectableRecycleGridLayout:
cols: 3
default_size: None, dp(26)
default_size_hint: 1, None
size_hint_y: None
height: self.minimum_height
orientation: 'vertical'
multiselect: True
touch_multiselect: True
<MainMenu>:
users: users
dropdown: dropdown
orientation: 'vertical'
BoxLayout:
canvas.before:
Rectangle:
pos: self.pos
size: self.size
Color:
rgb: (1,1,1)
size_hint_y:1
Button:
id: btn
text: 'user'
on_release: dropdown.open(self)
CustDrop:
id: dropdown
Button:
text: 'List User'
size_hint_y: None
height: '48dp'
on_release: root.display_users()
Label:
size_hint_x: 4
text: "label 1"
BoxLayout:
id: users
size_hint_y: 9
Output