Kivy控件与collide\u poin的坐标不正确

2024-04-25 15:20:15 发布

您现在位置:Python中文网/ 问答频道 /正文

很明显,这只是我缺少一些知识,但无论如何,我会问我的问题。你知道吗

我试着在屏幕上做一个圆形的触摸点来模拟操纵杆。为了实现这一点,我从一个圆形的小部件开始。所以我在小部件中画了一个圆,并覆盖了Widget.collide_point()。你知道吗

但是在测试时:
(a) 我的小部件从不使用右下位置提示,而且。。。
(b) 似乎认为它的中心点位置在屏幕外。你知道吗

我认为这是一个小部件的坐标在构建过程中没有最终确定的问题(因为我假设容器小部件移动了它),但是我真的不知道如何进一步解决这个问题。你知道吗

[旁白]如果我创建以self.center_x&;self.center_y为中心的圆,它会在左下角部分脱离屏幕。我一点也不明白。你知道吗

在容器小部件定位完成后,我试着用时钟设置一个回拨来重新调整圆圈,但也没用。你知道吗

#! /usr/bin/env python3
import kivy
kivy.require('1.9.1')

from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.floatlayout import FloatLayout
from kivy.graphics import Rectangle, Color, Rotate, PushMatrix, PopMatrix, Line, Ellipse
from kivy.core.window import Window
from kivy.clock import Clock

import random

WINDOW_WIDTH, WINDOW_HEIGHT = Window.size

class JoyStick( Widget ):

    def __init__( self, dial_width, **kwargs ):
        super( JoyStick, self ).__init__( **kwargs )
        self.radius     = dial_width // 2
        self.radius_sq  = self.radius * self.radius

        with self.canvas:
            Color( 200, 200, 20 )
            #Ellipse( pos=( self.center_x , self.center_y ), size=(self.radius * 2, self.radius * 2))
            Line( circle=( dial_width, dial_width, self.radius ) )

        self.size_hint  = ( None, None )  
        self.pos_hint   = { 'right':1, 'top':0 } 

    def collide_point( self, x, y ):
        centre_x = self.center_x
        centre_y = self.center_x
        print("JoyStick.collide_point( %d, %d ) -> cx=%d, cy=%d, r=%d" % ( x, y, centre_x, centre_y, self.radius ) )
        # Point-in-Circle Formula: if ((x-centre_x)^2 + (y - centre_y)^2 < radius^2) -> TRUE
        x_minus_cx = x - centre_x
        y_minus_cy = y - centre_y
        result = ( ( x_minus_cx * x_minus_cx ) + ( y_minus_cy * y_minus_cy ) < self.radius_sq ) 
        print("JoyStick.collide_point( %d, %d ) -> %s" % ( x, y, str( result ) ) )
        return result


class Screen( FloatLayout ):
    def __init__(self, **kwargs):
        super( Screen, self).__init__(**kwargs)
        # Controller
        self.joystick = JoyStick( 150 )
        self.add_widget( self.joystick )

    def on_touch_down( self, touch ):
        if ( self.joystick.collide_point( *touch.pos ) ):
            print("Joystick Handled point")

    def update( self, dt ):
        pass


class MainApp( App ):
    def build( self ):
        screen = Screen()
        Clock.schedule_interval( screen.update, 1.0 / 60.0 )
        return screen



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

在这种情况下,我不得不拉伸窗口,实际上有一个750x750点击。你知道吗

JoyStick.collide_point( 531, 582 ) -> cx=750, cy=750, r=75
JoyStick.collide_point( 531, 582 ) -> False
JoyStick.collide_point( 672, 712 ) -> cx=750, cy=750, r=75
JoyStick.collide_point( 672, 712 ) -> False
JoyStick.collide_point( 737, 721 ) -> cx=750, cy=750, r=75
JoyStick.collide_point( 737, 721 ) -> True
Joystick Handled point

main.png


Tags: fromimportself部件defpointcentercx
1条回答
网友
1楼 · 发布于 2024-04-25 15:20:15

只是一些建议,使这项工作。我会把布局放在千伏。使用on_touch_move。好吧,至少我希望操纵杆是这样工作的,在移动中。
还有一些拼写错误,比如centre_y = self.center_x
让我举个例子。它看起来仍然有点像你正在做的,只是添加了一些标签调试,而不是打印。你知道吗

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.widget import Widget
from kivy.uix.floatlayout import FloatLayout
from kivy.properties import StringProperty

class JoyStick(Widget):
    radius = 70

    def collide_point( self, x, y ):
        result = (x-self.center_x) ** 2 + (y-self.center_y) ** 2 < self.radius ** 2
        return result

class MyLayout(FloatLayout):
    handling = StringProperty("")
    xt = StringProperty("")
    yt = StringProperty("")

    def on_touch_move( self, touch ):
        self.xt, self.yt = str(round(touch.pos[0])), str(round(touch.pos[1]))
        if ( self.js.collide_point( *touch.pos ) ):
            self.handling = "True"
        else:
            self.handling = "False"


KV = """

MyLayout:
    js: js
    JoyStick:
        id: js
        canvas:
            Line:
                circle: root.center_x, root.center_y, self.radius

    Label:
        font_size: "30sp"
        text: root.handling
    BoxLayout:
        orientation: "vertical"
        Label:
            text: "x: {}".format(root.xt)
        Label:
            text: "y: {}".format(root.yt)
"""


class MyApp(App):
    def build(self):
        return Builder.load_string(KV)


MyApp().run()

相关问题 更多 >