Kivy/Python пытается активировать/деактивировать кнопки при перетаскивании в макете сетки

#python #button #kivy #grid-layout #drag

Вопрос:

Я пытаюсь создать стиль кнопки, который работает как обычная кнопка, но я также хочу иметь возможность запускать несколько кнопок одним щелчком мыши и перетаскивать по строке/столбцу кнопок, которые я пытаюсь отключить.

У меня есть некоторый стартовый код, код работает точно так, как задумано, при перетаскивании слева направо или сверху вниз, но не справа налево или снизу вверх.

Я постарался максимально упростить код. Любая помощь была бы ОЧЕНЬ признательна.

 from kivy.app import App
from kivy.graphics import Color
from kivy.uix.button import Button
from kivy.uix.gridlayout import GridLayout
from kivy.uix.widget import Widget
from kivy.core.window import Window


def pointInRect(point, rect):
    x1, y1, w, h = rect
    x2, y2 = x1 w, y1 h
    x, y = point
    if (x >= x1 and x < x2) and (y >= y1 and y < y2):
        return True
    return False

class TouchInput(Widget):
    def __init__(self, cb, *args, **kwargs):
        super(TouchInput, self).__init__(*args, **kwargs)
        self.cb = cb
    def on_touch_down(self, touch):
        self.cb( touch.button, touch.pos )
    def on_touch_up(self, touch):
        self.cb( None, touch.pos )

class CustomButton(Button):
    def __init__(self, name, *args, bg_color=None, **kwargs):
        Window.bind(mouse_pos=self.on_mouse_pos)
        super(CustomButton, self).__init__(*args, **kwargs)
        self.mouse_button = None
        self.mouse_entered_while_down = False
        
        self.enabled = True

        self.text = name

        self.background_normal = ''
        self.background_down = ''
        self.default_color = (0.3, 0.1, 0.1, 1 )
        self.pressed_color = (.66, .66, .66, 1)
        self.disabled_color = (.125, .125, .125, 1)
        
        toucher = TouchInput( self.on_touch )
        toucher.size = self.size
        toucher.pos = self.pos
        self.add_widget ( toucher )
        
        self.colorize()
        
    def colorize(self, bg_color=None, text_color=None):
        if not bg_color:
            bg_color = self.disabled_color if not self.enabled else self.default_color
        
        text_color = (1 - bg_color[0],  1 - bg_color[1], 1 - bg_color[2], bg_color[3])

        self.background_color = bg_color
        self.color = text_color

    def on_touch(self, button, pos):
        self.mouse_button = button
        
        if pointInRect( pos, self.pos   self.size ):
            if self.mouse_button:
                self.mouse_enter()
            else:
                self.mouse_leave()

    def on_mouse_pos(self, *args):
        pos = args[1]
        if self.mouse_button:
            if pointInRect( pos, self.pos   self.size ):
                if not self.mouse_entered_while_down:
                    self.mouse_enter()
            else:
                if self.mouse_entered_while_down:
                    self.mouse_leave()
 
    def mouse_leave(self, *args):
        self.enabled = not self.enabled
        self.colorize()
        self.mouse_entered_while_down = False
 
    def mouse_enter(self, *args):
        self.colorize(bg_color=self.pressed_color)
        self.mouse_entered_while_down = True

class TestApp(App):
    def build(self):
        layout = GridLayout(cols=5, spacing=5, padding=5)
        for i in range(25):
            layout.add_widget( CustomButton(name=str(i)) )
        return layout

if __name__ == '__main__':
    TestApp().run()
 

Ответ №1:

Для всех, кто заинтересован; Я решил свою проблему со следующим кодом:

 def on_touch_up(self, touch):
    self.mouse_button = None
    if pointInRect( touch.pos, self.pos   self.size ):
        self.mouse_leave()
        
def on_touch_down(self, touch):
    self.mouse_button = touch.button
    if pointInRect( touch.pos, self.pos   self.size ):
        self.mouse_enter()

def on_mouse_pos(self, *args):
    pos = args[1]
    if self.mouse_button:
        if pointInRect( pos, self.pos   self.size ):
            if not self.mouse_entered_while_down:
                self.mouse_enter()
        else:
            if self.mouse_entered_while_down:
                self.mouse_leave()