python - Kivy 小部件坐标与 collide_point 不正确
问题描述
显然这只是我在这里缺少一些知识,但无论如何,我会问我的问题。
我正在尝试在屏幕上制作一个圆形触摸点,以模拟操纵杆。为了实现这一点,我从一个圆形的小部件开始。所以我在一个小部件中画了一个圆圈,并覆盖了Widget.collide_point()
.
但是在测试中:
(a)我的小部件从不使用右下角的位置提示,并且......
(b)似乎认为它的中心点位置不在屏幕上。
我认为这是在构建期间未最终确定 Widget 坐标的某种问题(因为我假设容器小部件移动它),但我真的不明白如何进一步解决这个问题。
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
解决方案
只是一些使这项工作的建议。我会把布局放在 kv 中。并on_touch_move
改为使用。好吧,至少这就是我期望操纵杆工作的方式,在移动中。
然后有一些错别字,比如centre_y = self.center_x
Well let me just throw the example here。它看起来仍然有点像您正在做的事情,只是添加了一些用于调试而不是打印的标签。
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()
推荐阅读
- vue.js - Vue v-bind:样式不随嵌套数据更改而更新
- scala - 在 hadoop 集群上提交 spark JAR 时出现 ClassNotFoundException 问题
- python - AWS DynamoDB - 提供的关键元素与架构不匹配
- nginx - 使用 NGINX 等 TLS 代理的 MinIO KES 的 HA 问题
- ibm-cloud - IBM Watson Studio 或 Watson Machine Learning 中的 WML_INSTANCE_NAME 是什么
- python - 如何指定要从 Yahoo Finance API 返回而不是获取所有字段?
- scala - 将 spark 数据框中的值限制为仅指定的值
- python - 如何添加到 websocket on_message 中的 manager.dict()
- firebase - GCP MFA 是否允许受信任的设备?
- python - 平均使用 *args 和类的属性