Это мой первый интерфейс Kivy GUI, поэтому я подозреваю, что не делаю что-то правильно. Тем не менее, я хотел бы знать, почему это происходит или как достичь желаемого результата.
Я пытаюсь сделать изображение в Toggle Button. По какой-то причине при запуске приложения загружается только вторая кнопка.
Я покрасил кнопку переключения, которая создает проблему зеленым цветом, поэтому я могу проверить, было ли мое позиционирование выключено. Функции, которые связаны с кнопками, значок изображения вообще не отображается.
Вот мой.kv файл:
<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)
Вот код Python:
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()
Я открыл проблему в github, поведение, которое я обнаружил, похоже, является проблемой с компоновкой сетки и как она вычисляет позиционирование для первого элемента в контейнере.
Я решил это, просто предоставив произвольное значение размера, pos_hint и x и x позиционирование на первом элементе Image.
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
Из того, что я могу сказать, сетка не знает его размеров, пока первый элемент не будет помещен внутри него. Таким образом, второе добавленное ToggleButton Image понимает, где оно относится только после того, как первый элемент указан с большей детализацией.
Опять же, я не уверен, является ли это ошибкой или как разработан GridLayout.
Если я понимаю, что вы просите, вы можете это сделать, просто используя свойства background_normal
и background_down
для ToggleButton
. Кроме того, ToggleButton
не является контейнером, поэтому попытка использовать Image
в качестве дочернего элемента ToggleButton
самом деле не имеет смысла. Поэтому в вашем файле Kivy
попробуйте настроить ToggleButton
следующим образом:
##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)
Устраните дочерний ToggleButton
Image
ToggleButton
и удалите код в root.attendantchange()
который пытается изменить Image
. Сделайте те же самые изменения для другого ToggleButton
. Также обратите внимание, что background_color
в ToggleButton
просто отображает фактическое изображение, поэтому вы также можете удалить его.