Kivy window set_title changes back to main file name - kivy

When I set the window title, the title is set back to it's corresponding file name.
class myniceApp(App):
global Window
def build(self):
Window.clearcolor = (.95,.95,.95,1)
Window.size = (1024, 768)
Window.set_title('mykivyapp')
Builder.load_string(style)
homewin = MyniceappHome()
homewin.initapp()
return homewin
myniceApp().run()
In the above example, the title 'mykivyapp' is shown initially but set back to the filename after homewin.initapp()
How should set_title() be used?

Window title is set with App.title, not with Window directly:
class MyApp(App):
def build(self):
self.title = 'Hello world'

you can use it like below.. this one worked for me.. i tried the first solution explained above, but it did not work.. so i change a bit and put the title outside the build function, its working successfully..
class controllerApp(App):
title = 'Vehicle Detection System'
def build(self, video_source=VIDEO_SOURCE):
...
...

Related

KIVY "[CRITICAL] [Clock ] Warning" on_touch_move

I have written a small code to drag widget horizontally using on_touch_move event. Even my widget moves horizontally. But when I am dragging the widget, following log gets generated."[CRITICAL] [Clock ] Warning, too much iteration done before the next frame. Check your code, or increase the Clock.max_iteration attribute".
Please find below my sample code. To reproduce this scenario, just drag the white widget right and left. The above log messages gets printed.
from kivy.app import App
from kivy.graphics import Rectangle
from kivy.uix.scatter import Scatter
from kivy.uix.relativelayout import RelativeLayout
class MyPaintWidget(Scatter):
def __init__(self, **kwargs) :
super(MyPaintWidget, self).__init__(**kwargs)
def on_touch_move(self, touch):
touch_x_hint = touch.x / self.parent.size[0]
self.pos_hint = {'center_x': touch_x_hint }
return super(Scatter, self).on_touch_move(touch)
class MyPaintApp(App):
def build(self):
parent = RelativeLayout()
Wdgt = MyPaintWidget(pos_hint={'center_x':0.5, 'center_y':0.5}, size_hint=(0.2,0.2))
with Wdgt.canvas:
Rectangle(pos_hint = {'center_x':0.5, 'center_y':0.5}, size = (Wdgt.width, Wdgt.height))
parent.add_widget(Wdgt)
return parent
if __name__ == '__main__':
MyPaintApp().run()
I see two problems with your code. The first is that your super() call in MyPaintWidget.on_touch_move() should pass MyPaintWidget, not Scatter. Second, using pos_hint causes extra calculations, so I suggest changing your on_touch_move() to:
def on_touch_move(self, touch):
self.pos_hint = {'center_y':0.5} # eliminates the x pos_hint
self.x = touch.x
return super(MyPaintWidget, self).on_touch_move(touch)

Kivy: Change the background of ActionButton in ActionOverFlow

I want to change the background of the ActionButtons which are inside the ActionOverflow in an ActionBar, however using the usual approach for Buttons (background_down, background_normal) seems not to work.
[ActionButton with black background] (https://raw.githubusercontent.com/Thomas-Adams/kivy_mananger/master/color_mananger/kivy-actionbutton.png)
Strangely enough when i click on that specific ActionButton (for instance 'List') the background changes as desired. However the 'normal' not pressed state has still a black background. I also tried tampering with background-image property, but to no avail. What do I miss? Does anybody has a clue or hint about this?
#:import get_color_from_hex kivy.utils.get_color_from_hex
<MainView>:
...
ActionButton:
canvas.before:
Color:
rgba: get_color_from_hex('#d500f9')
Rectangle:
size: self.size
pos: self.pos
background_normal: 'electric-violet.png'
background_down: 'electric-violet-lighten.png'
background_disabled: ''
background_disabled_down: ''
background_color: get_color_from_hex('#d500f9')
text: 'Create'
Here's the link to the complete kv file
Another possibility is to create your own class based on ActionButton:
class MyActionButton(ActionButton):
real_background_normal = StringProperty('')
And modify its style in your kv file:
<MyActionButton>:
-background_normal: self.real_background_normal
Then elsewhere in your kv file, when you use MyActionButton, just use real_background_normal instead of background_normal:
MyActionButton:
real_background_normal: 'electric-violet.png'
I figured it out by myself, in case anybody else is stuck here, instead of using the ActionButton widget i wrote my own widget which is based on ActionItem and Button :
class ColorActionButton(ActionItem, Button, EventDispatcher):
color_name = StringProperty()
base_dir = IMAGE_BASE_DIR
b_normal = StringProperty()
b_down = StringProperty()
b_disabled_down = StringProperty()
b_disabled = StringProperty()
def __init__(self, **kwargs):
super().__init__(**kwargs)
def on_color_name(self, instance, value):
self.b_normal = self.base_dir + value + SUFFIX
self.b_down = self.base_dir + value + LIGHTEN_SUFFIX
self.b_disabled_down = self.base_dir + value + DARKEN_SUFFIX
Using this now works like a charm.

How to delete clicked Widget?

I create child widgets (Buttons for example).
When I click each button (each child widget) I wish to remove the clicked widget from parent.children.
I can't figure out how to fetch that specific clicked widget from parent.children other than having a clumsy system in parent:
def DeleteWidget(self, targetWidget):
for i in self.children:
if id(i) == id(targetWidget):
self.remove_widget(i)
Any better methods to delete a clicked widget?
You can bind each button's on_press property to your class method DeleteWidget like this:
btn1 = Button(text= "Button 1")
btn1.bind(on_press = self.DeleteWidget)
When btn1 is pressed, it'll execute your DeleteWidget method which will take an argument (in this case, button object with its address).
def DeleteWidget(self, *args):
self.remove_widget(args[0])
Here's a basic example:
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.button import *
from kivy.uix.boxlayout import *
class TestApp(App):
def build(self):
bx = BoxLayout(orientation = 'vertical')
btn1 = Button(text="Button 1")
btn1.bind(on_press = self.deleteButton)
bx.add_widget(btn1)
btn2 = Button(text="Button 2")
btn2.bind(on_press = self.deleteButton)
bx.add_widget(btn2)
return bx
def deleteButton(self, x):
self.root.remove_widget(x)
TestApp().run()

on_touch_down problems with dynamic created widgets in kivy

I'm new to kivy and need some assistance with the following problem. I adding numbers/operators as widgets (labels) dynamically and at a random position to a layout(FloatLayout). The idea is that when I clicked on a number/operator it will draw a circle around the number/operator. I get some very strange behaviour. Does not matter what number/operator I click the selection circle is only drawn around the last added label. Then to confuse me even more the other number/operator is circled if I press on some random point on the screen
following is the core of my code:
class SelectedObject(Label):
selected = BooleanProperty()
refresh = BooleanProperty()
def __init__(self, **kwargs):
super(SelectedObject, self).__init__(**kwargs)
self.center_x = randint(0, Window.width/2)
self.center_y = randint(0, Window.height/2)
self.bind( refresh = self.redraw )
def redraw(self, *args):
#print('Redraw for: ' + self)
self.canvas.after.clear()
if self.selected:
with self.canvas.after:
Line(circle=(self.center_x, self.center_y, 20))
self.canvas.ask_update()
def on_touch_down(self, touch):
print("touch#: " + str(touch))
if not self.collide_point(touch.x, touch.y):
return False
print("yip: " + self)
self.selected = not self.selected
self.refresh = not self.refresh # force a redraw
return True
class GameNumber(SelectedObject):
pass
class Operator(SelectedObject):
pass
class GameApp(App):
numberArr = ListProperty([])
operatorArr = ListProperty([])
def build(self):
f = FloatLayout()
#populate numberArr and operatorArr
self.buildLevel()
for number in self.numberArr:
numberItem = GameNumber(text = str(number))
f.add_widget(numberItem)
for operator in self.operatorArr:
f.add_widget(Operator(text = operator))
return f
The problem here is that you have not set sizes to the labels. So each label takes up as much space as it can and the last label being on top, it gets the circle.
You need to pass each GameNumber and Operator some sort of size_hint and/or size. For example, if you want each label to be 10 by 10, you can do something like this: numberItem = GameNumber(text=str(number), size_hint=(None, None), size=(10, 10)). You can set their size relative to the window size by for example setting size_hint=(0.1, 0.1).
Remember that size_hint is always (1, 1) by default, so you need to change it something else if you want your widgets to be smaller than the space of the container and set size_hint=(None, None) if you want to set a fixed size yourself.
If you want to position the labels randomly around the screen, take a look at pos_hint, which is more convenient than playing with the size of the window directly. Also, remember that there's a chance that multiple labels might get on top of each other or at the very borders of the window or even outside if you are not careful.
EDIT: To help you find the source of these kind of problems (that usually relate to layout issues), take a look at Kivy Widget Area Display

django admin list_display invert (not) a boolean field

I have:
class MyModelAdmin(admin.ModelAdmin):
list_display = ('name', 'locked', )
It displays the nice green and red icons for the locked field.
What I want is to show inverted values in locked field.
So i wrote this:
def not_locked(obj):
return not obj.locked
class MyModelAdmin(admin.ModelAdmin):
list_display = ('name', not_locked,)
And this works (inverts the values), but it displays ugly True or False instead of the nice green and red icons.
How to make it show the icons again?
just add to your method 'not_locked' attribute boolean=True,
def not_locked(self, obj):
return not obj.locked
not_locked.boolean = True

Resources