From e21a5757ee3545199da0f42df69ae2355b18208a Mon Sep 17 00:00:00 2001 From: yumoqing Date: Sat, 27 Mar 2021 14:04:10 +0800 Subject: [PATCH] bugfix --- kivyblocks/baseWidget.py | 45 +++++---------------------- kivyblocks/blocks.py | 7 +++-- kivyblocks/blocksapp.py | 1 + kivyblocks/dataloader.py | 4 ++- kivyblocks/dg.py | 53 ++++++++++++++------------------ kivyblocks/markdown.py | 16 +++++----- kivyblocks/orientationlayout.py | 6 ++-- kivyblocks/ready.py | 21 +++++-------- kivyblocks/toggleitems.py | 48 +++++++++++++++++++---------- kivyblocks/toolbar.py | 40 +++++++++++------------- kivyblocks/widgetExt/messager.py | 9 ++++-- kivyblocks/widget_css.py | 35 +++++++++++++++++++-- 12 files changed, 147 insertions(+), 138 deletions(-) diff --git a/kivyblocks/baseWidget.py b/kivyblocks/baseWidget.py index 7b900dd..6592407 100755 --- a/kivyblocks/baseWidget.py +++ b/kivyblocks/baseWidget.py @@ -73,6 +73,8 @@ from .tab import TabsPanel from .qrdata import QRCodeWidget from .threadcall import HttpClient from .i18n import I18n +from .widget_css import WidgetCSS +from .ready import WidgetReady from .utils import CSize if platform == 'android': @@ -85,40 +87,9 @@ class WrapText(Label): self.bind(width=lambda *x: self.setter('text_size')(self, (self.width, None)), texture_size=lambda *x: self.setter('height')(self, self.texture_size[1])) -class Box(BGColorBehavior, BoxLayout): - def __init__(self,color_level=-1,radius=[],**kw): - BoxLayout.__init__(self, **kw) - BGColorBehavior.__init__(self, color_level=color_level, - radius=radius) - - def add_widget(self, w, *args, **kw): - super().add_widget(w, *args, **kw) - self.setWidgetTextColor(w) - - def setWidgetTextColor(self,w): - if isinstance(w,Box): - return - - if isinstance(w,Text): - if not w.bgcolor: - w.color = self.fgcolor - return - for c in w.children: - self.setWidgetTextColor(c) - - def selected(self): - super().selected() - if self.fgcolor == self.selected_fgcolor: - return - for c in self.children: - self.setWidgetTextColor(c) - - def unselected(self): - super().unselected() - if self.fgcolor == self.normal_fgcolor: - return - for c in self.children: - self.setWidgetTextColor(c) +class Box(WidgetCSS, WidgetReady, BoxLayout): + def __init__(self, **kw): + super(Box, self).__init__(**kw) class HBox(Box): def __init__(self,**kw): @@ -239,11 +210,9 @@ class Title6(Text): kw.update({'texttype':'title6','bold':True}) Text.__init__(self, **kw) -class Modal(BGColorBehavior, ModalView): - def __init__(self, auto_open=False, color_level=-1, radius=[], **kw): +class Modal(ModalView): + def __init__(self, auto_open=False, **kw): ModalView.__init__(self, **kw) - BGColorBehavior.__init__(self, color_level=color_level, - radius=radius) self.auto_open = auto_open def add_widget(self,w, *args, **kw): diff --git a/kivyblocks/blocks.py b/kivyblocks/blocks.py index 066328a..801a38b 100755 --- a/kivyblocks/blocks.py +++ b/kivyblocks/blocks.py @@ -51,6 +51,7 @@ def wrap_ready(klass): Factory.unregister(klass) globals()[klass] = w except: + print_exc() w = globals().get(klass) if w is None: return None @@ -222,6 +223,7 @@ class Blocks(EventDispatcher): # print('Blocks.py :resp=',resp) return resp except Exception as e: + print_exc() if errback: return errback(None,e) return None @@ -598,9 +600,10 @@ class Blocks(EventDispatcher): widget = self.w_build(desc) self.dispatch('on_built',widget) if hasattr(widget,'ready'): - widget.ready() + widget.ready = True return widget except Exception as e: + print_exc() self.dispatch('on_failed',e) return None @@ -643,7 +646,6 @@ class Blocks(EventDispatcher): @classmethod def getWidgetById(self,id,from_widget=None): - print('getWidgetById(%s,%s) ...' % (id, from_widget)) def find_widget_by_id(id, from_widget): if id=='self': return from_widget @@ -694,7 +696,6 @@ class Blocks(EventDispatcher): if from_widget is None: from_widget = app.root for id in ids: - print('finding', id) w = find_widget_by_id(id,from_widget=from_widget) if w is None \ and id == ids[0] \ diff --git a/kivyblocks/blocksapp.py b/kivyblocks/blocksapp.py index 2f2243a..71fc23c 100644 --- a/kivyblocks/blocksapp.py +++ b/kivyblocks/blocksapp.py @@ -109,6 +109,7 @@ class BlocksApp(App): hc = HttpClient() d = hc.get(self.realurl(config.css.css_url)) self.buildCsses(d) + Logger.info('blocksapp: csses=%s', self.csses) def buildCsses(self, dic): for k,v in dic.items(): diff --git a/kivyblocks/dataloader.py b/kivyblocks/dataloader.py index 49a3f82..8cb697a 100644 --- a/kivyblocks/dataloader.py +++ b/kivyblocks/dataloader.py @@ -1,5 +1,6 @@ from kivy.event import EventDispatcher +from kivy.app import App from .threadcall import HttpClient from .utils import absurl from appPublic.registerfunction import RegisterFunction @@ -125,7 +126,8 @@ class DataLoader(EventDispatcher): class HttpDataLoader(DataLoader): def load(self, *args, **kw): - url = absurl(self.data_user.url,self.data_user.target.parenturl) + app = App.get_running_app() + url = app.realurl(self.data_user.url) method = self.data_user.method params = self.data_user.params.copy() params.update({ diff --git a/kivyblocks/dg.py b/kivyblocks/dg.py index 8d02194..830dce6 100644 --- a/kivyblocks/dg.py +++ b/kivyblocks/dg.py @@ -6,7 +6,7 @@ from kivy.uix.scrollview import ScrollView from kivy.uix.label import Label from kivy.uix.button import ButtonBehavior from kivy.clock import Clock -from kivy.properties import BooleanProperty +from kivy.properties import BooleanProperty, StringProperty from kivy.properties import ListProperty from kivy.graphics import Color, Rectangle from kivy.app import App @@ -112,8 +112,8 @@ class Cell(BoxLayout): def cell_press(self,obj): self.row.selected() -class Row(GridLayout): - def __init__(self,part, rowdesc,header=False,data=None): +class Row(WidgetCSS, GridLayout): + def __init__(self,part, rowdesc,header=False,data=None, **kw): """ rowdesc=[ { @@ -130,8 +130,12 @@ class Row(GridLayout): self.row_id = None self.linewidth = 1 self.rowdesc = rowdesc - super().__init__(cols=len(self.rowdesc),spacing=self.linewidth) - self.spacing = 2 + opts = kw.copy() + opts.update({ + "cols":len(self.rowdesc), + "spacing":2 + }) + super(Row, self).__init__(**opts) # Clock.schedule_once(self.init,0) self.init(0) @@ -159,10 +163,10 @@ class Row(GridLayout): self.part.datagrid.select_row = self self.part.datagrid.dispatch('on_selected',self) -class Header(ScrollWidget, WidgetReady, WidgetCSS): - def __init__(self,part,color_level=-1,**kw): - self.part = part +class Header(WidgetReady, ScrollWidget): + def __init__(self,part,**kw): super(Header, self).__init__(**kw) + self.part = part self.init(1) self.bind(on_scroll_stop=self.part.datagrid.on_scrollstop) if self.part.freeze_flag: @@ -173,11 +177,11 @@ class Header(ScrollWidget, WidgetReady, WidgetCSS): [ f.update({'value':self.part.fields[i].get('label', \ self.part.fields[i].get('name'))}) \ for i,f in enumerate(rd) ] - self.header = Row(self.part,rd,header=True) + self.header = Row(self.part,rd,header=True, csscls=self.part.datagrid.header_css) self.add_widget(self.header) self.height = self.header.height -class Body(ScrollWidget, WidgetReady, WidgetCSS): +class Body(WidgetReady, ScrollWidget): def __init__(self,part,**kw): self.part = part super(Body, self).__init__(**kw) @@ -189,7 +193,7 @@ class Body(ScrollWidget, WidgetReady, WidgetCSS): def addRow(self,id, data,index=0): rd = [ f.copy() for f in self.part.rowdesc ] [ f.update({'value':data.get(f['name'])}) for f in rd ] - row = Row(self.part,rd,data=data) + row = Row(self.part,rd,data=data, csscls=self.part.datagrid.body_css) row.row_id = id self.add_widget(row,index=index) self.idRow[id] = row @@ -220,7 +224,6 @@ class DataGridPart(WidgetReady, BoxLayout): self.fields_width = None BoxLayout.__init__(self, orientation='vertical') WidgetReady.__init__(self) - # Clock.schedule_once(self.init,0.1) self.init(0) def setWidth(self): @@ -250,7 +253,6 @@ class DataGridPart(WidgetReady, BoxLayout): kw['size_hint'] = (None,None) else: kw['size_hint'] = (1,None) - kw['height'] = self.datagrid.rowHeight() if not self.datagrid.noheader: @@ -269,7 +271,7 @@ class DataGridPart(WidgetReady, BoxLayout): return self.body.addRow(id, data) -class DataGrid(WidgetReady, BGColorBehavior, BoxLayout): +class DataGrid(WidgetReady, BoxLayout): """ DataGrid data format: { @@ -303,28 +305,19 @@ class DataGrid(WidgetReady, BGColorBehavior, BoxLayout): ] } """ + header_css = StringProperty(None) + body_css = StringProperty(None) + noheader = BooleanProperty(False) row_selected = BooleanProperty(False) - def __init__(self,color_level=-1,radius=[],**options): - kw = DictObject() - kw = setSizeOptions(options, kw) - kw.orientation = 'vertical' - self.color_level = color_level - self.radius = radius - self.select_rowid = None + def __init__(self,**options): + options['orientation'] = 'vertical' + BoxLayout.__init__(self) WidgetReady.__init__(self) - BoxLayout.__init__(self,**kw) - BGColorBehavior.__init__(self,color_level=color_level, - radius=radius) - self.parenturl = options.get('parenturl',None) + self.select_rowid = None self.options = options - self.noheader = options.get('noheader',False) - self.header_bgcolor = options.get('header_bgcolor',[0.29,0.29,0.29,1]) - self.body_bgcolor = options.get('body_bgcolor',[0.25,0.25,0.25,1]) - self.color = options.get('color',[0.91,0.91,0.91,1]) self.row_height = None self.on_sizeTask = None self.selected_rowid = None - self.dataUrl = self.options.get('dataurl') self.show_rows = 0 self.toolbar = None self.freeze_part = None diff --git a/kivyblocks/markdown.py b/kivyblocks/markdown.py index 1a91457..40f3953 100644 --- a/kivyblocks/markdown.py +++ b/kivyblocks/markdown.py @@ -7,6 +7,7 @@ from kivy.uix.label import Label from kivy.uix.image import AsyncImage from .baseWidget import ScrollWidget, getDataHandler, VBox + from .utils import CSize import re @@ -220,9 +221,8 @@ class MarkdownBody(VBox): Logger.info('resize:parent is null') def build_source(self,source_desc): - color_level = self.color_level+1 w = MarkdownBody(md_obj=self.md_obj, - color_level=color_level,size_hint_y=None) + csscls=md_obj.second_css, size_hint_y=None) w.show_mdtext(source_desc) self.add_widget(w) w.resize() @@ -386,17 +386,19 @@ description file format "widgettype":"Markdown", "options":{ "source": the markdown file + "first_css":, + "second_css": other options } } """ source = StringProperty(None) - - def __init__(self, color_level=0, **kw): - self.color_level = color_level - ScrollView.__init__(self, **kw) + first_css = StringProperty("default") + second_css = StringProperty("default") + def __init__(self, **kw): + ScrollView.__init__(self) self.root_body = MarkdownBody(md_obj=self, - color_level=color_level, + csscls=self.first_css, size_hint_y=None ) self.root_body.bind(minimum_height=self.root_body.setter('height')) diff --git a/kivyblocks/orientationlayout.py b/kivyblocks/orientationlayout.py index 8422e01..5326123 100644 --- a/kivyblocks/orientationlayout.py +++ b/kivyblocks/orientationlayout.py @@ -6,7 +6,7 @@ from kivy.clock import Clock from kivyblocks.swipebehavior import SwipeBehavior from kivyblocks.ready import WidgetReady -class OrientationLayout(WidgetReady, SwipeBehavior, FloatLayout): +class OrientationLayout(FloatLayout, WidgetReady, SwipeBehavior): """ TwinStyleLayout layout two widget verical when parital orientation and second widget hide when it is in landscape @@ -17,9 +17,7 @@ class OrientationLayout(WidgetReady, SwipeBehavior, FloatLayout): self.widget_main = None self.widget_second = None self.second_flg = False - FloatLayout.__init__(self, **kw) - SwipeBehavior.__init__(self) - WidgetReady.__init__(self) + super(OrientationLayout, self).__init__(**kw) self.build_children() self.bind(on_swipe_left=self.toggle_second) self.bind(on_swipe_right=self.toggle_second) diff --git a/kivyblocks/ready.py b/kivyblocks/ready.py index 2954850..43f7f1c 100644 --- a/kivyblocks/ready.py +++ b/kivyblocks/ready.py @@ -1,4 +1,5 @@ from kivy.core.window import Window +from kivy.clock import Clock from kivy.utils import platform from kivy.app import App from kivy.properties import BooleanProperty @@ -11,24 +12,18 @@ desktopOSs=[ class WidgetReady(object): fullscreen = BooleanProperty(False) + ready = BooleanProperty(False) + _fullscreen = False - def __init__(self, **kw): - self.register_event_type('on_ready') - self._fullscreen_state = False - self._ready = False - - def on_ready(self): + def on_ready(self, *args): pass - def ready(self): - if self._ready: - return - self.dispatch('on_ready') - self._ready = True + def set_ready(self, *args): + self.ready = True def reready(self): - self._ready = False - self.ready() + self.ready = False + Clock.schedule_once(self.set_ready, 0.1) def use_keyboard(self): self.my_kb = Window.request_keyboard(None, self) diff --git a/kivyblocks/toggleitems.py b/kivyblocks/toggleitems.py index 499a3b2..c9181ca 100644 --- a/kivyblocks/toggleitems.py +++ b/kivyblocks/toggleitems.py @@ -1,35 +1,47 @@ from functools import partial +from kivy.logger import Logger from kivy.uix.behaviors import TouchRippleButtonBehavior from kivy.graphics import Color, Rectangle from kivy.uix.boxlayout import BoxLayout from kivy.factory import Factory +from kivy.properties import ObjectProperty, StringProperty, BooleanProperty from kivyblocks.ready import WidgetReady from kivyblocks.bgcolorbehavior import BGColorBehavior from kivyblocks.utils import CSize from kivyblocks.baseWidget import Box +from kivyblocks.widget_css import WidgetCSS class PressableBox(TouchRippleButtonBehavior, Box): + normal_css = StringProperty("default") + actived_css = StringProperty("default") + box_actived = BooleanProperty(False) def __init__(self,border_width=1, color_level=-1, user_data=None, radius=[], **kw): - Box.__init__(self, padding=[border_width, + super(PressableBox, self).__init__( + padding=[border_width, border_width, border_width, border_width], - color_level=color_level, radius=radius, **kw) - TouchRippleButtonBehavior.__init__(self) self.border_width = border_width self.user_data = user_data - self.unselected() + self.actived = False + self.csscls = self.normal_css + + def on_box_actived(self, o, v): + if self.box_actived: + self.csscls = self.actived_css + else: + self.csscls = self.normal_css def on_press(self,o=None): - print('on_press fired') - self.selected() + self.box_actived = True + def setValue(self,d): self.user_data = d @@ -48,7 +60,7 @@ ToggleItems format: orientation: } """ -class ToggleItems(BGColorBehavior, BoxLayout): +class ToggleItems(BoxLayout, WidgetCSS): def __init__(self, color_level=1, radius=[], @@ -56,6 +68,8 @@ class ToggleItems(BGColorBehavior, BoxLayout): unit_size=3, items_desc=[], border_width=1, + normal_css="default", + actived_css="default", **kw): self.unit_size_pix = CSize(unit_size) kw1 = { @@ -72,13 +86,11 @@ class ToggleItems(BGColorBehavior, BoxLayout): kw1['size_hint_min_y'] = self.unit_size_pix BoxLayout.__init__(self, **kw1) - BGColorBehavior.__init__(self, - color_level=color_level, - radius=radius) self.item_widgets = [] kw = { "border_width":border_width, - "color_level":color_level, + "normal_css":normal_css, + "actived_css":actived_css, "radius":radius } kw.update(kw1) @@ -101,7 +113,7 @@ class ToggleItems(BGColorBehavior, BoxLayout): b.widgetBuild(desc) if len(self.item_widgets) > 0: - self.item_widgets[0].selected() + self.item_widgets[0].actived = True else: print('items_desc=',items_desc,'error') self.register_event_type('on_press') @@ -111,19 +123,23 @@ class ToggleItems(BGColorBehavior, BoxLayout): pass def select_item(self,o=None): - [i.unselected() for i in self.item_widgets if i != o] + for i in self.item_widgets: + if i!=o: + i.box_actived = False + self.dispatch('on_press',o.getValue()) def getValue(self): for i in self.item_widgets: - if i.is_selected(): + if i.actived: return i.getValue() return None def setValue(self,v): for i in self.item_widgets: if i.getValue() == v: - i.selected() + i.actived = True self.select_item(i) - return + else: + i.actived = False diff --git a/kivyblocks/toolbar.py b/kivyblocks/toolbar.py index 530e053..05a7623 100644 --- a/kivyblocks/toolbar.py +++ b/kivyblocks/toolbar.py @@ -9,6 +9,7 @@ from kivy.uix.widget import Widget from kivy.app import App from kivy.clock import Clock from kivy.factory import Factory +from kivy.properties import StringProperty from appPublic.dictObject import DictObject from appPublic.registerfunction import RegisterFunction @@ -17,14 +18,12 @@ from .widgetExt.scrollwidget import ScrollWidget from .utils import * from .ready import WidgetReady from .color_definitions import getColors -from .bgcolorbehavior import BGColorBehavior -from .baseWidget import Text -from .toggleitems import PressableBox, ToggleItems +from .baseWidget import Text, Box +from .toggleitems import ToggleItems """ toolbar options { - color_level: radius: "mode":"icon", "icontext","text" img_size=1.5, @@ -39,19 +38,21 @@ toolbar options ] } """ -class Toolbar(BoxLayout): - def __init__(self, color_level=-1, +class Toolbar(Box): + def __init__(self, radius=[], img_size=1.5, text_size=0.5, - tools=[], **opts): - self.color_level = color_level + tools=[], + normal_css="default", + actived_css="default", + **opts): self.radius = radius self.img_size = img_size self.text_size = text_size self.tools = tools self.tool_widgets={} - BoxLayout.__init__(self, **opts) + Box.__init__(self, **opts) self.register_event_type('on_press') first = True subs_desc = [] @@ -89,11 +90,12 @@ class Toolbar(BoxLayout): subs_desc.append(desc) self.toggle_items = ToggleItems( - color_level=self.color_level, radius=self.radius, unit_size=self.img_size + self.text_size, items_desc=subs_desc, - orientation=opts.get('orientation','horizontal') + normal_css=normal_css, + actived_css=actived_css, + **opts ) for ti in self.toggle_items.item_widgets: ti.widget_id = ti.user_data @@ -112,7 +114,6 @@ Toolpage options img_size:1.5, text_size:0.7, tool_at:"left","right","top","bottom", - color_level:0, radius: "show_name":"default open tool's name" tools:[ @@ -128,8 +129,10 @@ Toolpage options ] """ -class ToolPage(BGColorBehavior, BoxLayout): - def __init__(self,color_level=-1,radius=[], +class ToolPage(BoxLayout): + normal_css=StringProperty(None) + actived_css=StringProperty(None) + def __init__(self,radius=[], toolbar_size=None, img_size=1.5, text_size=0.7, @@ -151,13 +154,9 @@ class ToolPage(BGColorBehavior, BoxLayout): self.content_widgets = {} self.show_name = show_name - self.color_level=self.opts.color_level or 0 self.sub_radius = self.opts.radius self.tool_at = tool_at BoxLayout.__init__(self,orientation=orient) - BGColorBehavior.__init__(self, - color_level=color_level, - radius=[]) self.content = None self.toolbar = None self.init() @@ -165,9 +164,6 @@ class ToolPage(BGColorBehavior, BoxLayout): Clock.schedule_once(self.show_page, 0.5) def show_page(self, *args): - print('toolbar=',self.toolbar.width,self.toolbar.height, \ - 'toggleitems=',self.toolbar.toggle_items.width, \ - self.toolbar.toggle_items.height) toggle_items = self.toolbar.toggle_items for c in toggle_items.item_widgets: cvalue = c.getValue() @@ -202,7 +198,7 @@ class ToolPage(BGColorBehavior, BoxLayout): opts['size_hint_x'] = None opts['width'] = CSize(self.toolbar_size) opts['orientation'] = 'vertical' - self.toolbar = Toolbar(color_level=self.color_level, + self.toolbar = Toolbar( radius=self.sub_radius, img_size=self.img_size, text_size=self.text_size, diff --git a/kivyblocks/widgetExt/messager.py b/kivyblocks/widgetExt/messager.py index 698cd56..b07582c 100644 --- a/kivyblocks/widgetExt/messager.py +++ b/kivyblocks/widgetExt/messager.py @@ -2,15 +2,20 @@ from kivy.uix.popup import Popup from kivy.clock import Clock from kivy.uix.boxlayout import BoxLayout from kivy.uix.textinput import TextInput +from ..widget_css import WidgetCSS +class MyPopup(WidgetCSS, Popup): + def __init__(self,content=None, title='', **kw): + super(MyPopup, self).__init__(content=content, + title=title, **kw) class Messager: - def __init__(self, show_time=0, title=None): + def __init__(self, show_time=0, title=None, **kw): self.show_time = show_time self.title = title if title else 'Message' self.time_task = None self.w = Popup(content=BoxLayout(orientation='vertical'), title=self.title, - size_hint=(0.8,0.8)) + size_hint=(0.8,0.8), **kw) self.messager = TextInput(size=self.w.content.size, multiline=True,readonly=True) self.w.content.add_widget(self.messager) diff --git a/kivyblocks/widget_css.py b/kivyblocks/widget_css.py index 6262bdb..56f7f25 100644 --- a/kivyblocks/widget_css.py +++ b/kivyblocks/widget_css.py @@ -1,3 +1,4 @@ +from kivy.logger import Logger from kivy.properties import NumericProperty, ListProperty, StringProperty from kivy.graphics import Color, Rectangle, RoundedRectangle from kivy.uix.textinput import TextInput @@ -13,11 +14,17 @@ class WidgetCSS(object): width_cm = NumericProperty(None) bgcolor = ListProperty(None) fgcolor = ListProperty(None) - csscls = StringProperty(None) + csscls = StringProperty("default") radius = ListProperty(None) background_rec = None bg_func = Rectangle + def on_size(self, o, s): + self.set_background_color() + + def on_pos(self, o, p): + self.set_background_color() + def on_height_nm(self, o, v): if not self.height_nm: return @@ -60,6 +67,24 @@ class WidgetCSS(object): self.size_hint_x = None self.width = CSize(self.width_cm) + def set_child_fgcolor(self, c): + if not hasattr(c,'fgcolor'): + return + if c.fgcolor: + return + if isinstance(c, TextInput): + c.foreground_color = self.fgcolor + return + if isinstance(c, Label): + c.color = self.fgcolor + return + for x in c.children: + self.set_child_fgcolor(x) + + def on_children(self, o, c): + for c in self.children: + self.set_child_fgcolor(c) + def on_fgcolor(self, o, c): if not self.fgcolor: return @@ -68,6 +93,8 @@ class WidgetCSS(object): if isinstance(self, Label): self.color = self.fgcolor return + for c in self.children: + self.set_child_fgcolor(c) return def on_bgcolor(self, o, c): @@ -82,7 +109,7 @@ class WidgetCSS(object): self.set_background_color() def on_radius(self, o, r): - if not radius: + if not self.radius: self.bg_func = Rectangle return self.bg_func = RoundedRectangle @@ -90,8 +117,12 @@ class WidgetCSS(object): def set_background_color(self, *args): if not self.bgcolor: + Logger.info('WidgetCSS: set_bg_color(), bgcolor is null, (%s)', + self.__class__.__name__) return if not self.canvas: + Logger.info('WidgetCSS: set_bg_color(), canvas is null(%s)', + self.__class__.__name__) return with self.canvas.before: