In the code below I have a second screen, and I tried to add two buttons to this screen, but one button is on top of the other, I can see it when I use label instead.
I need to add each Label on a row or column because at the moment I cant even read the Label text.
This is how I add the label to new screen:
self.new_screen.add_widget(Label(text='LABEL NUMER 1'))
self.new_screen.add_widget(Label(text='THIS IS THE LABEL NUMBER 2'))
full code:
import kivy
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.gridlayout import GridLayout
from kivy.uix.button import Button
from kivy.uix.screenmanager import ScreenManager, Screen
class Grid(GridLayout):
def __init__(self, **kwargs):
super(Grid, self).__init__(**kwargs)
self.rows= 3
self.titlet = Label(text='MAIN SCREEN')
self.add_widget(self.titlet)
self.MainGrid = GridLayout()
self.MainGrid.cols = 2
self.b4 = Button(text="Botao")
self.MainGrid.add_widget(self.b4)
self.add_widget(self.MainGrid)
class MyScreenManager(ScreenManager):
def __init__(self, **kwargs):
super(MyScreenManager, self).__init__(**kwargs)
self.main_screen = Screen(name="main_screen")
self.new_screen = Screen(name="new_screen")
self.add_widget(self.main_screen)
self.add_widget(self.new_screen)
self.grid = Grid()
self.grid.b4.bind(on_press=self.change_screen)
self.new_screen.cols = 2
self.new_screen.add_widget(Label(text='LABEL NUMER 1'))
self.new_screen.add_widget(Label(text='THIS IS THE LABEL NUMBER 2'))
self.main_screen
self.main_screen.add_widget(self.grid)
def change_screen(self, *args):
self.current = "new_screen"
class MyApp(App):
def build(self):
return MyScreenManager()
if __name__ == "__main__":
MyApp().run()
In the same way that you have established a layout on the first Screen you must do it with the second Screen, in this case you must use BoxLayout:
from kivy.uix.boxlayout import BoxLayout
# ...
class MyScreenManager(ScreenManager):
def __init__(self, **kwargs):
super(MyScreenManager, self).__init__(**kwargs)
self.main_screen = Screen(name="main_screen")
self.new_screen = Screen(name="new_screen")
self.add_widget(self.main_screen)
self.add_widget(self.new_screen)
self.grid = Grid()
self.grid.b4.bind(on_press=self.change_screen)
box_layout = BoxLayout(orientation="vertical")
self.new_screen.add_widget(box_layout)
box_layout.add_widget(Label(text='LABEL NUMER 1'))
box_layout.add_widget(Label(text='THIS IS THE LABEL NUMBER 2'))
self.main_screen.add_widget(self.grid)
# ...
Related
import kivy
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.textinput import TextInput
from kivy.uix.gridlayout import GridLayout
from kivy.uix.button import Button
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.behaviors import ButtonBehavior
from kivy.uix.image import Image
class FirstPage(GridLayout, ButtonBehavior, Image):
def __init__(self, **kwargs):
super(FirstPage, self).__init__(**kwargs)
self.cols =2
self.row_force_default = True
self.row_default_height = 100
self.add_widget(Label(text='Enter Name: '))
self.name = TextInput(multiline=False)
self.add_widget(self.name)
self.submit_name = Button(text = 'Submit name', font_size = 30)
self.submit_name.bind(on_press = self.sub_name)
self.add_widget(Label())
self.add_widget(self.submit_name)
def sub_name(self, instance):
if self.name.text == '':
name_error = Label(text= 'Please put your name')
self.add_widget(Label())
self.add_widget(name_error)
else:
name = Label(text = 'Hello' + ' ' + self.name.text)
self.add_widget(Label())
self.add_widget(name)
self.inside = FloatLayout()
self.inside.cols = 1
self.add_widget(self.inside)
self.title = Label(text ='[b]Please choose your country[/b] ' + f'[b]{self.name.text}
[/b]',pos=(200,200), markup=True )
self.inside.add_widget(self.title)
self.pic = Image(source='unitedkingdom.png', on_press=self.ha)
self.inside.add_widget(self.pic)
def ha(self, instance):
print('ha')
class WeatherApp(App):
def build(self):
return FirstPage()
if __name__ == '__main__':
WeatherApp().run()
I want to make the image act as a button however when i run the app i get a random white box and my picture doesn't at as a button. Does this have to do with the way i added the button behaviour, any suggestions are appreciated. In addition could the answers please be in python code because i have some problems with my computer that does not allow me to use a kv file, thanks.
class united_k(ButtonBehavior, Image):
def __init__(self, **kwargs):
super(united_k, self).__init__(**kwargs)
self.pic = Image(source='unitedkingdom.png', on_press=self.ha)
self.inside.add_widget(self.pic)
def ha(self, instance):
print('ha')
i created this new class under the class above and it still did not work, if possible could you write out the code in order to help me understand
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.
How to resolve widget overlapping in kivy framework, I am adding widgets in for cycle so I have more than one widget but all of them comes to be in one place, how can I prevent this?
My python code:
from kivy.app import App
from kivymd.app import MDApp
from kivy.uix.label import Label
from kivy.clock import Clock
from kivy.graphics import Color
from kivy.uix.widget import Widget
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.uix.gridlayout import GridLayout
from kivymd.uix.card import MDCard
from kivy.properties import StringProperty
from kivy.lang import Builder
import requests, time, collections
class request_sender():
return 'DATA'
class CustomLabel(Label):
pass
class CustomBox(BoxLayout):
pass
class AuctionCard(Widget):
auc_timer = ''
auc_img = ''
auc_name = ''
def __init__(self, **kwargs):
super(AuctionCard, self).__init__(**kwargs)
with self.canvas.before: Color(1, 0, .4, mode='rgb')
Clock.schedule_once(self.load_info)
def load_info(self, dt):
print(self.auc_name)
self.size_hint = None, None
box = BoxLayout(orientation='vertical', size = (800, 600))
box.size_hint_x = 50;
box.height = 100
AuctionName = CustomLabel(text=self.auc_name, pos_hint={'top': 300.9})
AuctionImage = CustomLabel(text=self.auc_img)
AuctionTimer = CustomLabel(text=self.auc_name)
box.add_widget(AuctionName)
box.add_widget(AuctionTimer)
box.add_widget(AuctionImage)
self.add_widget(box)
class MyWidget(Widget):
prop = StringProperty('')
array_of_labels = []
prop1 = StringProperty('Second card')
n = 0
all_cards = collections.defaultdict()
def __init__(self, **kwargs):
super(MyWidget, self).__init__(**kwargs)
self.screen_load()
def timer_le(self, dt):
returned_data = request_sender().sender_update('ajax.php')
for key in self.all_cards:
for data in returned_data:
if data['pid'] == key:
self.all_cards[key][0].text = str(data['remaining_time'])
def screen_load(self):
returned_data = request_sender().sender_update('ajax.php')
box = GridLayout(cols=2)
self.size_hint = None, None
for data in returned_data:
AucCard = AuctionCard()
AucCard.auc_name = str(data['auc_name'])+'\n\n'
AucCard.auc_timer = str(data['remaining_time'])+'\n\n'
AucCard.auc_img = str(data['auc_img'])+'\n\n'
box.add_widget(AucCard)
print('Widget added')
self.add_widget(box)
#self.all_cards[str(data['pid'])] = [AucCard]
#Clock.schedule_interval(self.timer_le, 1/30)
class TestApp(App):
def build(self):
box = GridLayout(cols=2)
return MyWidget()
TestApp().run()
My kv code:
<CustomLabel>:
size_hint_y: None
text_size: self.width, None
height: self.texture_size[1]
Result:
Kind of result that I want to create:
Actually I found easy way to solve this issue. The problem was in parent class of my AuctionCard and MyWidget classes, I set parent class to Widget but for the AuctionCard it should be BoxLayout and for MyWidget GridLayout. So from there I managed to set cols = 2 and size to window.size. From here it works exactly how it should work.
from kivy.lang import Builder
from kivy.app import App
from kivy.core.window import Window
from kivy.uix.widget import Widget
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.clock import Clock
from kivy.uix.gridlayout import GridLayout
class AuctionCard(BoxLayout):
auc_timer = ''
auc_img = ''
auc_name = ''
def __init__(self, **kwargs):
super(AuctionCard, self).__init__(**kwargs)
Clock.schedule_once(self.load_info)
def load_info(self, dt):
self.orientation = 'vertical'
AuctionName = Label(text=self.auc_name)
AuctionImage = Label(text=self.auc_img)
AuctionTimer = Label(text=self.auc_timer)
self.add_widget(AuctionName)
self.add_widget(AuctionTimer)
self.add_widget(AuctionImage)
class MyWidget(GridLayout):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.cols = 2
self.size = (Window.size[0], self.size[1])
self.load_app()
print('MyWidget size: '+str(self.size))
def load_app(self):
self.size_hint = None, None
returned_data = [{'auc_name':'name 1', 'remaining_time':'100', 'auc_img':'https://img.src'},
{'auc_name':'name 2', 'remaining_time':'200', 'auc_img':'https://img.src'},
{'auc_name':'name 3', 'remaining_time':'300', 'auc_img':'https://img.src'}]
for data in returned_data:
AucCard = AuctionCard()
AucCard.auc_name = str(data['auc_name'])+'\n\n'
AucCard.auc_timer = str(data['remaining_time'])+'\n\n'
AucCard.auc_img = str(data['auc_img'])+'\n\n'
self.add_widget(AucCard)
print('Widget added')
class MyTestApp(App):
def __init__(self, **kwargs):
self.title = "My Material Application"
super().__init__(**kwargs)
def build(self):
return MyWidget()
if __name__ == "__main__":
MyTestApp().run()
Result:
Result
i'm using kivy for building an app screen with 3 screens.
my main screen ( class Base) is showing data from a SQL request.
i would like the user to be able to update these data using a button.
first this class Base is called in the screen manager which is itself called in my root class.
So my question is , how do i clear the data in my class Base and update it with the new data?
i tried to clear the data in my class screen manager.
the refresh function is called from the root class.
i have the below error:
'ScreenManager uses remove_widget only for removing Screens'
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.button import Button
from kivy.uix.label import Label
from sql import runsql2
from kivy.core.window import Window
class Manager(ScreenManager):
def __init__(self):
super(Manager, self).__init__()
for i in range(2):
txt = 'Screen {}'.format(i)
lbl = Label(text=txt)
screen = Screen(name=txt)
screen.add_widget(lbl)
self.add_widget(screen)
base=Base('main')
self.add_widget(base)
def refresh(self):
self.clear_widgets(screens='main')
base=Base('main')
self.add_widget(base)
class Nav(GridLayout):
def __init__(self,sm=None):
super(Nav, self).__init__()
self.sm = sm
self.cols =3
self.size_hint = (1,0.1)
self.add_widget(Button(text="Clearing Screen", on_release=self.change))
self.add_widget(Button(text="Go screen 2", on_release=self.goscreen))
self.add_widget(Button(text="Quit", on_release=self.quit))
def change(self, btn):
#self.sm.current = btn.text
self.sm.current='main'
def quit(self,ins):
exit()
def goscreen(self,ins):
self.sm.current='Screen 1'
class Base(Screen):
def __init__(self,name):
super(Base, self).__init__()
self.lay=GridLayout()
self.name=name
self.bout=['[color=33ff99]Refresh[/color]','',"","","","","","","","",""]
self.data=runsql2()
self.lay.cols = 11
self.titre=['[color=ff9900]Market[/color]', '[color=ff9900]B/S[/color]', '[color=ff9900]Volume[/color]', '[color=ff9900]Contract[/color]',
'[color=ff9900]C/P[/color]', '[color=ff9900]Expiry[/color]', '[color=ff9900]Strike[/color]', '[color=ff9900]Price[/color]',
'[color=ff9900]Account[/color]', '[color=ff9900]Give up Member[/color]', '[color=ff9900]Allocation Account[/color]']
#self.lay.add_widget(Button(text='[color=33ff99]Refresh[/color]', size_hint=(1, 0.15), markup=True,on_release=self.do))
for i in range(11):
self.lay.add_widget(Label(text='', size_hint=(1, 0.15)))
for j in range(11):
self.lay.add_widget(Label(text=str(self.titre[j]),size_hint=(0.2,0.2),markup=True))
long = len(self.data)
for i in range(long):
for j in range(11):
self.lay.add_widget(Label(text=str(self.data[i][j])))
self.add_widget(self.lay)
class Root(BoxLayout):
def __init__(self):
super(Root, self).__init__()
self.orientation = "vertical"
#Window.clearcolor = (0.6, 0.6, 0.6,1)
sm = Manager()
self.add_widget(Nav(sm=sm))
self.add_widget(sm)
self.add_widget(Button(text='refresh',size_hint=(0.2,0.2),on_release=self.refresh))
Window.size = (1500, 900)
def refresh(self,ins):
sm=Manager()
sm.refresh()
class TestApp(App):
def build(App):
return Root()
if __name__ == '__main__':
TestApp().run()
Two problems with your code. First, in your refresh() method, the self.clear_widgets(screens='main') is incorrect. The screens arg must be a list of screens. So it should be
def refresh(self):
self.clear_widgets(screens=[self.get_screen('main')])
base=Base('main')
self.add_widget(base)
Since you are only removing one screen, you could use self.remove_widget(self.get_screen('main')) instead.
And, second, your refresh() method in the Root class is creating a new Manager class and calling the refresh() method of that new Manager rather than the one you have displayed. To correct this, you can save a reference to the original Manager, and use that reference in the refresh() method:
class Root(BoxLayout):
def __init__(self):
super(Root, self).__init__()
self.orientation = "vertical"
#Window.clearcolor = (0.6, 0.6, 0.6,1)
sm = Manager()
self.sm = sm # keep a reference for later use
self.add_widget(Nav(sm=sm))
self.add_widget(sm)
self.add_widget(Button(text='refresh',size_hint=(0.2,0.2),on_release=self.refresh))
Window.size = (1500, 900)
def refresh(self,ins):
self.sm.refresh()
I'm trying to make a screen that has two rows, one of those rows are the actual game screen and the another one is a button to clear the table above. But the problem here is that the first row is blank when I run the app. That's the code that I am stuck till now:
import kivy
from kivy.app import App
from kivy.uix.screenmanager import Screen, ScreenManager
from kivy.uix.gridlayout import GridLayout
from kivy.uix.button import Button
kivy.require('1.9.2')
class VelhaGame(GridLayout, Screen):
def __init__(self, **kwargs):
super(VelhaGame, self).__init__(**kwargs)
self.cols = 3
self.rows = 3
self.font_size = 100
self.buttons = []
for i in range(9):
button = Button(text='', font_size=self.font_size)
button.bind(on_release=self.player_turn)
self.add_widget(button)
self.buttons.append(button)
self.player1 = True
def player_turn(self, button, *args):
if self.player1 and button.text == '':
self.player1 = False
button.text = 'X'
elif not self.player1 and button.text == '':
self.player1 = True
button.text = 'O'
class MainMenu(GridLayout, Screen):
def __init__(self, **kwargs):
super(MainMenu, self).__init__(**kwargs)
self.cols = 1
self.rows = 2
self.button_play = Button(text='PLAY', font_size=40)
self.button_play.bind(on_release=self.play)
self.add_widget(self.button_play)
self.button_exit = Button(text='EXIT', font_size=40)
self.button_exit.bind(on_release=self.exit)
self.add_widget(self.button_exit)
def play(self, *args):
screen_manager.current = 'velhaPage'
def exit(self, *args):
App.get_running_app().stop()
game_screen_manager = ScreenManager()
game_screen_manager.add_widget(VelhaGame(name='velhaGame'))
class VelhaScreen(GridLayout, Screen):
def __init__(self, **kwargs):
super(VelhaScreen, self).__init__(**kwargs)
self.rows = 2
self.add_widget(game_screen_manager)
self.clear_button = Button(text='Clear', font_size=40)
self.add_widget(self.clear_button)
screen_manager = ScreenManager()
screen_manager.add_widget(MainMenu(name='menu'))
screen_manager.add_widget(VelhaScreen(name='velhaPage'))
class VelhaGameApp(App):
def build(self):
return screen_manager
if __name__ == '__main__':
VelhaGameApp().run()
Do you know what I could do to accomplish this task?
The answer to you question, is "You cannot do that".
Screenmanager only shows one screen at a time.
you can read about that in the docs https://kivy.org/docs/api-kivy.uix.screenmanager.html
But to acheive something like you are trying to, you could do like this:
Instead of screens inside another screen, you could put the gridlayout, and button inside a vertical orientated boxlayout like this:
import kivy
from kivy.app import App
from kivy.uix.screenmanager import Screen, ScreenManager
from kivy.uix.gridlayout import GridLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.properties import ListProperty
kivy.require('1.9.1')
class VelhaGame(Screen):
buttons = ListProperty([])
def __init__(self, **kwargs):
super(VelhaGame, self).__init__(**kwargs)
self.game_window = BoxLayout(orientation="vertical")
self.add_widget(self.game_window)
self.game_table = GridLayout(cols=3,rows=3)
for i in range(9):
button = Button(text='', font_size="100sp")
button.bind(on_release=self.player_turn)
self.game_table.add_widget(button)
self.buttons.append(button)
self.player1 = True
self.clear_button = Button(on_press=self.clear,text='Clear', font_size="40sp")
self.game_window.add_widget(self.game_table)
self.game_window.add_widget(self.clear_button)
def clear(self,*args):
for button in self.buttons:
button.text = ""
def player_turn(self, button, *args):
if self.player1 and button.text == '':
self.player1 = False
button.text = 'X'
elif not self.player1 and button.text == '':
self.player1 = True
button.text = 'O'
class MainMenu(GridLayout, Screen):
def __init__(self, **kwargs):
super(MainMenu, self).__init__(**kwargs)
self.cols = 1
self.rows = 2
self.button_play = Button(text='PLAY', font_size="40sp")
self.button_play.bind(on_release=self.play)
self.add_widget(self.button_play)
self.button_exit = Button(text='EXIT', font_size=40)
self.button_exit.bind(on_release=self.exit)
self.add_widget(self.button_exit)
def play(self, *args):
screen_manager.current = 'velhaPage'
def exit(self, *args):
App.get_running_app().stop()
screen_manager = ScreenManager()
screen_manager.add_widget(MainMenu(name='menu'))
screen_manager.add_widget(VelhaGame(name='velhaPage'))
class VelhaGameApp(App):
def build(self):
return screen_manager
if __name__ == '__main__':
VelhaGameApp().run()