Search code examples
pythonpython-3.xkivykivy-languagekivymd

how to aolve "The screen only shows a blank purple screen" issue?


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


Solution

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