Ich habe gerade Kivy abgeholt und bin auf dieses Problem gestoßen. Wenn es einen besseren Weg gibt, das zu erreichen, was ich generell versuche, würde ich gerne davon hören.Kivy platziert Widgets über Python und Kivy leicht anders. Fehle ich etwas?
Was ich bemerkt habe, ist, dass, wenn ich ein Widget zu einem anderen Widget hinzufügen, wenn ich dies durch Python-Code tun wird es leicht an einer anderen Position als ich es durch Kivy getan habe. Ich füge meinen Code unten ein (im Moment ist es ziemlich kurz) und du kannst es einfach selbst ausprobieren und du wirst sehen, was ich meine.
client.py:
import kivy
kivy.require('1.9.1') # current kivy version
from kivy.config import Config
Config.set('graphics', 'width', '360')
Config.set('graphics', 'height', '640')
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.properties import ObjectProperty, NumericProperty, ReferenceListProperty
from kivy.graphics import Color, Rectangle
from kivy.clock import Clock
from kivy.vector import Vector
from random import randint
class Bird(Widget):
'''
Bird Widget defines each sprite./Test version: blue and red cards
Defined attributes:
SIZE
POSITION
(COLOR)
Upade the position of this widget individually every 0.7 seconds with 60 fps
'''
# set attributes
border_color = (1,1,1)
r = NumericProperty(0)
g = NumericProperty(0)
b = NumericProperty(0)
color = ReferenceListProperty(r, g, b) # initial color = red // maybe make it random
velocity_x = NumericProperty(0)
velocity_y = NumericProperty(-3)
velocity = ReferenceListProperty(velocity_x, velocity_y)
def __init__(self, **kwargs):
super(Bird, self).__init__(**kwargs)
self.pick_color()
# Randomly generate 0 or 1, and pick a color based on that
def pick_color(self):
color_num = randint(0,1)
if color_num == 0: # blue
self.color = (0,0,1)
elif color_num == 1: # red
self.color = (1,0,0)
# Move the widget by -3y increment at 60 fps
def increment(self, dt):
self.pos = Vector(*self.velocity) + self.pos
def move(self):
# While the sprite moves at 60 fps, the movement is "cancelled" after 0.3 seconds
# This event sequence is refreshed every 0.7 seoncds in MainApp class
move = Clock.schedule_interval(self.increment, 1.0/60.0)
stop = Clock.schedule_once(lambda dt: move.cancel(), 0.3)
class GameMain(Widget):
'''
Contains two functions: ADD_NEW_BIRD() and UPDATE().
All controls happen in this widget
Not using kivy.screen because there is only one screen used
ADD_NEW_BIRD() adds a new bird to list_of_birds AND add it as a child widget to the GameMain Widget. UPDATE() calls MOVE() (Bird Widget) and receives events
Create global variable limit = 0; if limit == 4, game over; variable accessed in update function, which checks whether the limit has been reached. If the player makes the right decision, then limit -= 1
'''
limit = 0
def add_new_bird(self):
self.new_bird = Bird(center_x=self.center_x, center_y=self.height/1.5)
print (self.center_x, self.height)
self.new_bird.pick_color()
self.add_widget(self.new_bird)
def update(self, dt):
for bird in self.children:
bird.move()
self.add_new_bird()
class MainApp(App):
def build(self):
game = GameMain()
Clock.schedule_interval(game.update, 0.7)
return game
if __name__ == '__main__':
MainApp().run()
main.kv:
#:kivy 1.9
<Bird>:
size: 70, 80
canvas:
Color:
rgb: self.border_color
Rectangle:
size: self.size
pos: self.pos
Color:
rgb: self.color
Rectangle:
size: root.width - 10, root.height - 10
pos: root.x + 5, root.y + 5
<GameMain>
Bird:
center_x: root.center_x
center_y: root.height/1.5
Der Code macht genau das, was ich will es tun (ich auf die z-Werte später berühren werde) außer dass die allererste Karte leicht nach links abweicht. Ich bin nur wirklich verwirrt, weil center_x: root.center_x
in main.kv
nicht anders sein sollte als Bird(center_x=self.center_x
in client.py
, soweit ich verstehe. Ich habe versucht, innerhalb einer init-Funktion die ersten Instanz von Bird()
Initialisierung wie folgt:
def __init__(self, **kwargs):
super(GameMain, self).__init__(**kwargs)
self.bird = Bird(center_x=self.center_x, center_y=self.height/1.5)
self.bird.pick_color()
self.add_widget(self.bird)
Und das Problem war immer noch da! Wenn jemand erklären könnte, was vor sich geht/was ich falsch mache, und vielleicht sogar einen besseren Weg vorschlage, würde ich es begrüßen.
Nur für den Fall, dass Sie neugierig sind, muss ich Widgets direkt aus Python-Code hinzufügen, weil ich die App ständig eine neue Karte in einem konstanten Zeitintervall produzieren muss. Die erste Karte wird jedoch der Einfachheit halber in der Kivy-Datei initialisiert. Um fair zu sein, funktioniert es bis auf den Offset ziemlich gut. Und schließlich benutze ich kein Layout, weil ich nicht sicher war, welches ich verwenden soll ... Ich habe FloatLayout ein wenig in die Hand genommen, aber es schien nicht so, als würde es mein Problem irgendwie lösen.
Vielen Dank. Ich benutzte einen Workaround, aber wenn ich das wüsste, hätte ich mir eine Menge Kopfschmerzen ersparen können. Auch dieser Teil über nicht zu viel Kivy und Python mischen - ich sehe das Problem gerade mit Popups. Ich hätte gerne diese ideale "Trennung" (kivy behandelt alle UI-Sachen, Python behandelt Logik), aber da ich Widgets dynamisch ziemlich oft hinzufüge, benutze ich am Ende mehr Python. Vielleicht sollte ich die Kivy-Datei komplett löschen. – spicypumpkin