I'm using Windows 10, Python 3.7.9
My code:
In Main.py:
from kivy.app import App
from kivy.uix.widget import Widget
class MyGrid(Widget):
pass
class Main(Widget):
def build(self):
return Main()
if __name__ == "__main__":
Main().run()
In main.kv:
<Main>
GridLayout:
cols:1
GidLayout:
cols:2
Label:
text: "Name: "
TextInput:
multiline:False
Label:
texxt: "Email: "
TextInput:
multiline:False
Button:
text:"Submit"
Error(1):
In the .py file, 'Main' in 'Main().run()' is underlined with:
Instance of 'Main' has no 'run' member
Error(2):
In the .kv file '' is underlined with:
Kivy files require #:Kivy
I can't figure out how to fix, any help is appreciated
I see two bugs, one in the kv code, and the second in the python code.
In the kv code change the <Main> to <MyGrid>.
MyGrid class is the root widget, not the Main class. The Main class is only responsible to build the widget tree.
In the python code, change the return of the build method in the Main class so that it returns a MyGrid instance. And the Main should inherit from the App class, not from the Widget class.
class Main(App):
def build(self):
return MyGrid()
According to the documentation, a kv file:
Syntax of a kv File A Kivy language file must have .kv as filename
extension.
The content of the file should always start with the Kivy header,
where version must be replaced with the Kivy language version you’re
using. For now, use 1.0:
#:kivy `1.0`
# content here
Then, in your py file. an application must extend App not Widget. Also, the build() method must return a Widget, not an instance of the App. And, if your App is named Main, then you should choose a different name for the root widget of your App.
The rules in the kv file describe how to build widgets, and cannot be applied to building an App. They can describe the building of the root widget of the App, but not the App itself.
Related
I'm following a tutorial on youtube and when I run the code, the window shows the labels half off the screen on the left-bottom side. I uploaded a screenshot of the window.
The .kv file is:
<MyGrid>
GridLayout:
cols: 1
GridLayout:
cols: 2
Label:
text: "Name: "
TextInput:
multiline:False
Label:
text: "Email: "
TextInput:
multiline:False
Button:
text: "Submit"
And the py file is:
from kivy.app import App
from kivy.uix.widget import Widget
class MyGrid(Widget):
pass
class MyApp (App):
def build(self):
return MyGrid()
if __name__ == "__main__":
MyApp().run()
You are trying to use the base Widget class as a container, but it was not designed for that use. Try just using some Layout class as the base for MyGrid, like this:
class MyGrid(FloatLayout):
pass
Note that this will result in a GUI that is a FloatLayout that contains a GridLayout which contains another GridLayout. If that is not your intention, consider changing the base class of MyGrid to GridLayout and eliminate one or two of the contained GridLayouts.
I'm trying to make an app that can automate an Instagram page, and I have the script for the program ready, but just need to implement it into a GUI. For this, I'm using Kivy. However, I only need to send one request to the API for this. When I click on a button, it triggers the command attached to on_release of the button twice. How can I fix this?
Simplified Python Script:
from kivymd.app import MDApp
from kivy.uix.screenmanager import Screen, ScreenManager
from kivy.lang import Builder
class StartScreen(Screen):
pass
class WindowManager(ScreenManager):
pass
class BruhApp(MDApp):
def build(self):
self.root = Builder.load_file("bruh.kv")
if __name__ == '__main__':
BruhApp().run()
.kv File:
WindowManager:
StartScreen:
<StartScreen>:
name: "start"
FloatLayout:
MDLabel:
text: "Welcome to the Instagram Page Automator!"
font: "RobotoThin"
font_style: "H5"
halign: "center"
size_hint:0.9,0.7
color: 0,0,0,0.5
pos_hint:{"center_x":0.5,"y":0.5}
MDFillRoundFlatButton:
md_bg_color: 0, 1, 0.6, 1
text:"Continue"
font: "RobotoThin"
size_hint:0.4,0.07
pos_hint:{"center_x":0.5,"y":0.1}
on_release:
print("yes")
This script prints "Yes" twice for me everytime I press the button.
The kivy system automatically loads a kv file for an App if the file is correctly named (See the documentation). Since your kv file is correctly named, it will be loaded automatically. But since you also load it explicitly using the line:
self.root = Builder.load_file("bruh.kv")
the kv file actually gets loaded twice, which causes some things to be instantiated twice. Try replacing the build() method with a simple pass.
import kivy
from kivy.app import App
from kivy.uix.widget import Widget
#MADE A CLASS FOR MAKING THE GUI
class Main_GUI(App):
pass
def ind(self):
print("hi")
kv = Main_GUI()
kv.run()
The above is the Python code which i have named sample.py.
Below is the Main_GUI.kv
BoxLayout:
orientation: "vertical"
Button:
text: "Hello"
on_press: ind()
Button:
text: "Btn2"
problem is that the function ind is not called up
Please help in rectifying the error.
ERROR
NameError: name 'ind' is not defined
Please Intimate me if any errors. I am new to kivy.
Your ind() method is defined outside of any class. Probably not what you want, but you can access it from within kv by adding:
#: import ind __main__.ind
to the start of your kv file.
A better approach is to just move that method inside your Main_GUI class:
class Main_GUI(App):
def ind(self):
print("hi")
and access it in kv using the app keyword:
Button:
text: "Hello"
on_press: app.ind()
The app refers to your application instance. See the documentation.
In order to understand the logic behind Kivy kv language, I'm trying to rewrite a minimal application by replacing the automatic load of a kv file by a call to Builder.load_string().
Here's my starting point (source: examples 1-2, 1-3): two files, weather.py and weather.kv :
weather.py:
from kivy.app import App
class WeatherApp(App):
pass
if __name__ == '__main__':
WeatherApp().run()
and weather.kv:
Label:
text: "Hello World"
Up to there, everything's alright
.
But if I try to load manually the kv stuff, I just get a black screen (and no error message). My code:
from kivy.app import App
from kivy.lang import Builder
KV = '''
Label
text: "Hello World"
'''
Builder.load_string(KV)
class WeatherApp(App):
pass
if __name__ == '__main__':
WeatherApp().run()
I'm obviously missing something here, but what ? Any help would be appreciated !
When you create a .kv there are basic but strict rules, among them there can only be one toplevel, the toplevel is identified because it does not have "<>", besides for the App to recognize it it must have the same name of the application in lowercase, in your case the .kv is called weather.kv and the WeatherApp app. But the above does not happen if you use Builder, in the case that the .kv has a root as it is in your case Builder.load_string() returns it so you must return it in the build method of the App:
from kivy.app import App
from kivy.lang import Builder
KV = '''
Label:
text: "Hello World"
'''
root = Builder.load_string(KV)
class WeatherApp(App):
def build(self):
return root
if __name__ == '__main__':
WeatherApp().run()
I want to make a simple program that is just showing definitions that are stored in text file.One label and button to show next definition. I try to do it with documentation but i cannot find how to load text into label. Can someone show me to some good resources or code samples ?
My code for now (i want to build in on top of example from kivy website):
import kivy
kivy.require('1.9.0')
from kivy.app import App
from kivy.uix.label import Label
class MyApp(App):
def build(self):
return Label(text = 'Hello world')
if __name__ == '__main__':
MyApp().run()
The easiest way to update widgets in the UI are by binding to their properties. This can be done in code, but the real power of kivy in my opinion comes from using it's declarative UI language. Using kv, you get automatic binding.
Here is a quick example of what you might do:
from kivy.app import App
from kivy.lang import Builder
from kivy.properties import StringProperty
kv = '''
BoxLayout:
orientation: 'vertical'
Label:
text: app.text
Button:
text: 'click me'
on_press: app.clicked()
'''
class MyApp(App):
text = StringProperty("hello world")
def build(self):
return Builder.load_string(kv)
def clicked(self):
self.text = "clicked!"
if __name__ == '__main__':
MyApp().run()
In the kv description of the UI, you tell kivy that you want the text on the Label to be bound to a StringProperty on the app which you defined on the class. The auto-binding means that anytime you set a value to that property (like in the clicked function), the UI will update with the new value automatically.