This is my first Kivy GUI interface so I suspect I'm not doing something correctly. However, I'd like to know why this is happening or how to achieve the desired result.
I'm attempting to render an Image within a Toggle Button. For whatever reason, only the second button is loaded when I run the application.
I colored the toggle button that is creating the problem in green so I could check if my positioning was off. The functions that are bound to the buttons work, the image icon will not display at all.
Here's my .kv file:
<Controller>:
lbl: my_label
tbl: my_other_label
atl: attendant_label
timg: my_test_img
aimage: attendant_img
BoxLayout:
canvas.before:
Color:
rgba: 0.137, 0.149, 0.161, 1
Rectangle:
# self here refers to the widget i.e BoxLayout
pos: self.pos
size: self.size
orientation:'horizontal'
GridLayout:
cols:1
rows:2
##THIS DOES NOT DISPLAY
ToggleButton:
id:attendant_label
group: 'g2'
border:0,0,0,0
background_color:(0, 1, 0, 1.0)
background_normal:''
background_down: ''
on_press: root.attendantchange(*args)
Image:
id:attendant_img
source: 'attendantoff.png'
size: self.parent.width, self.parent.height
##THIS DISPLAYS..
ToggleButton:
id:my_other_label
group: 'g1'
border:0,0,0,0
background_color:(0.137, 0.149, 0.161, 1.0)
background_normal:''
background_down: ''
on_press: root.buttonchange(*args)
Image:
id:my_test_img
source: 'bulb1.png'
size: self.parent.width, self.parent.height
Slider:
canvas:
Color:
rgb: 0.89,0.694,0
BorderImage:
border: (0, 18, 0, 18) if self.orientation == 'horizontal' else (18, 0, 18, 0)
pos: (self.x + self.padding, self.center_y - sp(18)) if self.orientation == 'horizontal' else (self.center_x - 35, self.y + self.padding)
size: (max(self.value_pos[0] - self.padding * 2 - sp(16), 0), sp(36)) if self.orientation == 'horizontal' else (sp(36), max(self.value_pos[1] - self.padding * 2, 0))
source: 'atlas://data/images/defaulttheme/slider{}_background{}'.format(self.orientation[0], '_disabled' if self.disabled else '')
id:my_label
size_hint:.25,1
min: 0
max: 100
enabled: False
disabled: True
orientation:'vertical'
value_track_color: [0, 1, 0, 1]
on_value: root.new_brightness(*args)
Here is the Python Code:
import paho.mqtt.client as mqtt
import kivy
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.gridlayout import GridLayout
kivy.require('1.10.1') # replace with your current kivy version !
class Controller(BoxLayout):
def __init__(self):
self.buttonState = 0;
self.attendantState = 0;
self.oldBrightness = '0';
self.client = mqtt.Client();
super(Controller,self).__init__()
def new_brightness(self,*args):
if(self.buttonState == 0):
print('light is off');
else:
#self.lbl.text = str(int(args[1]))
#self.tbl.text = str(int(args[1]))
self.oldBrightness = str(int(args[1]))
if(int(args[1]) <= 10):
self.timg.source = "bulb2.png"
elif (int(args[1]) <= 50):
self.timg.source = "bulb2.png"
else:
self.timg.source = "bulb2.png"
self.publish(self.oldBrightness)
def buttonchange(self,*args):
if(self.buttonState == 0):
self.buttonState = 1;
self.lbl.enabled = True;
self.lbl.disabled = False;
self.timg.source='bulb2.png'
self.publish(1)
else:
self.buttonState = 0;
self.timg.source='bulb1.png'
self.lbl.enabled = False;
self.lbl.disabled = True;
self.publish(0)
#self.tbl.text = str(self.buttonState)
print(str(self.__class__) + ": " + str(self.__dict__))
def attendantchange(self,*args):
if(self.attendantState == 0):
self.attendantState = 1;
self.aimage.source='attendanton.png'
else:
self.attendantState = 0;
self.aimage.source='attendantoff.png'
print(str(self.__class__) + ": " + str(self.__dict__))
def __str__(self):
return str(self.__class__) + ": " + str(self.__dict__)
def publish(self,value):
# When I manually send a message from the command line, there is a connect, send, disconnect process
# I am recreating that process here as opposed to connecting once and leaving the connection open.
# If there is only a single connection attempt which fails because the receiver is powered off, etc
# that would leave us with no way to reestablish communications
# connect to broker
Broker = "192.168.1.21"
pub_topic = "RL"
#self.client.connect(Broker, 1883, 60)
# I need this for message subscriptions; not sure about publising
#self.client.loop_start()
# send updated value to reading light
#self.client.publish(pub_topic, value)
# close everything down after sending a message
#self.client.loop_stop()
#self.client.disconnect()
class MyApp(App):
def build(self):
return Controller()
window = MyApp()
window.run()
If I understand what you are asking, you can accomplish that simply by using the background_normal
and background_down
properties of the ToggleButton
. Also, the ToggleButton
is not a container, so trying to use an Image
as a child of the ToggleButton
doesn't really make sense. So in your Kivy
file, try setting up your ToggleButton
like this:
##THIS DOES NOT DISPLAY
ToggleButton:
id:attendant_label
group: 'g2'
border:0,0,0,0
background_normal:'attendantoff.png'
background_down: 'attendanton.png'
on_press: root.attendantchange(*args)
Eliminate the Image
child of the ToggleButton
and remove the code in root.attendantchange()
that tries to change the Image
. Do the same sort of changes for the other ToggleButton
. Also, note that background_color
in the ToggleButton
just tints the actual image, so you may want to remove that, also.
I opened an issue on github, the behavior I discovered appears to be an issue with the Grid Layout and how it computes positioning for the first element in the container.
I solved this by simply providing an arbitrary size value, a pos_hint, and x and x positioning on the first Image element.
ToggleButton:
id:my_other_label
group: 'light'
border:1,1,1,1
background_color:(0.137, 0.149, 0.161, 1.0)
background_normal:''
background_down: ''
on_press: root.buttonchange(*args)
Image:
id:my_test_img
source: 'bulb1.png'
size: 250,250
allow_stretch: True
pos_hint: {'center_x': .5, 'center_y': .5}
y: self.parent.y + self.parent.height - 350
x: self.parent.width/2 - self.width/2
ToggleButton:
id:attendant_label
group: 'gatt'
background_color:(0.137, 0.149, 0.161, 1.0)
background_normal:''
background_down: ''
on_press: root.attendantchange(*args)
Image:
id:attendant_img
source: 'attendantoff.png'
size: self.parent.width, self.parent.height
From what I can tell, the grid doesn't know it's dimensions until the first item is placed inside it. So the second ToggleButton Image that is added understands where it belongs only after the first element is specified with greater detail.
Again, I'm not sure if this is a bug, or how the GridLayout is designed.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.