I've based this section of my code on the documentation and information from other posts here such as:
How to fetch data from database and show in table in kivy+python
The goal is to have a scrolling word list with just the words as selectable buttons and when you click on the button the word, pronunciation, and translation should be presented in a popup. All of this is pulled from rows in a sqlite database that is constantly updating.
I have it mostly working but the one thing I cannot figure out how to do is to separate the data, which is in the form of a dictionary of strings, to display just the word (column 1) in the list and all of the information (columns 1, 2, and 3) in the popup. I also do not want to have to iterate through the entire dictionary because although the sample db here only has 8 items in it, the real one has thousands. I would like the information to be pulled from the db when I click on the selectable button.
Is there away to either pull the text from the individual rows from the following code-
data: [{'text': f'{entry[0], entry[1], entry[2]}'} for entry in root.rows]
or set the data separately as variables and use those-
data: [{'text': f'{entry[0]}'} for entry in root.rows]
data2: [{'text': f'{entry[1]}'} for entry in root.rows]
data3: [{'text': f'{entry[2]}'} for entry in root.rows]
Is there some other way of doing this that I am missing?
Another issue I am having is that the text on the selectable buttons are being shown twice - on the button and also underneath (you can see it when you shrink the window) and I don't know why or how to fix it.
Any help is appreciated, thanks.
minimum code with databases: https://github.com/nitro9a/word_a_day_minimum
app.py:
import csv
import sqlite3
import random
import textwrap
from utils import database, scalelabel, scrollablelabel, recycleselect
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.label import Label
from kivy.uix.widget import Widget
from kivy.uix.button import Button
from kivy.uix.recycleview import RecycleView
from kivy.uix.relativelayout import RelativeLayout
from kivy.uix.recycleboxlayout import RecycleBoxLayout
from kivy.uix.recycleview.views import RecycleDataViewBehavior
from kivy.uix.recycleview.layout import LayoutSelectionBehavior
from kivy.uix.behaviors import FocusBehavior
from kivy.uix.popup import Popup
from kivy.uix.screenmanager import ScreenManager, Screen, NoTransition
from kivy.properties import BooleanProperty, ListProperty, ObjectProperty, StringProperty
word_dict = {}
class MessageBox(Popup):
def popup_dismiss(self):
self.dismiss()
obj = ObjectProperty(None)
obj_text = StringProperty('')
def __init__(self, obj, **kwargs):
super(MessageBox, self).__init__(**kwargs)
self.obj = obj
self.obj_text = obj.text #what is in the message box, will display same on click
class SelectableRecycleBoxLayout(FocusBehavior, LayoutSelectionBehavior, RecycleBoxLayout):
""" Adds selection and focus behaviour to the view. """
class SelectableButton(RecycleDataViewBehavior, Button):
""" 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
print(type(data))
#print(f'Data: {data.items()}, Index: {index},rv: {rv}, Type: {type(data)}')
return super(SelectableButton, self).refresh_view_attrs(rv, index, data)
def apply_selection(self, rv, index, is_selected):
self.selected = is_selected
def on_press(self):
popup = MessageBox(self)
popup.open()
def update_changes(self, txt):
self.text = txt
class RV(RecycleView):
#data_items = ListProperty([])
def __init__(self, **kwargs):
super(RV, self).__init__(**kwargs)
class WindowManager(ScreenManager):
pass
class UnreadWords(Screen):
unread_table = ObjectProperty(None)
rows = ListProperty([("Word", "Pronunciation", "English")])
def __init__(self, **kwargs):
super(UnreadWords, self).__init__(**kwargs)
def display_database(self):
con = sqlite3.connect('italian_unread.db')
cursor = con.cursor()
cursor.execute("SELECT Word, Pronunciation, English from Italian_a")
self.rows = cursor.fetchall()
kv = Builder.load_file("layout.kv")
class WordApp(App):
def build(self):
return kv
if __name__=="__main__":
WordApp().run()
layout.kv:
#: import NoTransition kivy.uix.screenmanager.NoTransition
#: include italian_a
<RV>:
viewclass: 'SelectableButton'
RecycleBoxLayout:
bcolor: 1,1,1,1
padding: "15dp", "5dp", "15dp", "15dp"
default_size: None, dp(25)
default_size_hint: 1, None
size_hint_y: None
height: self.minimum_height
orientation: 'vertical'
<SelectableButton>:
state_image: self.background_normal if self.state == 'normal' else self.background_down
disabled_image: self.background_disabled_normal if self.state == 'normal' else self.background_disabled_down
_scale: 1. if self.texture_size[0] < self.width else float(self.width) / self.texture_size[0]
orientation: 'horizontal'
canvas:
Color:
rgba: self.background_color
BorderImage:
border: self.border
pos: self.pos
size: self.size
source: self.disabled_image if self.disabled else self.state_image
PushMatrix
Scale:
origin: self.center
x: self._scale or 1.
y: self._scale or 1.
Color:
rgba: self.disabled_color if self.disabled else self.color
Rectangle:
texture: self.texture
size: self.texture_size
pos: int(self.center_x - self.texture_size[0] / 2.), int(self.center_y - self.texture_size[1] / 2.)
PopMatrix
<MessageBox>:
name: 'mbox'
lbl: lbl
title: ''
size_hint: None, None
size: 400, 400
on_open:
root.obj.update_changes(lbl.text)
BoxLayout:
orientation: 'vertical'
Label:
id: lbl
text: root.obj_text
Button:
size_hint: 1, 0.2
text: 'OK'
on_press:
root.dismiss()
WindowManager:
transition: NoTransition()
UnreadWords:
<UnreadWords>:
name: "unread"
unread_table: unread_table
BoxLayout:
orientation: "vertical"
rows: 4
cols: 1
GridLayout:
cols: 2
rows: 1
size_hint_y: 5
ScaleButton:
id: page2
text: "Page 2"
on_release:
app.root.current = "unread"
root.display_database()
GridLayout:
cols: 1
rows: 1
size_hint_y: 5
ScaleLabel:
text: "Unread Words"
size_hint_y: 5
color: (0/255., 0/255., 0/255., 1)
background_normal: ''
bcolor: (155/255., 155/255., 155/255., 1)
GridLayout:
cols: 1
rows: 1
size_hint_y: 80
BoxLayout:
id: unread_table
RV:
id: dat
viewclass: 'SelectableButton'
size_hint_y: 1
font_size: self.height * 0.5
data: [{'text': f'{entry[0], entry[1], entry[2]}'} for entry in root.rows]
#data: [{'text': f'{entry[0]}'} for entry in root.rows]