I recently started to get in to Kivy and now I am trying to create app for me and my friends which is a D&D sheet. I wanted to have all the important stats in one tab in which you can scroll down so that the text font doesn't have to be that small but I can't get it working with the self.minimum_height property of the GridLayout that will contain other elements.
I am running kivy version 1.10.0
If I set the height manually the ScrollView works just fine.
Here is my .kv file
<TabbedPanel>:
do_default_tab: False
tab_pos: 'bottom_mid'
tab_width: self.width / 4
TabbedPanelItem:
text: "Character"
ScrollView:
size_hint: (1, None)
height: root.height
GridLayout:
cols: 1
size_hint_y: None
height: self.minimum_height
Button:
text: "Hello"
Button:
text: "Hello"
Button:
text: "Hello"
Button:
text: "Hello"
Button:
text: "Hello"
Button:
text: "Hello"
Button:
text: "Hello"
Button:
text: "Hello"
Button:
text: "Hello"
Button:
text: "Hello"
Button:
text: "Hello"
Button:
text: "Hello"
Button:
text: "Hello"
Button:
text: "Hello"
Button:
text: "Hello"
TabbedPanelItem:
text: "Weap's & Mods"
TabbedPanelItem:
text: "Vehicle"
TabbedPanelItem:
text: "Vehicle Upgr"
You need to also set an explicit height for each contained widget, so that the GridLayout can add them together to calculate its minimum height. For instance, in your example you could add the following lines to each button:
size_hint_y: None
height: dp(30)
Cant comment yet, so have to make a separate answer:
You could make:
<My_button>(Button):
size_hint_y: None
height: dp(30)
And use that in your Gridlayout. That would save repeating it for each entry.
Related
I have a dropdown menu in which I would like to know which value the user has selected so I can use it later in my program. This is my .kv code:
BoxLayout:
orientation: 'horizontal'
size_hint_x: 1
Button:
pos_hint:{'center_x': .5, 'center_y': .5}
id: units_num_btn
text: '0'
size_hint_y: None
height: 44
on_parent: drop_player_numbers_units.dismiss()
on_release: drop_player_numbers_units.open(self)
DropDown:
id: drop_player_numbers_units
on_select: units_num_btn.text = '{}'.format(args[1])
on_select: app.return_player_numbers()
Button:
id: units_num_btn_1
text: '1'
size_hint_y: None
height: 35
on_release: drop_player_numbers_units.select('1')
Button:
id: units_num_btn_2
text: '2'
size_hint_y: None
height: 35
on_release: drop_player_numbers_units.select('2')
and so on.
My .py code is here:
class drop_content(DropDown):
pass
class PlayerScreen(Screen):
pass
class TheApp(App):
def build(self):
sm = ScreenManager()
sm.add_widget(PlayerScreen(name='player_setup'))
sm.current = 'player_setup'
return sm
def main():
Builder.load_file('menu.kv')
app = TheApp()
app.run()
if __name__ == '__main__':
main()
I have previously used a function such as this:
# .py example
def return_text(self):
text = self.root.get_screen('screen').ids.specific_id.text
print(text)
# .kv example
TextInput:
id: input
text: "2"
on_text: app.return_text()
which did return text using a Textinput type in my .kv file. I know it doesn't work for the dropdown menu since the text is not inputted in the same way. Do you know how I would do this?
Thanks in advance
from kivy.app import App
from kivy.uix.dropdown import DropDown
from kivy.uix.screenmanager import Screen,ScreenManager
from kivy.lang.builder import Builder
class TestScreen(Screen):
def return_player_numbers(self,play_number):
print('Test : ',play_number)
kv = '''
ScreenManager:
TestScreen:
<TestScreen>:
BoxLayout:
orientation: 'horizontal'
size_hint_x: 1
Button:
pos_hint:{'center_x': .5, 'center_y': .5}
id: units_num_btn
text: '0'
size_hint_y: None
height: 44
on_parent: drop_player_numbers_units.dismiss()
on_release: drop_player_numbers_units.open(self)
DropDown:
id: drop_player_numbers_units
on_select:
units_num_btn.text = '{}'.format(args[1])
app.root.current_screen.return_player_numbers(args[1])
app.return_player_numbers(args[1])
Button:
id: units_num_btn_1
text: '1'
size_hint_y: None
height: 35
on_release: drop_player_numbers_units.select('1')
Button:
id: units_num_btn_2
text: '2'
size_hint_y: None
height: 35
on_release: drop_player_numbers_units.select('2')
'''
class TheApp(App):
def return_player_numbers(self,play_number):
print('App : ',play_number)
def build(self):
return Builder.load_string(kv)
if __name__ == '__main__':
TheApp().run()
I have found a way that I think is simpler than the current answer provided. This method uses that fact that the text on the button used to initiate the drop down changes as another button is selected. This is to show the user what they have selected. Since I want to know the text the user has selected from the drop down menu, and this is in fact the same thing that is updated on the initial button, I can just read the text from the button to obtatin my result like so:
(in .kv file)
<player_setup>
BoxLayout:
orientation: 'horizontal'
size_hint_x: 0.2
pos_hint: {'x':.4, 'y':0}
Button:
pos_hint:{'center_x': .5, 'center_y': .5}
id: tens_num_btn
text: '0'
size_hint_y: None
# size_hint_x: 0.1
height: 44
on_parent: drop_player_numbers_tens.dismiss()
on_release: drop_player_numbers_tens.open(self)
DropDown:
id: drop_player_numbers_tens
on_select:
#######
tens_num_btn.text = '{}'.format(args[1])
# this line here ^ is the one that re-formats the text of the button above to
# the selected text
app.return_player_numbers()
max_height: 120
(.py file)
def return_player_numbers(self):
player_number = self.root.get_screen('player_setup').ids.tens_num_btn.text
return player_number
This also allows me to concatenate multiple dropdown results using a single function, however it is menu specific. In my case, this works better for me
Last time I solved the error thanks to you.
However, due to my lack of skills,
I looked up a lot of data but couldn't solve the error.
If I click information Button happen this error message.
File "", line 27, in
NameError: name 'Factory' is not defined
I want to make Project. This Picture. But The Button location always not good.
This is My Python KIVY code
#project.kv file
kv = '''
BoxLayout:
orientation: 'vertical'
Upper_bar:
size_hint: (1, 0.1)
Label:
text: 'Select Mode'
BoxLayout:
padding: [90, 40]
size_hint: (1, 0.5)
orientation: 'horizontal'
Button:
size_hint: (0.5, 1)
text: 'Object'
BoxLayout:
Button:
size_hint: (0.5, 1)
text: 'Street'
<Upper_bar>:
BoxLayout:
Button:
size_hint: (0.3, 1)
text: 'Information'
on_press: Factory.InformationPop().open()
<InformationPop#Popup>:
size_hint: 0.5, 0.5
tittle: 'Information'
auto_dismiss: True
BoxLayout:
orientation: 'vertical'
Label:
text:
"""Name:
Student Number:
E-mail: """
Button:
text:
'Close'
on_press:
root.dismiss()
size_hint_y: None
height: '40dp'
'''
class Upper_bar(BoxLayout):
pass
class AIObjectCameraApp(App):
def build(self):
return Builder.load_string(kv)
if __name__ == '__main__':
AIObjectCameraApp().run()
You just forgot to add the import of Factory at the top of your kv string:
#:import Factory kivy.factory.Factory
First I'm new to kivy. myApp is based on kivy-example/demo/kivycatlog and I was modifying PopupContainer.kv, but my code doesn't work.
PopupContainer.kv
BoxLayout:
id: bl
orientation: "vertical"
popup: popup.__self__
canvas:
Color:
rgba: .18, .18, .18, .91
Rectangle:
size: self.size
pos: self.pos
Button:
id: showPopup1
text: 'press to show popup'
on_release: root.popup.open()
Button:
id: showPopup2
text: 'press to show popup'
on_release: root.popup.open()
Popup:
id: popup
on_parent: if self.parent == bl: bl.remove_widget(self)
title: "An example popup"
BoxLayout:
orientation: 'vertical'
BoxLayout:
orientation: 'vertical'
Button:
id: accept
text: "yes"
on_release: status.text = self.text
Button:
id: cancel
text: "no"
on_release: status.text = self.text
Label:
id: status
text: "yes or no?"
Button:
text: "press to dismiss"
on_release: popup.dismiss()
I want to change the text(showPopup) when I click on "yes" or "no"
on the showPopup's text.
You could get the text of your ShowPopup's buttons from your code. I mean declare a variable in your code named popups_text and in your .kv file try accesing it using root.popups_text. then create a method in your code that changes this text every time the button is pressed.
I have a basic app in Kivy with a class for each screen. I would like to have the user enter some text in one screen and for this to be displayed in a label on another screen.
I've been through all the similar posts but can't seem to get anything working.
The two classes EnterSentences and Review have ObjectProperties. Is there a way to connect these with bind? Or do I need to just structure things completely differently?
Any help much appreciated. Here's the .py file
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import ObjectProperty
class MainMenu(BoxLayout):
def enter_sentences_button(self):
self.clear_widgets()
self.add_widget(EnterSentences())
def review_button(self):
self.clear_widgets()
self.add_widget(Review())
def settings_button(self):
pass
class EnterSentences(BoxLayout):
search_box = ObjectProperty()
def main_menu(self):
self.clear_widgets()
self.add_widget(MainMenu())
class Review(BoxLayout):
sentence = ObjectProperty()
class NewApp(App):
pass
if __name__ == "__main__":
NewApp().run()
and the .kv file:
MainMenu
<MainMenu>:
orientation: 'vertical'
Label:
text: "Welcome to your Flash Card App!"
size_hint_y: 5
BoxLayout:
size_hint_y: 1
orientation: "horizontal"
Button:
text: "Enter sentences"
on_press: root.enter_sentences_button()
Button:
text: "Review"
on_press: root.review_button()
Button:
text: "Settings"
<EnterSentences>:
search_box: enter_sentence
orientation: "vertical"
Label:
text: "Enter your sentences here:"
size_hint_y: 4
TextInput:
id: enter_sentence
TextInput:
TextInput:
BoxLayout:
orientation: 'horizontal'
Button:
text: 'Main Menu'
on_press: root.main_menu()
Label:
text: ''
<Review>:
orientation: 'vertical'
Label:
size_hint_y: 4
text: root.search_box
TextInput:
size_hint_y: 1
You only have to change the kv file. You could add the text from the 3 TextInputs to 3 variables readable from the whole app:
TextInput:
+ on_text: app.sentence1=self.text
id: enter_sentence
TextInput:
+ on_text: app.sentence2=self.text
TextInput:
+ on_text: app.sentence3=self.text
Then you could access the new variables in the Review:
<Review>:
orientation: 'vertical'
Label:
size_hint_y: 4
text: app.sentence1 + "\n" + app.sentence2 + "\n" + app.sentence3
TextInput:
size_hint_y: 1
I'm creating a simple app interface using kivy and the kv language. The interface consists of a search text input, a button for search confirmation and an 'add' button. Bellow this, there is a TabbedPanel for the app's contents:
#:import label kivy.uix.label
#:import sla kivy.adapters.simplelistadapter
<MenuScreen>:
AnchorLayout:
anchor_x: 'left'
anchor_y: 'top'
BoxLayout:
orientation: 'vertical'
BoxLayout:
orientation: 'horizontal'
size_hint_y: 0.15
TextInput:
text: 'Search'
Button:
size_hint_x: 0.2
text: 'Ok'
Button:
size_hint_x: 0.2
text: '+'
TabbedPanel:
do_default_tab: False
TabbedPanelItem:
text: 'tab1'
ListView:
orientation: 'vertical'
adapter:
sla.SimpleListAdapter(
data=["Item #{0}".format(i) for i in range(100)],
cls=label.Label)
TabbedPanelItem:
text: 'tab2'
BoxLayout:
Label:
text: 'Second tab content area'
Button:
text: 'Button that does nothing'
TabbedPanelItem:
text: 'tab3'
RstDocument:
text:
'\\n'.join(("Hello world", "-----------",
"You are in the third tab."))
This is the design output:
The TabbedPannel works perfectly the way I desire, however I want the tabs to fill all the horizontal space. For instance, if I use a BoxLayout with Buttons, they expand using all the horizontal space, just as I want it:
BoxLayout:
orientation: 'horizontal'
size_hint_y: 0.1
Button:
text: 'tab1'
Button:
text: 'tab2'
Button:
text: 'tab3'
Is there a way to tune the TabbedPannel so its TabbedPannelItems tabs can use all the horizontal space?
Set the tab_width property of TabbedPanel to its width divided by number of tabs:
from kivy.app import App
from kivy.uix.tabbedpanel import TabbedPanel
from kivy.lang import Builder
Builder.load_string("""
<Test>:
do_default_tab: False
tab_width: self.size[0]/len(self.tab_list)
TabbedPanelItem:
text: 'tab 1'
TabbedPanelItem:
text: 'tab2'
TabbedPanelItem:
text: 'tab3'
""")
class Test(TabbedPanel):
pass
class TabbedPanelApp(App):
def build(self):
return Test()
if __name__ == '__main__':
TabbedPanelApp().run()