I want to have opportunity to change or delete rectangle in builder, but I get AttributeError.
How can I fix it? I hope you help me
from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.image import Image
from kivy.lang import Builder
from kivy.core.window import Window
from kivy.graphics import Color, Rectangle
Builder.load_string('''
<RootWidget>
FloatLayout:
id: layout
canvas.before:
Rectangle:
id: image
size: (100, 180)
pos: (223, 191)
source:'image.gif'
''')
class RootWidget(FloatLayout):
def __init__(self, **kwargs):
super(RootWidget, self).__init__(**kwargs)
self.ids.layout.remove_widget(self.ids.image)
class WindowApp(App):
def build(self):
return RootWidget()
if __name__ == '__main__':
WindowApp().run()
Unfortunately, you can't set the id of a canvas object. Here is a workaround: Consider you want to change the source attribute of your Rectangle. Set rectangle_image: "image.gif" in your FloatLayout, then set source: self.rectangle_image in your Rectangle. Now you can reference the FloatLayout by its id and change its rectangle_image variable, and it will automatically update the Rectangle's source attribute!
Related
I have a code, but when it executed it gives a black screen. Tell me what's wrong with it, please.
I try to make a background from a picture on the screen in kivy.
Here is my .py file:
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen, FadeTransition
from kivy.uix.floatlayout import FloatLayout
from kivy.lang import Builder
from kivy.graphics import Color, Rectangle
from kivy.uix.image import Image
Builder.load_file("Layout.kv")
class SpaceAdventure(App):
def build(self):
return RootManager()
class RootManager(ScreenManager):
pass
class StartScreen(Screen):
pass
if __name__ == '__main__':
SpaceAdventure().run()here
There is my kv file:
<RootScreen>:
transition: FadeTransition()
StartScreen:
<StartScreen>:
name: "start"
canvas.before:
Rectangle:
pos: self.pos
size: self.size
source: 'test.jpg'
FloatLayout:
orientation: 'vertical'
MyButton:
text: 'Start'
<MyButton#Button>:
background_color: 1, 1, 1, 1
bold: True
Your MyButton#Button overlayed background.
You add Rectangle to screen with background, then add FloatLayout, then add button with black background. No size hint for button so fill all empty space - actually all your screen.
im really new in Kivy and i would like to make an app where i could create a MDIconButton that is draggable, and if possible, droppable in any BoxLayout? Is that possible in KivyMD or Kivy? Also is there a Kivy function where whenever I hold down a button, it'll display some kind of small dialogue box that contains details that can be entered by the user. thanks!
Rather than use Drag-N-Drop from kivy-garden just use the DragBehavior class! It comes directly installed with Kivy and it'll save you having to install kivy-garden.
https://kivy.org/doc/stable/api-kivy.uix.behaviors.drag.html
Here is some example code of how it's used:
from kivy.uix.label import Label
from kivy.app import App
from kivy.uix.behaviors import DragBehavior
from kivy.lang import Builder
# You could also put the following in your kv file...
kv = '''
<DragLabel>:
# Define the properties for the DragLabel
drag_rectangle: self.x, self.y, self.width, self.height
drag_timeout: 10000000
drag_distance: 0
FloatLayout:
# Define the root widget
DragLabel:
size_hint: 0.25, 0.2
text: 'Drag me'
'''
class DragLabel(DragBehavior, Label):
pass
class TestApp(App):
def build(self):
return Builder.load_string(kv)
TestApp().run()
I have some Kivy code which so far displays a Screen (BrickBreakerMenuScreen) with an Image and a Label, which, when pressed, changes to a blank Screen (GameScreen) with an image in the centre. However, this is not the aim of my code; as you can see from the Builder, the second screen should align the Image in the top right corner:
from kivy.lang import Builder
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.anchorlayout import AnchorLayout
from kivy.uix.image import Image
from kivy import Config
from kivy.uix.screenmanager import ScreenManager, Screen, FadeTransition
from kivy.uix.widget import Widget
from kivy.animation import Animation
import time
Config.set('graphics', 'multisamples', '0')
Builder.load_string('''
<BrickBreakerMenuScreen>:
BoxLayout:
orientation: 'vertical'
Image:
source: 'brickbreaker log.png'
Label:
font_name: 'vgafix.fon'
text: 'Tap to start'
<GameScreen>:
AnchorLayout:
anchor_x: 'right'
anchor_y: 'top'
Image:
source: 'settings-cog.png'
''')
class BrickBreakerMenuScreen(Screen):
def __init__(self, **kwargs):
super(BrickBreakerMenuScreen, self).__init__(**kwargs)
def on_touch_down(self, touch):
sm.current = 'game'
class GameScreen(Screen):
def __init__(self, **kwargs):
super(GameScreen, self).__init__(**kwargs)
sm = ScreenManager(transition = FadeTransition())
sm.add_widget(BrickBreakerMenuScreen(name='menu'))
sm.add_widget(GameScreen(name='game'))
class BrickBreakerInsanityApp(App):
def build(self):
return sm
if __name__ == '__main__':
BrickBreakerInsanityApp().run()
Is this a problem due to the ScreenManager? I have changed the kv script to attempt to see if it's an issue with AnchorLayout, but none of the other layouts change the image's location on the GameScreen.
Any help is much appreciated. Thanks!
Images:
Your code is working OK. The image is at the top-right corner.
Your problem is the size of that Image widget. Its as big as the size of the window.
To fix this, you could add size_hint: .1, .1 to the Image properties and it will display as you want.
Image:
size_hint: .1, .1
source: 'settings-cog.png'
I'm trying to draw a rectangle in the center of my widget:
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.graphics import Rectangle
class MyWidget(Widget):
def __init__(self):
super(MyWidget, self).__init__()
with self.canvas:
Rectangle(pos=(self.center_x, self.center_y)
class MyApp(App):
def build(self):
return MyWidget()
if __name__ == '__main__':
MyApp().run()
This is what I'm getting:
Doing the exact same thing using a .kv file works:
<MyWidget>:
canvas:
Rectangle:
pos: self.center_x, self.center_y
Please explain how to achieve what I'm trying to do, and why it does work using a .kv file, as opposed to Python code. Thank you
If you add the Widget from a kv file the the widget will be automatically be attached to the App’s root attribute and used as the base of the application widget tree. So in your situation from the kv file the size of the widget is automatically bind to the application windows size and becomes root widget. Taking that into consideration the self.center_x and self.center_y works. You can read this at https://kivy.org/docs/guide/lang.html under the line `MyApp -> my.kv.
When not using a kv file this will not happen and the default size of the widget will be (100,100). To properly place your rectangle use a layout so you can refer use the size_hint to properly place or re size any child widget. As stated in the documentation
FloatLayout honors the pos_hint and the size_hint properties of its children.
https://kivy.org/docs/api-kivy.uix.floatlayout.html#kivy.uix.floatlayout.FloatLayout
So create a Float layout in example, add a widget with pos_hint equals to center_x and center_y that will refer to the layout being a parent and then draw a rectangle to the widget.
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.floatlayout import FloatLayout
from kivy.graphics import Rectangle
from kivy.core.window import Window
class myLayout(FloatLayout):
def __init__(self):
super(myLayout, self).__init__()
self.size = Window.size
self.myWidget = Widget(size=(100,100))
self.add_widget(self.myWidget)
with self.myWidget.canvas:
Rectangle(pos=(self.center_x, self.center_y))
class MyApp(App):
def build(self):
return myLayout()
if __name__ == '__main__':
MyApp().run()
I would like to create a scrollable Floatlayout with dynamically created buttons (kind of paint where I can scroll the drawing board). Unfortunately, the code that I come out doesn't work and the buttons don't move while scrolling the FloatLayout. How can I attach the button to the FloatLayout?
import kivy
kivy.require('1.0.7')
from kivy.app import App
from kivy.uix.scrollview import ScrollView
from kivy.lang import Builder
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.button import Button
Builder.load_string('''
<Scroller>
view: glayout
FloatLayout:
id: glayout
width: 2000
height: 2000
size_hint: (None, None)
''')
class Main(App):
def build(self):
self.root=Scroller()
return self.root
class Scroller(ScrollView):
def __init__(self, **kwargs):
super(Scroller, self).__init__(**kwargs)
a = Button(size_hint=(None,None), width=200, height=200)
self.ids.glayout.add_widget(a)
a.bind(pos=self.ids.glayout.pos)
if __name__ in ('__main__'):
app = Main()
app.run()
The FloatLayout handle the size, not the position. The most simple solution is to replace your FloatLayout with a RelativeLayout, which handle size, and position is relative to the RelativeLayout origin.