将Widgets 设置为不更改size 或pos 是最简单的解决方案。基本上只用size_hint=(None, None),不要用GridLayout:
from kivy.app import App
from kivy.graphics import Rectangle
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.label import Label
class MyGrid(FloatLayout):
def __init__(self,**kwargs):
super(MyGrid,self).__init__(**kwargs)
self.grid_size=4
for k in range(self.grid_size):
for i in range(self.grid_size):
with self.canvas:
Rectangle(size=(100,100),pos=(k*160+100,i*160+100),source="52852.JPG")
for h in range(self.grid_size):
for j in range(self.grid_size):
self.add_widget(Label(text="labwl"+str(h)+str(j),size=(100,100),pos=(h*160+100,j*160+100), size_hint=(None, None)))
class GameApp(App):
def build(self):
return MyGrid()
if __name__ == '__main__':
GameApp().run()
要使Rectangles 和Labels 更改pos 和size 有点复杂。在下面您的代码的修改版本中,我保留Labels 和Rectangles 和bind 的列表,adjust_common_size() 方法在size 的MyGrid 更改时运行。然后该方法调整Labels 和Rectangles 的size 和pos 以匹配:
from kivy.app import App
from kivy.properties import ListProperty
from kivy.graphics import Rectangle
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.label import Label
class MyGrid(FloatLayout):
common_size = ListProperty((100, 100))
def __init__(self,**kwargs):
super(MyGrid,self).__init__(**kwargs)
self.grid_size=4
self.rects = []
self.labels = []
for k in range(self.grid_size):
one_row = []
self.rects.append(one_row)
for i in range(self.grid_size):
with self.canvas:
one_row.append(Rectangle(size=self.common_size,pos=(k*160+100,i*160+100),source="52852.JPG"))
for h in range(self.grid_size):
one_row = []
self.labels.append(one_row)
for j in range(self.grid_size):
label = Label(text="labwl"+str(h)+str(j),size=self.common_size,pos=(h*160+100,j*160+100), size_hint=(None, None))
one_row.append(label)
self.add_widget(label)
self.bind(size=self.adjust_common_size)
def adjust_common_size(self, instance, new_size):
self.common_size = (new_size[0] * 0.9 / self.grid_size, new_size[1] * 0.9 / self.grid_size)
for k in range(self.grid_size):
for i in range(self.grid_size):
adjusted_pos = (k * new_size[0] / self.grid_size, i * new_size[1] / self.grid_size)
rect = self.rects[k][i]
label = self.labels[k][i]
label.size = self.common_size
label.pos = adjusted_pos
rect.size = self.common_size
rect.pos = adjusted_pos
class GameApp(App):
def build(self):
return MyGrid()
if __name__ == '__main__':
GameApp().run()
没有必要为common_size 使用ListProperty,但如果您决定使用kv 会很方便。
这是一个有趣的问题。这是使Rectangle 和Label 匹配的更好方法。下面的代码使用了GridLayout,但定义了MyLabel以包含它自己的Rectangle,并保持它的Rectangle在pos和size中匹配:
from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.graphics import Rectangle
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.label import Label
class MyLabel(Label):
def __init__(self, **kwargs):
super(MyLabel, self).__init__(**kwargs)
with self.canvas.before:
self.rect = Rectangle(size=self.size,pos=self.pos,source="52852.JPG")
self.bind(size=self.adjust_size)
self.bind(pos=self.adjust_pos)
def adjust_pos(self, instance, new_pos):
self.rect.pos = new_pos
def adjust_size(self, instance, new_size):
self.rect.size = new_size
class MyGrid(FloatLayout):
def __init__(self,**kwargs):
super(MyGrid,self).__init__(**kwargs)
self.grid=GridLayout()
self.grid_size=4
self.grid.cols=self.grid_size
for h in range(self.grid_size):
for j in range(self.grid_size):
self.grid.add_widget(MyLabel(text="labwl"+str(h)+str(j),size=(100,100),pos=(h*160+100,j*160+100)))
self.add_widget(self.grid)
class GameApp(App):
def build(self):
return MyGrid()
if __name__ == '__main__':
GameApp().run()
使用这种方法,您根本不必在MyGrid 中创建Rectangles,因为每个Label 都会创建自己的。