I'm trying to display some label using kivy framework in specified time with Timer module. Here is what I have and what I want to include into my python kivy:
from threading import Timer
time_var = 2
def time():
print(time_var)
t = Timer(time_var, time)
t.start()
Here is my python kivy code:
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.uix.popup import Popup
from kivy.config import Config
from threading import Timer
Config.set("graphics", "resizable", 0)
Config.set("graphics", "width", 400)
Config.set("graphics", "height", 500)
time_var = 2
class myLayout(BoxLayout):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.t = Timer(time_var, self.timer)
layout = BoxLayout(orientation="vertical",
padding=20,
spacing=10)
btn = Button(text="Click")
btn.bind(on_press=self.t.start())
self.add_widget(layout)
layout.add_widget(btn)
def timer(self, obj):
popup = Popup(content=Label(text="timer"),
size_hint=(None, None),
size=(300, 200))
return popup.open()
class ReminderApp(App):
def build(self):
return myLayout()
if __name__ == "__main__":
ReminderApp().run()
But I cannot figure it out how to make it work.
Maybe there is a way to make it using kivy modules.. Please help me because I am stuck..
I guess I figured it out.. correct me if I am wrong
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.uix.popup import Popup
from kivy.config import Config
from threading import Timer
Config.set("graphics", "resizable", 0)
Config.set("graphics", "width", 400)
Config.set("graphics", "height", 500)
time_var = 2
class myLayout(BoxLayout):
def __init__(self, **kwargs):
super().__init__(**kwargs)
layout = BoxLayout(orientation="vertical",
padding=20,
spacing=10)
btn = Button(text="Click")
self.add_widget(layout)
layout.add_widget(btn)
btn.bind(on_press=self.timer)
def popup(self):
popup = Popup(content=Label(text="timer"),
size_hint=(None, None),
size=(300, 200))
popup.open()
def timer(self, obj):
timer = Timer(time_var, self.popup)
timer.start()
class ReminderApp(App):
def build(self):
return myLayout()
if __name__ == "__main__":
ReminderApp().run()
Related
After some days looking for an answer, I finally decided that it was time to ask some more experienced users ! Here is my problem : in the following piece of code (simplified version of the original code), when I open the Dialog by clicking on the button, the opened window doesn't have the right size, and so one part of the GridLayout is appearing outside this popup.
I anyone has an idea, thanks in advance !
from kivymd.app import MDApp
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivymd.uix.dialog import MDDialog
class AppClass(MDApp):
def build_toolbar(self):
button = Button(text="Press")
button.bind(on_press=self.popup)
return button
def build(self):
self.theme_cls.theme_style = "Dark"
layout = BoxLayout(orientation='vertical')
toolbar = self.build_toolbar()
layout.add_widget(toolbar)
return layout
#==============================
def popup(self, instance):
print("called")
panel = self.build_settings_panel()
self.dialog = MDDialog(
type="custom",
title="Settings",
content_cls=panel
)
self.dialog.open()
def build_settings_panel(self):
panel = GridLayout(cols=2, row_default_height=100)
for i in range(4):
panel.add_widget(Label(text="Number"))
panel.add_widget(Label(text=str(i)))
return panel
if __name__ == '__main__':
AppClass().run()
It appears that the problem is the size of the panel. way to fix that is to just calculate that size and set it in the build_settings_panel():
def build_settings_panel(self):
row_height = 100
total_height = 0
panel = GridLayout(cols=2, row_default_height=row_height)
for i in range(4):
panel.add_widget(Label(text="Number"))
panel.add_widget(Label(text=str(i)))
total_height +=row_height
panel.height = total_height
return panel
You can try:
row_default_height=9
In your code:
from kivymd.app import MDApp
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivymd.uix.dialog import MDDialog
class AppClassjbsidis(MDApp):
def build_toolbar(self):
button = Button(text="Press")
button.bind(on_press=self.popup)
return button
def build(self):
self.theme_cls.theme_style = "Dark"
layout = BoxLayout(orientation='vertical')
toolbar = self.build_toolbar()
layout.add_widget(toolbar)
return layout
#==============================
def popup(self, instance):
print("called")
panel = self.build_settings_panel()
self.dialog = MDDialog(
type="custom",
title="[color=ffffff]Settings",
content_cls=panel
)
self.dialog.open()
def build_settings_panel(self):
panel = GridLayout(cols=2, row_default_height=9)
for i in range(4):
panel.add_widget(Label(text="Number"))
panel.add_widget(Label(text=str(i)))
return panel
if __name__ == '__main__':
AppClassjbsidis().run()
Pictures:
I am experimenting with Kivy. When I tried using a screen manager, when the application runs, there is a black screen, nothing appears
That is my code. I have no idea what is the problem. It seems that the GridLayout doesn't get displayed on the screen.
import kivy
from kivy.uix.widget import Widget
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.gridlayout import GridLayout
from kivy.graphics import *
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen, SlideTransition
class load_file_screen(Screen):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.my_layout = GridLayout(cols=1)
self.my_layout.cols = 1
self.label = Label(text="Loading files from here")
self.button = Button(text="Click to change")
self.button.bind(on_press=self.changer)
self.my_layout.add_widget(self.label)
self.my_layout.add_widget(self.button)
def changer(self, *args):
self.manager.current = "ViewFile"
class view_file_screen(Screen):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.my_layout = GridLayout(cols=1)
self.label = Label(text="View File here")
self.button = Button(text="Click to change")
self.button.bind(on_press=self.changer)
self.my_layout.add_widget(self.label)
self.my_layout.add_widget(self.button)
def changer(self, *args):
self.manager.current = "LoadFile"
class my_app(App):
def build(self):
self.my_screen_manger = ScreenManager(transition=SlideTransition())
self.my_screen_manger.add_widget(load_file_screen(name="LoadFile"))
self.my_screen_manger.add_widget(view_file_screen(name="ViewFile"))
# self.my_screen_manger.current = "LoadFile"
return self.my_screen_manger
application = my_app()
application.run()
In both your view_file_screen and your load_file_screen, you need to add the line:
self.add_widget(self.my_layout)
in the __init__() method.
I think this question is very basic, but it stops me for two days.
I want to make a simple Kivy-GUI-App. Drag a folder to a ScrollView, then the ScrollView show the files in the folder.
Here is where am I:
from kivy.app import App
from kivy.uix.button import Button
from kivy.core.window import Window
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.scrollview import ScrollView
from kivy.uix.gridlayout import GridLayout
class DropApp(App):
def build(self):
box = BoxLayout()
scrV = ScrollView(width = 300, height = 400, size_hint_x=None, size_hint_y=None)
box.add_widget(scrV)
layout = GridLayout(cols=1, spacing=10, size_hint_y=None)
layout.bind(minimum_height=layout.setter('height'))
for i in range(100):
btn = Button(text=str(i), size_hint_y=None, height=40)
layout.add_widget(btn)
scrV.add_widget(layout)
Window.bind(on_dropfile=self.handledrops(widget = scrV))
return box
def handledrops(self, widget, filename, *args):
if widget.collide_point(*Window.mouse_pos):
print(filename)
if __name__ == '__main__':
DropApp().run()
NOTE: drop to a widget not the window.
I did a lot of googling, studied a lot of examples. I cannot find what's wrong with the code.
Most examples on internet use a lot of classes. But what I want is window, button, label.... I try to understand what's class, what's init, what's self., what's super(). But they make the code abstract. So I avoid them as possible as i can. Hope someone can help me what's wrong with this code.
from kivy.app import App
from kivy.uix.button import Button
from kivy.core.window import Window
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.scrollview import ScrollView
from kivy.uix.gridlayout import GridLayout
class DropApp(App):
def build(self):
box = BoxLayout()
self.scrV = ScrollView(width = 300, height = 400, size_hint_x=None, size_hint_y=None)
box.add_widget(self.scrV)
layout = GridLayout(cols=1, spacing=10, size_hint_y=None)
layout.bind(minimum_height=layout.setter('height'))
for i in range(100):
btn = Button(text=str(i), size_hint_y=None, height=40)
layout.add_widget(btn)
self.scrV.add_widget(layout)
Window.bind(on_dropfile=self.handledrops)
return box
def handledrops(self, window_object, filename):
if self.scrV.collide_point(*Window.mouse_pos):
print(filename)
if __name__ == '__main__':
DropApp().run()
I want to draw circle in center of FloatLayout. With my knowledges I obtained only default values for this. Why circle in showed code isn't red? Can You explain me process for obtaining necessary coordinates, please?
import kivy
from kivy.config import Config
kivy.config.Config.set('graphics','resizable', False)
from kivy.app import App
from kivy.graphics import Color, Ellipse
from kivy.uix.widget import Widget
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.uix.button import Button
class Scene(FloatLayout):
def __init__(self, **kwargs):
super(Scene, self).__init__(**kwargs)
def draw_circle(self):
with self.canvas:
Color=(1,0,0)
circ = Ellipse(pos = (self.center_x, self.center_y), size=(20,20))
def on_touch_down(self, touch):
pass
class Game(BoxLayout):
def __init__ (self,**kwargs):
super(Game, self).__init__(**kwargs)
self.orientation = 'vertical'
but1 = Button(text = 'button 1')
self.add_widget(but1)
self.scene = Scene()
self.add_widget(self.scene)
class TestApp(App):
def build(self):
game = Game()
game.scene.draw_circle()
return game
if __name__ == '__main__':
TestApp().run()
You should define the size of your float layout when you create it.
self.scene = Scene(size=(300, 300))
Then your circle should be at the center of the FloatLayout dimensions.
I also think FloatLayout is better used with size_hint and pos_hint instead of fixed coordinates.
You can call draw_circle with Clock to make sure the layout is completely initiated first.
Then make sure to create your color like this Color(1, 0, 0). Not Color = ()
from kivy.config import Config
Config.set('graphics','resizable', False)
from kivy.app import App
from kivy.graphics import Color, Ellipse
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.clock import Clock
class Scene(FloatLayout):
def draw_circle(self, dt):
with self.canvas:
Color(1,0,0)
circ = Ellipse(pos = (self.center_x, self.center_y), size=(20,20))
class Game(BoxLayout):
def __init__ (self,**kwargs):
super(Game, self).__init__(**kwargs)
self.orientation = 'vertical'
but1 = Button(text = 'button 1')
self.add_widget(but1)
self.scene = Scene()
self.add_widget(self.scene)
class TestApp(App):
def build(self):
game = Game()
Clock.schedule_once(game.scene.draw_circle) # call draw_circle on next frame
return game
if __name__ == '__main__':
TestApp().run()
I want to make a game and I have chosen Kivy for my GUI, as I have written my backend in Python. I am currently using runTouchApp(appwindow) to run the application, where appwindow is a FloatLayout() object. The way I update my screen is that I run appwindow.clear_widgets() and then appwindow.add_widget(new_screen) where new_screen is the layout object which contains all other widgets.
It worked fine till now, but for some reason I can't understand the widget I add gets loaded properly (according to the cmd running in the background) but won't display till I change the screen size.
Here is a sample code:
import kivy
kivy.require('1.1.1')
from kivy.base import runTouchApp
from kivy.uix.button import Button
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.image import Image
appwindow = FloatLayout()
class MenuScreen():
def build(self):
bg = Image(source = 'Images/bg/bg.jpg',allow_stretch= True,keep_ratio= False)
box = BoxLayout(orientation = 'vertical')
menu_items = []
for i in range (0,4):
button = Button(text = 'Menu item no:'+str(i))
button.bind(state = checkMenuPress)
menu_items.append(button)
for button in menu_items:
box.add_widget(button)
floater = FloatLayout(size = bg.size)
floater.add_widget(bg)
floater.add_widget(box)
floater.size_hint = 1,1
return floater
class SecondScreen():
def build(self):
bg = Image(source = 'Images/bg/bg.jpg',allow_stretch= True,keep_ratio= False)
box = BoxLayout(orientation = 'vertical')
box.add_widget(bg)
return box
def checkMenuPress(button,*args):
if button.state == 'normal':
sc = SecondScreen().build()
appwindow.clear_widgets()
appwindow.add_widget(sc)
if __name__ == '__main__':
menuscreen = MenuScreen().build()
appwindow.add_widget(menuscreen)
runTouchApp(appwindow)
Okay, there are a few things wrong here. To create an app, you should subclass kivy.app.App and have it's build method return the "root" widget. Only this class needs build method: any others are redundant.
Once you have a root widget, it's just a matter of inserting and removing widgets. This is how I would approach it.
import kivy
kivy.require('1.1.1')
from kivy.uix.button import Button
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.image import Image
from kivy.app import App
class MenuScreen(App):
floater = None
def build(self):
bg = Image(source='Images/bg/bg.jpg',
allow_stretch= True,
keep_ratio= False)
box = BoxLayout(orientation='vertical')
menu_items = []
for i in range(0, 4):
button = Button(text='Menu item no:'+str(i))
button.bind(state=self.checkMenuPress)
menu_items.append(button)
for button in menu_items:
box.add_widget(button)
self.floater = FloatLayout(size=bg.size)
self.floater.add_widget(bg)
self.floater.add_widget(box)
self.floater.size_hint = 1, 1
return self.floater
def checkMenuPress(self, button,*args):
if button.state == 'normal':
self.floater.clear_widgets()
self.floater.add_widget(SecondScreen())
class SecondScreen(FloatLayout):
def __init__(self, **kwargs):
super(SecondScreen, self).__init__(**kwargs)
self.add_widget(Image(source='Images/bg/bg.jpg',
allow_stretch=True,
keep_ratio=False))
if __name__ == '__main__':
MenuScreen().run()
Okay, so here's a quick rework of the example using Screens. It's difficult without knowing what you are trying to do, so if this does not help, try writing summary of the behavior you are looking for.
from kivy.uix.button import Button
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.image import Image
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
class MenuScreen(Screen):
"""
The Screen containing the menu
"""
def __init__(self, sm, **kwargs):
super(MenuScreen, self).__init__(**kwargs)
self.sm = sm # Store a reference to the screen manager
bg = Image(source='Images/bg/bg.jpg',
allow_stretch= True,
keep_ratio= False)
box = BoxLayout(orientation='vertical')
menu_items = []
for i in range(0, 4):
button = Button(text='Menu item no:'+str(i))
button.bind(state=self.check_menu_press)
menu_items.append(button)
for button in menu_items:
box.add_widget(button)
floater = FloatLayout(size=bg.size)
floater.add_widget(bg)
floater.add_widget(box)
floater.size_hint = 1, 1
self.add_widget(floater)
def check_menu_press(self, button, *args):
if button.state == 'normal':
self.sm.current = "second"
class SecondScreen(Screen):
def __init__(self, sm, **kwargs):
super(SecondScreen, self).__init__(**kwargs)
self.add_widget(Image(source='Images/bg/bg.jpg',
allow_stretch=True,
keep_ratio=False))
self.sm = sm # Store a reference to the screen manager
def on_touch_down(self, touch):
self.sm.current = "menu"
class MainApp(App):
def build(self):
sm = ScreenManager()
sm.add_widget(MenuScreen(sm, name="menu"))
sm.add_widget(SecondScreen(sm, name="second"))
return sm
if __name__ == '__main__':
MainApp().run()
looks like i have found a source of the crashing problem. I had used multi-threading for a server client interaction. i had been using two extra threads, one for the server and another for the client. If i try to integrate the client thread with the GUI it raises another problem. even if the socket.recv() is after the ScreenManager.current = "newscreen" line, the app's screen does not change. it freezes in the way i left it. it resumes only after it gets a message from the server.