問題描述
我正在嘗試在 kivy 中創建一個界面,我認為對于自定義小部件以及如何對它們進行分層,即使在完成本教程之后,我仍然不了解一些基本的東西.我認為我有更多的盒子模型 html 思維方式,所以小部件嵌套在原生 GUI 中的方式對我來說仍然有點陌生.
I'm trying to make an interface in kivy and I think there are some fundamental things I don't understand about custom widgets and how to hierarchy them, even after going through the tutorial. I think I have more of a box-model html mindset, so the way widgets are nested in native GUIs are still kind of foreign to me.
一些背景:
我咨詢了這篇文章關于如何添加背景(它回答問題:如何將背景圖像/顏色/視頻/...添加到布局中",我相信我正在使用 _update_rect 方法進行復制.
I consulted this entry on how to add a background (It answers the question: "How to add a background image/color/video/... to a Layout", which I believe I was replicating with the _update_rect methods).
這個有一個 on_touch_down 事件.
This one that has an on_touch_down event.
K,我正在嘗試讓 MyApp 看起來像這樣......
K, I'm trying to get MyApp to look like this...
據我了解,這里是我需要的東西:
As I understand it, here are the things I'd need for that:
- 您有一個應用.
- 應用有根.
- 根有背景,比如說背景是白色的.
- 背景包含一個支架,假設支架距離背景有一點邊距并且是灰色的.我確實希望這是一個小部件,而不僅僅是一個非小部件畫布,因為我希望持有者也對點擊事件做出反應.單擊時它會變成隨機顏色.(只是為了表明它正在做某事.)
- 支架包含兩個自定義小部件.這些是帶有標簽的圓圈,每個都是綠色的.單擊時它們會變成隨機顏色(只是為了表明它們正在做某事).
這是我的代碼,它不再崩潰,但不顯示任何顏色或任何類型的對象.
Here's my code, which doesn't crash anymore, but doesn't display any colors or objects of any kind.
#!/usr/bin/kivy
import kivy
kivy.require('1.7.2')
from random import random
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.floatlayout import FloatLayout
from kivy.graphics import Color, Ellipse, Rectangle
class MyApp(App):
title = 'My App'
def build(self):
root = RootWidget()
root.bind(
size=self._update_rect,
pos=self._update_rect)
def _update_rect(self, instance, value):
self.rect.pos = instance.pos
self.rect.size = instance.size
class RootWidget(FloatLayout):
def __init__(self, **kwargs):
super(RootWidget, self).__init__(**kwargs)
with self.canvas.before:
Color(1, 0, 0, 1) # This RED does not display.
self.rect = Rectangle(
size=self.size,
pos=self.pos,
text="some junk!") # This label does not display.
mybackground = Background()
self.add_widget(mybackground)
def _update_rect(self, instance, value):
self.rect.pos = instance.pos
self.rect.size = instance.size
class Background(Widget):
def __init__(self, **kwargs):
super(Background, self).__init__(**kwargs)
with self.canvas.before:
Color(1, 1, 1, 1) # This WHITE does not display
self.rect = Rectangle(
size=self.size,
pos=self.pos,
text="More stuff!") # This label does not display.
myholder = Holder()
self.add_widget(myholder)
def _update_rect(self, instance, value):
self.rect.pos = instance.pos
self.rect.size = instance.size
class Holder(Widget):
def __init__(self, **kwargs):
super(Holder, self).__init__(**kwargs)
with self.canvas.before:
Color(0.25, 0.25, 0.25, 1) # This GRAY does not display
self.rect = Rectangle(
size=self.size,
pos=self.pos,
text="More stuff!") # This does not display.
c1 = Circley(label="Label 1") # I see I'd need to do some size/pos math here to center
c2 = Circley(label="Label 2") # but since everything isn't working, I've tabled this.
self.add_widget(c1)
self.add_widget(c2)
def _update_rect(self, instance, value):
self.rect.pos = instance.pos
self.rect.size = instance.size
def on_touch_down(self, touch):
rcolor = Color(random(), random(), random(), 1)
with self.canvas:
self.color = rcolor
class Circley(Widget):
def __init__(self, label='label', **kwargs):
super(Circley, self).__init__(**kwargs)
with self.canvas.before:
Color(0, 1, 0, 1) # This GREEN does not display
self.circ = Ellipse(
size=self.size,
pos=self.pos,
text=label
)
def _update_circ(self, instance, value):
self.circ.pos = instance.pos
self.circ.size = instance.size
def on_touch_down(self, touch):
rcolor = Color(random(), random(), random(), 1)
with self.canvas:
self.color = rcolor
if __name__ == '__main__':
MyApp().run()
關于我做錯了什么以及如何正確嵌套這些小部件的任何指針?
Any pointers on what I'm doing wrong and how to nest these widgets correctly?
推薦答案
你得到一個空白屏幕的原因是你的應用程序的 build()
方法沒有返回任何東西.無論它返回什么都是根小部件,但即使您制作了一些小部件,您也不會返回一個,因此不會顯示任何內容.
The reason you get a blank screen is that your app's build()
method does not return anything. Whatever it returns would be the root widget, but even though you make some widgets you don't return one so nothing is displayed.
如果您解決了這個問題,您可以再次運行該應用程序,但您會立即收到類似 MyApp has no attribute rect
的錯誤.這是因為您的根小部件會立即調整大小并定位以填充窗口,這(根據您的 root.bind
行)觸發 MyApp._update_rect
.但是,這種方法嘗試修改 MyApp.rect.pos...但是應用程序沒有 self.rect!您大概打算綁定到 root._update_rect
,而不是應用程序的方法.(我改為綁定到 root._update_rect
,現在至少出現了紅色背景和綠色圓圈.)
If you fix this, you can run the app again but you'll immediately get an error something like MyApp has no attribute rect
. This is because your root widget is immediately sized and positioned to fill the window, which (as per your root.bind
line) triggers MyApp._update_rect
. However, this method try to modify MyApp.rect.pos...but the app doesn't have a self.rect! You presumably intended to bind to root._update_rect
, not the app's method. ( I bound to root._update_rect
instead and now at least the red background and green circle do appear.)
順便說一句,使用 kv 語言會更容易,它可以自動處理許多小部件的創建、矩形綁定等.
And as a side note, this would be a lot easier using the kv language, which could automatically take care of a lot of the widget creation, rectangle binding etc.
我現在沒有時間解決它,但也許這兩個問題可以幫助您解決整體流程.如果沒有其他人有,我稍后會嘗試發布更完整的答案.
I don't have time to fix it all right now, but perhaps these two problems can help you fix the overall flow. I'll try to post a more complete answer later if nobody else has.
根據評論,這是一個更新的 MyApp.
Here's an updated MyApp, as per the comments.
class MyApp(App):
title = 'My App'
def build(self):
root = RootWidget()
root.bind(
size=root._update_rect,
pos=root._update_rect)
這篇關于在 kivy 中嵌套小部件的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!