簡體   English   中英

Kivy小部件坐標與collide_point不正確

[英]Kivy widget co-ordinates incorrect with collide_point

顯然,只是我在這里缺少一些知識,但是無論如何,我會問我一個問題。

我試圖在屏幕上制作一個圓形的接觸點,以模擬操縱桿。 為了實現這一點,我從一個圓形的小部件開始。 因此,我在小部件中繪制了一個圓圈,並覆蓋了Widget.collide_point()

但是在測試中:
(a)我的小部件從不使用右下角的位置提示,並且...
(b)似乎認為其中心點位置在屏幕外。

我認為這是某種問題,即在構建期間未最終確定小部件的坐標(因為我假設容器小部件會移動它),但是我真的不了解如何進一步解決此問題。

[Aside]如果我創建一個以self.center_xself.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

關於這項工作的一些建議。 我會把布局放在kv中。 並改用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()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM