简体   繁体   中英

Kivy Image not displaying in grid layout within a toggleButton

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM