Kivy Spinner - Values Size - list

Is there a way to change the text size from the values argument within Spinner? I've found that I can change the height and width of the dropdown boxes and change the size of the "label" (Layer). But is there a way to change the text size of both heads and all?
Spinner:
id: spinner_lry
text: 'Layer'
values:['heads', 'all']
size_hint_y: None
height: 50
font_size: 20

Yes, the options in a Spinner are displayed using the SpinnerOption class (just a Button) by default. You can set a different class to display the options using option_cls atribute, and specify the font_size for that class, like this in your kv:
<MyOption#SpinnerOption>:
font_size: 50
Spinner:
id: spinner_lry
text: 'Layer'
option_cls: "MyOption"
values:['heads', 'all']
size_hint_y: None
height: 50
font_size: 20

Related

Bind kivy properties from one screen to another screen

newbie here trying to test my hand on something new.I'm trying to display slider value from one screen on another screen. The screen I want the value to be displayed in has multiple screens embedded in it. the first picture is the first screen.
home screen that contains multiple screens
below is the code for this screen:
<Thermostat>:
BoxLayout:
orientation: 'horizontal'
cols: 2
Label:
id: Thmo
font_size: "11sp"
text: "INSIDE: 50"
Label:
text: "More Info"
font_size: "11sp"
<Weather>:
BoxLayout:
orientation: 'horizontal'
cols: 2
Label:
id:Temp
text: "OUT TEMP: "+ root.checkWeather()
font_size: "11sp"
Label:
id: Locale
text: root.locale
font_size: "11sp"
The next screen which is the command screen is here below, i want the slider value from this screen to be updated in the home screen. I have tried using a global variable called TEMP but it did not work. any help would be appreciated.
command screen
below is the code for the command screen:
<Temperature>:
BoxLayout:
cols: 3
Label:
text: 'THERMOSTAT'
Slider:
id: temp_slider
min: 40
max: 100
value: 40
step: 1
on_value: app.TEMP = str(temp_slider.value)
Label:
id: value
text: str(temp_slider.value)
<Vent>:
BoxLayout:
size_hint_y: None
height: '48dp'
cols: 3
Label:
text: 'VENT'
Button:
id: state
text: 'Open'
on_press: root.Open(state)
Label:
id: cmdErr
from kivy.app import App
value = App.get_running_app().root.ids.SCREENCONTROLLER.get_screen('SCREENAMEHERE').ids.CHILDWIDGETID.
Basically, you do your usual id traveling but you start from the very top of the running app and work downwards.
'root' here is the widget that is returned in the Apps Build Method. You haven't provided that code, so I'm assuming you returned the Screen Controller.
Once you get to the screen controller, you can use its get_screen method by entering the string name you gave to the screen you want to go to, then from their you find it through ids as if you were on that screen.

Binding loop warning on Label

I am trying the similar code to the tutorial, but I get 'QML Rectangle: Binding loop detected for property "width"' on the list view delegate. This happens only on messages where words are larger than listView.width and text wrapping happens. This happens all time. How can I fix it?
delegeate: Rectangle {
id: delegateFrame
width: Math.min(messageText.implicitWidth , listView.width)
height: messageText.implicitHeight
Label {
id: messageText
anchors.fill: parent
text: model.text
wrapMode: Label.Wrap
}
}
I am using Qt 5.8.
EDIT
Changed as Felix suggested in his answer, however it only changed the "width" word in the warning to "implictWidth".
delegeate: Rectangle {
id: delegateFrame
implicitWidth: Math.min(messageText.implicitWidth , listView.width)
implicitHeight: messageText.implicitHeight
Label {
id: messageText
width: parent.width
text: model.text
wrapMode: Label.Wrap
}
}
The cause here is probably height: messageText.implicitHeight and anchors.fill: parent. Reason:
change label height --> change delegate hight --> change anchors --> change label height ...
QML detects those loops and interrupts them. In some cases, you have to live with those, because it's the only way to archive your layout.
In your case however, there might be a solution. You can try one of the following, and see if they work:
use implicitHeight and implicitWidth in the delegate. Sometimes those remove the warnings
Instead of using anchors.fill bind the width only: width: parent.width. Since you already adjust the parents height to the child, the child does not need to change it's height to the parent
Use Layouts. For example RowLayout. They provide advanced ways of placing items and use attached properties to adjust how items are displayed

ScrollView and CustomButton

I woud like to create ScrollView with custom Buttons (Label + Image), but I've got problem with proper positioning Label and Image on Button object.
Code:
class TestScreen(Screen):
def change(self, btn, pos):
print pos
def populate(self):
scroll = self.ids.myscroll
grid = self.ids.scrollgrid
btn = Button(size_hint_y=None, width='29sp', text='')
box = BoxLayout(size=btn.size, pos=btn.pos,orientation='horizontal')
image = Image(source='image.png', size_hint_x=None, width=74)
label = Label(size_hint_x=None, width=100, text='test')
box.add_widget(image)
box.add_widget(label)
btn.add_widget(box)
grid.add_widget(btn)
btn.bind(pos=partial(self.change))
and .kv file:
<TestScreen>:
Button:
text: 'populate'
size_hint: None, None
size: 100,100
pos: 0,0
on_press: root.populate()
ScrollView:
id: myscroll
size_hint: None, None
size: 300, 500
pos: 100, 100
scroll_x: 0.5
GridLayout:
spacing: 20
padding: 20
id: scrollgrid
size_hint: None, None
cols: 1
size_hint_y: None
children
height: self.minimum_height
width: self.parent.width
The biggest problem is that during creating BoxLayout in populate(), btn.pos is [0,0] and after rendering btn.pos is changed to proper coordinates (I checked that using bind() for pos). How can I get correct cooridnates during creating mentioned BoxLayout?
If you add a widget to another widget, which isn't a layout, it will receive default pos (0,0) and size (100, 100). Use a grid layout to pack an image and a button together. Example:
main.py:
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.screenmanager import Screen
from kivy.properties import StringProperty, ObjectProperty
from random import choice
class ImageButton(GridLayout):
images = [
'http://kivy.org/logos/kivy-logo-black-256.png',
'http://img.interia.pl/rozrywka/nimg/2/7/roz4286600.jpg',
'http://www.i-programmer.info/images/stories/News/2014/Apr/A/kivycont2.jpg',
'http://static.giantbomb.com/uploads/scale_small/9/90155/2472244-abathur.png',
'https://www.gravatar.com/avatar/a07de5a89d18964a22775deae84d9ba6?s=328&d=identicon&r=PG',
'https://www.gravatar.com/avatar/578e323e1c4dda99b24bf047e0cb2e3e?s=328&d=identicon&r=PG&f=1'
]
source = StringProperty(images[0])
def change_image(self):
while True:
new_img = choice(self.images)
if new_img != self.source:
self.source = new_img
break
class MainScreen(Screen):
grid = ObjectProperty()
def populate(self):
for i in xrange(10):
self.grid.add_widget(ImageButton())
class Test(App):
def on_start(self):
self.root.populate()
Test().run()
test.kv:
MainScreen:
grid: grid
ScrollView:
GridLayout:
id: grid
cols: 1
spacing: '10dp'
padding: '10dp'
size_hint_y: None
height: self.minimum_height
<ImageButton>:
cols: 2
size_hint_y: None
height: '200dp'
AsyncImage:
source: root.source
size_hint_x: 0.3
Button:
text: 'click me'
on_press: root.change_image()
Adding widgets to a Button isn't a very nice solution. Button actually is a Label with a behavior set to it, therefore you only duplicate it without any good reason. How to make such a widget(a button with an image) is explained here, you'd need only to choose a position for Image and position whole widget for your needs. In the first example the App class also behaves as a BoxLayout, so imagine it as a layout only - a root widget. From there it'll be easy.
Also, when a widget is initialized, it comes with the default values of size and pos and other values specific for the widget itself, which are then changed. Basically, you created a widget with btn = Button(), but didn't set any pos or size, so when you access the position later within box, you only take the defaults and well... place them to size and pos of another widget - so you only replaced defaults with the same values. To get correct values you'll need to set them first inside the widget to your desired pos&size.

Placing an image in the middle of the label in Kivy

I have the following Kivy language file, which should mimic a dialer app. Also in the middle underneath the digits it should display an icon (red rectangle). However it seems that in my implementation the parent, self and root objects all have the same properties. What's wrong in my code? Is there a better way to do it?
# File name: dialer.kv
#:kivy 1.9.0
<Button>:
color: .8,.9,0,.65
font_size: 32
<MyGridLayout>:
rows: 3
spacing: 10
GridLayout:
rows: 1
size_hint_y: .40
Label:
text: '12345678901231234567890'
size: self.texture_size
text_size: root.width, None
font_size: 44
halign: 'center'
valign: 'middle'
canvas.before:
Rectangle:
pos: self.parent.center_x - self.width / 2, self.parent.center_y - self.height / 2
source: 'bg.png'
GridLayout:
cols: 3
rows: 4
size_hint_y: .50
spacing: 10
Button:
text: '1'
Button:
text: '2'
Button:
text: '3'
Button:
text: '4'
Button:
text: '5'
Button:
text: '6'
Button:
text: '7'
Button:
text: '8'
Button:
text: '9'
Button:
text: '*'
Button:
text: '0'
Button:
text: '#'
GridLayout:
cols: 2
size_hint_y: .10
spacing: 10
Button:
text: 'Clear'
Button:
text: 'Dial'
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
# File name: main.py
import kivy
kivy.require('1.9.0')
from kivy.app import App
from kivy.uix.gridlayout import GridLayout
class MyGridLayout(GridLayout):
pass
class DialerApp(App):
def build(self):
return MyGridLayout()
if __name__=="__main__":
DialerApp().run()
self variable you're using inside the canvas instructions is referencing to enclosing widget class (in this case it's a label), not a VertexInstruction like Rectangle. In your code self.parent.center_x is in fact the center of GridLayout and the self.width is the label width. To place your image in the middle of the label you can calculate the position manually:
<MyGridLayout>:
rows: 3
spacing: 10
GridLayout:
rows: 1
size_hint_y: .40
Label:
# ...
canvas.before:
Rectangle:
pos: self.center_x - 50, self.center_y - 50 # default size is 100x100
source: 'test.png'
# ...
You can also use Image widget as follows:
<MyGridLayout>:
rows: 3
spacing: 10
GridLayout:
rows: 1
size_hint_y: .40
Label:
# ...
Image:
center: self.parent.center
source: 'test.png'
# ...
Image is a Widget so now self refers to it and self.parent refers to the Label and we can use the center attribute to calculate the position automatically.

Qt: active chats control

I'm trying to figure out what component that would be best to use for a active chats control.
I've attached an image with the layout that I'm aiming for.
Basically I want to add an icon to the left of each conversation, depending if the conversation is active or not. The middle column is the name of the conversation and the last column is an indicator if there are new messages for this conversation. However, if the row is selected the indicator should switch out to a close conversations button.
I've through about using:
- Listview, however this would not give me multiple columns?
- Treeview
- Tableview - this might be the best solution. However in unsure of how to add icons and buttons to different cells
Which one would be my best bet here?
I think it depends on API you want to achieve. Most importantly, who will be the close handler/listener:
You can go for a table view with three different delegates. This way the caller is responsible to set up the close event.
Or you can make it list view, which internally creates listView/GridView. This way the conversation itself would be the listener to the close event.
It's up to you to decide which of these (there may be more) is more suitable to your existing codebase
If you have a simple delegate to implement (and you work in QML), you can really use a ListView to get the job done.
Here is a self-contained prototype of your layout. Change Rectangle by Image. You see that color vary accordingly as the model give an odd or even number. You can in the same way change the Component to load, the source of an Image, whatever you can imagine.
import QtQuick 2.0
Rectangle {
width: 360
height: 200
ListView {
anchors.fill: parent
model: 3
delegate: Rectangle {
id: rect
width: parent.width
height: 60
property bool selected: false
color: selected ? "darkblue" : "transparent"
Rectangle {
id: bubbleIcon
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
width: 40
height: 40
color: "lightblue"
}
Text {
id: chatName
anchors.left: bubbleIcon.right
anchors.leftMargin: 10
height: parent.height
verticalAlignment: Text.AlignVCenter
text: "chat" + modelData
}
Rectangle {
id: notificationIcon
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
width: 40
height: 40
//just an dummy example to show how to change representation base
//expression binding
color: (modelData % 2 === 0) ? "lightGreen" : "red"
}
MouseArea {
anchors.fill: parent
onClicked: {
selected = ! selected;
}
}
}
}
}