kivy listitem button with checkbox position - python

I would like to have a list item button with at the right a checkbox.
At the moment I have the checkbox in the center and the list item button text also in the center, so both widgets are mixed
How can I shift the checkbox at the right side ?
My class code :
class AttendanceListButton(FloatLayout, ListItemButton, CheckBox):
root = FloatLayout()
b1 = ListItemButton(pos_hint={'left': 1, 'center_y': .5}, size_hint=(None, None))
b2 = CheckBox(pos_hint={'right': 1 , 'center_y': .5}, size_hint=(None, None))
root.add_widget(b1)
root.add_widget(b2)
Thank you in advance!

I don't quite get what you're asking but I know that ListView is now depreciated and replaced with RecycleView

Related

How to use the ScrollView on PC?

I have tried to add a simple scroll view on PC, I define the scroll view like any other widget and then adds its layout and that I then add the widgets.
Here is the code I use:
Window.size = (339, 600)
self.w1 = self
with self.w1.canvas.before:
Color(0.941176, 0.941176, 0.941176, 1)
self.rect = Rectangle(size=self.w1.size, pos=self.w1.pos)
self.w1.bind(pos=self.update_rect, size=self.update_rect)
self.scroll1 = ScrollView(size_hint=(None, 1), size=(Window.width, Window.height),scroll_type = ['bars',"content"])
self.w1.add_widget(self.scroll1)
self.scroll1_layout = RelativeLayout(pos_hint ={'x':0.0, 'y':0.0},size_hint = (0.626844, 1))
self.scroll1.add_widget(self.scroll1_layout)
self.button1 = Button(text = "Button", pos_hint ={'x':0.568182, 'y':0.47585}, size_hint = (1.30682, 0.0545617))
self.scroll1_layout.add_widget(self.button1)
self.button2 = Button(text = "Button", pos_hint ={'x':0.227273, 'y':0.864937}, size_hint = (0.909091, 0.0992844))
self.scroll1_layout.add_widget(self.button2)
How do I make it so that it has a button and below the widget origin. the widget origin is the bottom left of the widget and the bottom below it would not be visible until I scrolled down.
Thank You for any help.

Don't know why my Kivy Dropdown list isn't showing

For some reason my kivy dropdown list is not showing and im following the exact method from the documentation. Still no avail. ill appreciate any help. Here is my code.
class NewProjectScreen(Screen):
def __init__(self, **kwargs):
super(NewProjectScreen, self).__init__(**kwargs)
self.location = TextInput(multiline = True, pos_hint = {"center_x": 0.5, "center_y": 0.6}, hint_text = "Location", size_hint = [0.4, 0.10], font_name = 'fonts/Qanelas-Light.otf', id = "location")
self.add_widget(self.location)
self.location.bind(text = self.dropdown)
def dropdown(self, instance, value):
if len(self.location.text) > 0:
towns_cities = 'https://maps.googleapis.com/maps/api/place/findplacefromtext/json?input=' + self.location.text + "&inputtype=textquery&fields&types=geocode&sensor=false&types=regions&key=" + API_KEY
response = urllib.request.urlopen(towns_cities).read()
directions = json.loads(response)
print(directions)
for places in directions:
place = places
self.dropdown = DropDown()
for index in range (5):
btn = Button(text = places[index])
self.dropdown.add_widget(btn)
btn.bind(on_release=lambda btn: self.dropdown.select(btn.text))
self.dropdown.open(btn)
Several problems with your code.
Your code self.dropdown = DropDown() redefines self.dropdown, which is a method of your NewProjectScreen class. I suggest refactoring to change the name of that method.
Your code self.dropdown.open(btn) tries to attach the DropDown to one of its own buttons (probably won't work). I suggest replacing that with self.dropdown.open(self.location).
As mentioned in the documentation "When adding widgets, we need to specify the height manually". I suggest modifying your Button creation to btn = Button(text = places[index], size_hint=(1, None), height=50).
I believe the above changes will get your code working.

Drop down menu in Kivy Python

I had found a similar topic at stackoverflow but unluckily it didn't help me.
It's the first time I try to seriously program a GUI and I'm really getting mad.
I'm doing one step at a time, towards what I will finally need.
Now I'm trying to add a simple drop down menu in the top left corner of my widget, whose element should call a function whenever they are selected. I really looked for this in kivy documentation, and in this forum but I can't really solve this.
import multiprocessing
from mesh import MeshApp
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.dropdown import DropDown
from kivy.uix.button import Button
import os
MAINDIR = os.path.dirname(os.path.realpath(__file__))
categories = {}
def getCategories():
for dir in os.walk(MAINDIR):
if len(dir[1]) == 0:
filelist = set()
for mesh in dir[2]:
filelist.add(mesh.replace('_FRONT.png','').replace('_SIDE.png','').replace('_TOP.png',''))
categories.update({dir[0]: filelist})
#class CategoriesList(DropDown):
# pass
class MainWindow(Widget):
def __init__(self):
#self.categorieslist = CategoriesList()
categories_list = DropDown()
for i in categories.keys():
btn = Button(text=i.replace(MAINDIR, ''), size_hint_y=None, height=30)
btn.bind(on_release=lambda btn: categories_list.select(btn.text))
categories_list.add_widget(btn)
mainbutton = Button(text='Choose directory', size_hint=(1, 1))
mainbutton.bind(on_release=categories_list.open)
categories_list.bind(on_select=lambda instance, x: setattr(mainbutton, 'text', x))
#and now???
class RenderApp(App):
def build(self):
self.launchMeshApp()
return MainWindow()
def launchMeshApp(self):
app = MeshApp()
p = multiprocessing.Process(target=app.run)
p.start()
if __name__ == '__main__':
getCategories()
RenderApp().run()
And:
#:kivy 1.9.1
<MainWindow>:
canvas.before:
Color:
rgba: 0.6, 0.6, 1, 1
Rectangle:
pos: self.pos
size: self.size
canvas:
Color:
rgba: 0, 0, 0, 0.5
Rectangle:
pos: 0, self.height * 5 / 6 - 1
size: self.width, 2
I've created the dropdown as seen in the docs and in several other forum. But I need to place it in the top left corner, and I never found, or understood, the way to do this. Moreover I didn't get how to make them call a function with a parameter whenever they are clicked.
Thank you very much
EDIT: I don't know why but the first line with "Hi all" is automatically deleted
I don't know about the dropdown menu, but I can answer the data one.
When you bind a callback, the first argument you receive will be which widget that is bound to the callback. So the idea is to create a class that uses Button as its base class, then you can define whatever extra information you need.
Here is a rough, non tested example based on the button API example:
class MyAwesomeButton(Button):
def __init__(self, **kwargs):
super(MyAwesomeButton, self).__init__(**kwargs)
self.my_data = {} # enter your data here
def callback(instance):
print('The button <%s> is being pressed' % instance.text)
print instance.my_data
btn1 = MyAwesomeButton(text='Hello world 1')
btn1.bind(on_press=callback)
btn2 = MyAwesomeButton(text='Hello world 2')
btn2.bind(on_press=callback)

How to position Kivy Popup with absolute coordinate?

How do you disable relative position for a Kivy Popup object? For example, how would you define absolute pos for this example?:
from kivy.uix.popup import Popup
from kivy.uix.label import Label
popup = Popup(title='Test popup', content=Label(text='Hello world'),
size_hint=(None, None),
#pos_hint=None, pos_hint=(None, None), pos_hint={},
size=(200,200), pos=(10, 10))
popup.open()
Notice if the pos_hint attempts are uncommented, it fails either because pos_hint mustn't be null, cannot be a tuple, or simply has no effect (the popup is always centered vertically and horizontally). Notice also that the custom size does work.
Since pos_hint works well you can always do: ("10.0" is the absolute coordinate )
popup = Popup(title='Test popup', content=Label(text='Hello world'),
size_hint=(None, None),
pos_hint={'x': 10.0 / Window.width,
'y':10.0 / Window.height},
size=(200,200), #pos=(10, 10),
)
The only problem here is that you'll have to update the pos_hint on a re-size event
pos_hint should be a dict, not a tuple, so probably pos_hint={} or pos_hint=None will work (but I'm not sure which).

Dynamically resizing a kivy label (and button) on the python side

How do I dynamically resize the a label or button, in particular, the text_size and height, depending on the amount of text, at run-time?
I am aware that this question has already been answered in one way with this question:
Dynamically resizing a Label within a Scrollview?
And I reflect that example in part of my code.
The problem is dynamically resizing the labels and buttons at run-time. Using, for example:
btn = Button(text_size=(self.width, self.height), text='blah blah')
...and so on, only makes the program think (and logically so) that the "self" is referring to the class which is containing the button.
So, how do I dynamically resize these attributes in the python language, not kivy?
My example code:
import kivy
kivy.require('1.7.2') # replace with your current kivy version !
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.properties import ObjectProperty
from kivy.uix.button import Button
from kivy.uix.gridlayout import GridLayout
i = range(20)
long_text = 'sometimes the search result could be rather long \
sometimes the search result could be rather long \
sometimes the search result could be rather long '
class ButtonILike(Button):
def get_text(self):
return long_text
class HomeScreen(Screen):
scroll_view = ObjectProperty(None)
def __init__(self, *args, **kwargs):
super(HomeScreen, self).__init__(*args, **kwargs)
layout1 = GridLayout(cols=1, spacing=0, size_hint=(1, None), \
row_force_default=False, row_default_height=40)
layout1.bind(minimum_height=layout1.setter('height'),
minimum_width=layout1.setter('width'))
layout1.add_widget(ButtonILike())
for result in i:
btn1 = Button(font_name="data/fonts/DejaVuSans.ttf", \
size_hint=(1, None), valign='middle',)#, \
#height=self.texture_size[1], text_size=(self.width-10, None))
btn1.height = btn1.texture_size[1]
btn1.text_size = (btn1.width-20, layout1.row_default_height)
btn1.text = long_text
btn2 = Button(font_name="data/fonts/DejaVuSans.ttf", \
size_hint=(1, None), valign='middle')
btn2.bind(text_size=(btn2.width-20, None))
btn2.text = 'or short'
layout1.add_widget(btn1)
layout1.add_widget(btn2)
scrollview1 = self.scroll_view
scrollview1.clear_widgets()
scrollview1.add_widget(layout1)
class mybuttonsApp(App):
def build(self):
return HomeScreen()
if __name__ == '__main__':
mybuttonsApp().run()
And the kv file:
#:kivy 1.7.2
<ButtonILike>:
text_size: self.width-10, None
size_hint: (1, None)
height: self.texture_size[1]
text: root.get_text()
#on_release: root.RunSearchButton_pressed()
<HomeScreen>:
scroll_view: scrollviewID
AnchorLayout:
size_hint: 1, .1
pos_hint: {'x': 0, 'y': .9}
anchor_x: 'center'
anchor_y: 'center'
Label:
text: 'Button Tester'
ScrollView:
id: scrollviewID
orientation: 'vertical'
pos_hint: {'x': 0, 'y': 0}
size_hint: 1, .9
bar_width: '8dp'
You can see that I added the button from the kv file which displays all the behavior that I want at the top of the list. Resize your window while running it, and you can see the magic. And, of course, changing the text_size also makes it possible for me to align text.
I simply have not been able to achieve the same behavior on the python side. My app requires that the buttons be created at run-time. I think the answer might lie with "bind()", though admittedly, I'm not sure I used it correctly in my attempts or that I understand it fully. You can see that I tried with "btn2", which I thought would've thrown the text to the left (since halign defaults to left), but didn't seem to do anything.
I appreciate the help.
I think the best way is to set Label's/Button's size to texture_size:
Label:
text: "test"
size_hint: None, None
size: self.texture_size
canvas.before: # for testing purposes
Color:
rgb: 0, 1, 0
Rectangle:
pos: self.pos
size: self.size
My answer is slightly different from #martin's - I only want to modify the height.
def my_height_callback(obj, texture: Texture):
if texture:
obj.height = max(texture.size[1], 100)
class MyButton(Button):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.size_hint = (1, None)
self.bind(texture=my_height_callback)
When the text is rendered the texture property of the button gets set. That texture's height is then pushed to the button's height via the callback. Calling max() allows for a minimum height to be set. This works fine with labels as well.
btn2.bind(text_size=(btn2.width-20, None))
As with your other question, the problem is that you have the syntax of bind wrong. You must pass a function, but you just wrote a tuple, and bind can't do anything useful with that - it certainly doesn't know you happened to write btn2.width there.
Also, the syntax is that bind calls the function when the given property changes. That's the opposite of what you want - you need to change the text_size when btn2.width changes, not call a function when text_size changes
I think something like the following would work. instance and value are the default arguments we ignored in the other question.
def setting_function(instance, value):
btn2.text_size = (value-20, None)
btn1.bind(width=setting_function)
I was looking to resize both the text_size width and height, the latter specifically with regard to the documented behaviour of kivy.Label that vertical alignment of text in a label cannot be achieved without doing this first. Further, I needed to do it in python, not .kv.
class WrappedVAlignedLabel(Label):
def __init__(self,**kwargs):
super().__init__(**kwargs)
self.bind(height=lambda *x:self.setter('text_size')(self, (self.width, self.height)))
strangely, binding on width instead of height would only set text_size[0], I guess due to some order of rendering self.height wasn't yet computed, so the setting of text_size[1] wasn't happening. Whereas binding on height gets them both.

Categories