Kivy For The Non Computer Scientist – Part 17: Making Natural Looking GUI’s Using Kivy’s Float Layout.

In this blogpost we’ll look at how one can create more natural looking GUI’s by employing a background graphic and Kivy’s float layout. The post will also provide complete code and a background graphic, that place buttons and labels in precise locations for a 720p Jukebox interface. The interface is from the open source Convergence Jukebox project. The interface will appear as follows;

converge

Some things to understand before proceeding.

  • The GUI shown above and the code provided require that the graphic be rendered at 720p.
    • Only at 720p will all of the labels and buttons to line up appropriately in this example.
    • Assuming your display can handle 720p the GUI will render to that resolution when the code is run.
  • Float Layouts have unique properties in that;
    • Kivy Buttons and Labels (widgets) can be placed anywhere on the GUI.
    • Each widget type can be given both common and unique properties when deployed on the GUI itself.

The code for the above GUI is as follows;


import kivy
kivy.require("1.9.1")  # Used to alert user if this code is run on an earlier version of Kivy.
from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.lang import Builder
from kivy.core.window import Window  # Used to set Window to set window size and full screen

Window.fullscreen = False  # Does not force full screen
Window.size = (1280, 720)  # Sets 720p

Builder.load_string('''
<Label>: # Sets generic properties for Label instances. Can be overridden by changing properties in specific instance.
	color: 0,.7,0,1 # Sets Label generic text colour to green.
	font_size: 18 # Sets Label generic text font size to 18.
	valign: 'middle' # Sets Label generic text vertical alignment to middle.
	halign: 'left' # Sets Label generic text horizontal alignment to left.
	text_size: self.size # Forces text to be wrapped to fit Label size.
<Button>: # Sets generic properties for Button instances. Can be overridden by changing properties in specific instance.
	font_size: 18 # Sets Button generic font size to 18.
	color: 1,1,1,1 # Sets Button generic colour to white.
    bold: True # Sets Button generic text property to bold.
    background_normal: "" # Resets Button background default to plain.
    background_color: (0.0, 0.0, 0.0, 0.0) # Sets Button generic background colour to transparent.
    halign: 'center' # Sets Button generic horizontal alignment to center.
    valign: 'middle' # Sets Button generic vertical alignment to middle.
	text_size: self.size # Sets Button generic text to be wrapped to fit Button size.
	size_hint: .255, .0620 # Sets Button generic size.
<FloatLayout>:  # Creates a FloatLayout
    canvas.before:
        BorderImage: # Used to display background image.
            source: 'jukebox.png' # Background image filename.
            pos: self.pos # Positions image to take up 100% of layout.
            size: self.size # Positions image to take up 100% of layout.
	Label: # Creates an instance of Label on GUI. Properties below overide generic settings on this Label instance only.
	    id: sort_mode  # Identifies Label as sort_mode
	    text: "Sort Mode By Artist" # Text for this Label.
	    font_size: 38 # Overrides generic Label font size to 38 for this Label only.
	    halign: 'center' # Overrides generic Label horizontal alignment to center for this Label only.
	    size_hint: .3, 1 # Overrides generic Label size for this Label only.
		pos: 12,280 # Positions this label.
	Label: # Creates an instance of Label on GUI. Properties below overide generic settings on this Label instance only.
	    id: play_mode  # Identifies Label as sort_mode
	    text: "Mode: play_mode" # Text for this Label.
		pos: 40,245 # Positions this label.
	Label:
	    id: title_song
	    text: "Title: title_song"
		pos: 40,225
	Label:
	    id: title_artist
	    text: "Artist: title_artist"
		pos: 40,205
	Label:
	    id: title_year
	    text: "Year: 2017"
	    size_hint: 0.35, 1
		pos: 40,185
	Label:
	    id: title_length
	    text: "Length: title_length"
		pos: 135,185
	Label:
	    id: title_album
	    text: "Title: title_album"
		pos: 40,165
	Label:
	    id: sort_mode
	    text: "UPCOMING SELECTIONS"
	    font_size: 28
	    halign: 'center'
	    size_hint: .32, 1
		pos: 1,131
	Label:
	    id: selection_one
	    text: "selection_one"
		pos: 40,102
	Label:
	    id: selection_two
	    text: "selection_two"
		pos: 40,81
	Label:
	    id: selection_three
	    text: "selection_three"
		pos: 40,60
	Label:
	    id: selection_four
	    text: "selection_four"
		pos: 40,40
	Label:
	    id: selection_five
	    text: "selection_five"
		pos: 40,19
	Label:
	    id: selection_six
	    text: "selection_six"
		pos: 40,-1
	Label:
	    id: selection_seven
	    text: "selection_seven"
		pos: 40,-21
	Label:
	    id: selection_eight
	    text: "selection_eight"
		pos: 40,-41
	Label:
	    id: selection_nine
	    text: "selection_nine"
		pos: 40,-61
	Label:
	    id: selection_ten
	    text: "selection_ten"
		pos: 40,-81
	Label:
	    id: selection_eleven
	    text: "selection_eleven"
		pos: 40,-101
	Label:
	    id: selection_twelve
	    text: "selection_twelve"
		pos: 40,-121
	Label:
	    id: selection_thirteen
	    text: "selection_thirten"
		pos: 40,-141
	Label:
	    id: selection_fourteen
	    text: "selection_fourteen"
		pos: 40,-161
	Label:
	    id: selection_fifteen
	    text: "selection_fifteen"
		pos: 40,-181
	Label:
	    id: selection_sixteen
	    text: "selection_sixteen"
		pos: 40,-201
	Label:
	    id: credit_count
	    text: "CREDITS 0"
	    font_size: 34
	    halign: 'center'
	    size_hint: .3, 1
		pos: 12,-236
	Label:
	    text: "Twenty-Five Cents Per Selection"
	    halign: 'center'
	    size_hint: .3, 1
		pos: 12,-267
	Label:
	    id: selections_available
	    text: "selections_available"
	    halign: 'center'
	    size_hint: .3, 1
		pos: 12,-287
	Label:
	    id: jukebox_name
	    text: "Convergence Music System 2.0"
	    color: 0,0,0,1 # Sets text colour to black.
	    font_size: 38
	    bold: True
	    halign: 'center'
	    size_hint: .7, 1
		pos: 390,292
	Label:
	    id: song_name
	    text: "song_name"
	    color: 1,1,1,1 # Sets text colour to white.
	    font_size: 40
	    bold: True
	    halign: 'center'
	    size_hint: .7, 1
		pos: 390,230
	Label:
	    id: artist_name
	    text: "artist_name"
	    color: 1,1,1,1 # Sets text colour to white.
	    font_size: 40
	    bold: True
	    halign: 'center'
	    size_hint: .7, 1
		pos: 390,180
    Button: # Creates an instance of Button on GUI. Properties below overide generic settings on this Button instance only
	    id: song_0  # Identifies Button as song_0.
	    text: "song_0(Name)\\nsong_0(artist)" # Text for button includes line break.
		pos: 495,445 # Positions Button on GUI.
	Button:
	    id: song_1
	    text: "song_1(Name)\\nsong_1(artist)"
		pos: 495,390
	Button:
	    id: song_2
	    text: "song_2(Name)\\nsong_2(artist)"
		pos: 495,335
	Button:
	    id: song_3
	    text: "song_3(Name)\\nsong_3(artist)"
		pos: 495,280
	Button:
	    id: song_4
	    text: "song_4(Name)\\nsong_4(artist)"
		pos: 495,225
	Button:
	    id: song_5
	    text: "song_5(Name)\\nsong_5(artist)"
		pos: 495,170
	Button:
	    id: song_6
	    text: "song_6(Name)\\nsong_6(artist)"
		pos: 495,115
	Button:
	    id: song_7
	    text: "song_7(Name)\\nsong_7(artist)"
		pos: 495,60
	Button:
	    id: song_8
	    text: "song_8(Name)\\nsong_8(artist)"
		pos: 835,445
	Button:
	    id: song_9
	    text: "song_9(Name)\\nsong_9(artist)"
		pos: 835,390
	Button:
	    id: song_10
	    text: "song_10(Name)\\nsong_10(artist)"
		pos: 835,335
	Button:
	    id: song_11
	    text: "song_11(Name)\\nsong_11(artist)"
		pos: 835,280
	Button:
	    id: song_12
	    text: "song_12(Name)\\nsong_12(artist)"
		pos: 835,225
	Button:
	    id: song_13
	    text: "song_13(Name)\\nsong_13(artist)"
		pos: 835,170
	Button:
	    id: song_14
	    text: "song_14(Name)\\nsong_14(artist)"
		pos: 835,115
	Button:
	    id: song_15
	    text: "song_15(Name)\\nsong_15(artist)"
		pos: 835,60

''')

class RootWidget(FloatLayout):
    pass

class MainApp(App):
    def build(self):
        return RootWidget()

MainApp().run()

You’ll also need this graphic and ensure its named jukebox.png and it’s placed in the same directory as the above code;

jukebox

You can download this graphic by right mouse clicking and performing a Save As or by clicking on the link above.

Here are some of the new items you’ll find in the code;

  • Lines 12 and 18 – These lines establish generic properties for first the Label instances (line 12 and below) and then the Button instances (line 18 and below) when they are called.
    • In FloatLayouts these generic properties can be overridden by changing properties when a specific instance is established.
    • By setting up generic properties in this manner, the KV Language code is reduced significantly when instances are called.
      • In this app 45 instances of Buttons and Labels are created.
    • All lines involved in establishing the generic properties have comments as to what they do.
  • Line 23 – Code that sets Button generic background colour to transparent.
  • Lines 29 thru 33 – Code places and sets up GUI’s background image.
    • Comments provide insight into role each property plays
  • Lines 34 thru 40 – Code lays out first Label on Gui. Lines are commented so you know what function they play.
    • Any properties declared on these lines that match generic properties, override generic settings for this instance only.
  • Lines 39 and 40 – size_hint and pos properties work in concert with one another to set Label position. size_hint sets size of Label. pos positions top left corner of label.
    • Positioning is one of the hardest things to explain in a FloatLayout. I just kept changing both the size_hint and pos values until Labels lined up.
  • Lines 41 thru 44 – Code lays out second Label on Gui. Comments define what each line of code does.
  • Lines 45 thru 245 – Code for the remainder of Labels and Buttons on Gui following principles outlined above.
  • Lines 182 – 185 – Code for first Button placed on GUI.
  • Line 184 – Text for button using a line break.

To conclude the great thing about using a FloatLayout is the ability to place a widget with great accuracy on your Kivy GUI. As well, the use of a background image and transparent button overlays as performed in this example makes for a much more natural looking interface for your user.

In this case we have a layout that displays all of the widget’s object names. Based on what was presented in earlier blogposts in this series, the Buttons and Labels texts can be updated accordingly as well as callbacks added to buttons to provide the desired functionality.

Happy coding,

….brad….

Advertisements

4 Responses

  1. […] You can find more about what I’ve been learning about Kivy by following a series of blogposts starting with Kivy For The Non Computer Scientist – Part 1: Making It Simple. And more specifically you can look at Kivy For The Non Computer Scientist – Part 17: Making Natural Looking GUI’s Using Kivy’s Float…. […]

  2. […] things up  for this blog post. The next blog post Kivy For The Non Computer Scientist – Part 17: Making Natural Looking GUI’s Using Kivy’s Float…. will focus on more natural looking Kivy GUI […]

  3. […] trying to update the screen built in Part 17: Making Natural Looking GUI’s Using Kivy’s Float Layout of this series I could not figure out how to update the text on the various buttons and labels that […]

  4. […] Part 17: Making Natural Looking GUI’s Using Kivy’s Float Layout. […]

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: