I consider the default look and feel of Java plainly horrible, it resemble shiny effects of the 90’s. Well, it was created around then, and it hasn’t evolved since:

parameters

Although there is alternative themes, they all have their problems. The ones included in Java (such as Nimbus) feel equally old, inherit the Look and feel of the OS carries a lot of problems with compatibility, and using external libraries is a hassle in terms of packaging and licensing.

I have learnt a couple of things of design (please ignore my website design) in the last few years, and I decided that there are three basic problems with the default Java Look and Feel.

  1. The bold titles occupy too much space
  2. The shiny buttons are cheesy
  3. The buttons are bulky

It is a combination of cheesyness and bulkyness. So, let’s quickly improve this. First, we need a method to change the font of all the interface components.

private static void setUIFont (javax.swing.plaf.FontUIResource f){
    Enumeration<object width="300" height="150"> keys = UIManager.getDefaults().keys();
    while (keys.hasMoreElements()) {
        Object key = keys.nextElement();
        Object value = UIManager.get (key);
        if (value != null && value instanceof javax.swing.plaf.FontUIResource)
            UIManager.put (key, f);
    }
} 

Once that is done, we will change (1) the font of the components, (2) remove the metal shiny color for a plain gray, and (3) add a modest line border:

    setUIFont (new javax.swing.plaf.FontUIResource("Sans Serif",Font.PLAIN,12));
    UIManager.put("Button.background",  Color.decode("#eeeeee"));
    UIManager.put("ToggleButton.background",  Color.decode("#eeeeee"));
    UIManager.put("Button.border", new CompoundBorder(new LineBorder(new Color(200, 200, 200)), new EmptyBorder(2, 2, 2, 2)));
    UIManager.put("ToggleButton.border", new CompoundBorder(new LineBorder(new Color(200, 200, 200)), new EmptyBorder(2, 2, 2, 2)));
    // call on the JFrame

The previous code should be added just before you call the JFrame. Here is the result:

parametersafter

It is not perfect, but I would say that now it is decent. Here is another couple of images of another interface of my Cultural Simulator:

Before:

before

After:

after

You probably have noticed that there are many widgets in Kivy that lack a property to set the background color. This is mainly because the widgets of Kivy are thought to be the simplest as possible to avoid unnecessary overload.

The good news is that extend and create new widgets in Kivy is extremely easy. Here is an example of how to have our personalized widget with a background color property. I am applying this to a Label because a lot of people have asked and it seems like an expected property to have. Nonetheless, the below technique could be applied to any particular Widget class – and certainly to other things different than just colors in the canvas.

Here is the code for our LabelB:

from kivy.uix.label import Label
from kivy.properties import ListProperty

from kivy.factory import Factory
from kivy.lang import Builder

Builder.load_string("""
<LabelB>:
  bcolor: 1, 1, 1, 1
  canvas.before:
    Color:
      rgba: self.bcolor
    Rectangle:
      pos: self.pos
      size: self.size
""")

class LabelB(Label):
  bcolor = ListProperty([1,1,1,1])

Factory.register('KivyB', module='LabelB')

We create a class that contains the bcolor property. Properties are extremely useful and powerful, and basically are the ones that keep our interface updated when the user (or the application internally) interacts with it. If you want to understand properties you can check the Kivy Documentation, or my book is load with examples :).

But adding the property to the class is obviously not enough. We need to link the property with the actual color of the the background. We create the background of the Label with a Rectangle (in the same position and of the same size of the Label), and set the color of the canvas to self.bcolor, i.e. the value contained in the list property we just created.

The Kivy Factory (last line) gives the final trick to integrate our new BLabel to the available Kivy classes in the Kivy Language.

And that is it!. Here is an example of how to use the class. Notice that all we need to do is change the bcolor property and the color adjusts accordingly.

import kivy
from kivy.uix.gridlayout import GridLayout

from kivy.app import App
from kivy.lang import Builder

import LabelB

Builder.load_string("""
<MyGrid>:
  rows: 2
  LabelB:
    bcolor: 1,0,0,1
  LabelB:
    bcolor: 0,1,0,1
""")

class MyGrid(GridLayout):
    pass

class TheApp(App):
    def build(self):
        return MyGrid()

TheApp().run()

And here is the final screenshot.

Screenshot from 2015-07-15 13:23:58

6926OS After many revisions and reviews, the 2nd Edition of my book has been published. I have updated all the content to Kivy 1.9.0. I introduce some new topics of that Kivy release including Behaviors, ActionBar and PageLayout. It also contains a complete new chapter that explains how reproduce and stream video, and add subtitles to it.

I hope people enjoy this edition!

Find it here! or the main online stores

I dreamed to write a book once. I didn’t know what I was going to write about, but I thought it was going to be some science divulgation stuff. I was not worried about selling any copies, just write it for the pleasure of it.

The science divulgation book hasn’t happen… yet, but the book did and specially selling copies. The solely fact that 800 people have picked the book, and look at their pages make me shiver. I never imagined this to happen, but I can say is it feels good.

And, somehow, it reminds me that I have a blog and that I should write more often on it.