LibGDX Tutorial - Creating a User Interface Part 1

    Dealing further with the libGDX library, I got to the com.badlogic.gdx.scenes.scene2d.ui package. This package is designed to create a user interface. And here disappointment awaited me: there is no tutorial article. Therefore, I decided to independently deal with the package using the sources and Javadoc documentation. That is, it will be a tutorial on scene2d.ui, but not a translation. I will not describe constructors, methods in detail here, or provide detailed signatures. I will try to take a bird's-eye view, because knowing the principles, you can always learn more from the documentation. But even with this approach, there is too much material, so I will break it into two (possibly more) articles.

    Recall the previous article and what we said about the Stage class. The Stage class can contain and manage actors (Actor). Also, there is the Group class, which is both an actor and a container for an actor. So, all the visual components from the scene2d.ua package are inherited from either Actor or Group. Accordingly, Group heirs may contain other components. We will look at these components later, and now take a look at the heirs of Actor. The direct descendant is the Widget class, and the following six components are inherited from it: Label, TextField, Image, List, SelectBox, Slider.

    It should be noted that all visual components implement the Layout interface. This interface is needed for the correct placement of components in container components. It provides methods for redrawing a component, determining the preferred, minimum, maximum size.

    Another important concept is style. Inside, almost every graphic component has a static class called <ComponentName> Style. For example, LabelStyle. This class stores the resources necessary for the correct operation of this class - for example, font, font color, etc. The fact is that OpenGL cannot directly render fonts, so some additional mechanisms are needed. The obvious option is to create a picture with images of letters and a text file that describes where which letter is located. Then from this description you can make a class that can "build" lines of text from individual letter-pictures. Here is an example of the LabelStyle class from the Label class:

    static public class LabelStyle {
    		public BitmapFont font;
    		/** Optional. */
    		public Color fontColor;
    		public LabelStyle () {
    		}
    		public LabelStyle (BitmapFont font, Color fontColor) {
    			this.font = font;
    			this.fontColor = fontColor;
    		}
    	}
    


    Some fields are marked as optional by the comment. This means that they can not be described in the style description in the settings file.

    The Skin class is used to store styles. The Skin class reads styles from a file from the settings and stores them internally. Then, when creating a new graphic component, we pass Skin to it in the constructor. If there is a suitable style, it is used. If not, an exception is thrown. Here is an example of a simple settings class, where a style is defined for only one component - Label:

    {
      	resources: {
      		com.badlogic.gdx.graphics.Color: {
      			black: { r: 0, g: 0, b: 0, a: 1 }
      		},
      		com.badlogic.gdx.graphics.g2d.BitmapFont: {
      			default-font: { file: default.fnt }
      		}
      	},
      	styles: {
      		com.badlogic.gdx.scenes.scene2d.ui.Label$LabelStyle: {
      			default: {
      				font: default-font, fontColor: black
      			}
      		}
      	}
    }
    


    Some comments. This file is written in JSON format. The first section is resources. black is the color defined in the RGBA model. default-font is the name of the font. I took the font from the com.badlogic.utils package, where they were called arial-15.fnt and arial-15.png. The second section is directly styles. Here we have identified one font that has been given a font and font color. Note that the names of the fields in the file correspond to the names of public fields in the style classes. You can define several styles for each component with different names. You can get the desired style using the getStyle (Class type, String name) method of the Skin class. By default, you pass the Skin component to the constructor and from it the component takes a style called default.

    For the settings file, it is necessary that the image file of the same name be in the same directory, but with the extension png. If, for example, you named the SimpleSkin settings file, then the graphic file will be called SimpleSkin.png. It is necessary if you use resources like TextureRegion. Without this file, the program will throw an exception and will not start.

    It should be noted that there are no Russian letters in this font file. I have not yet figured out this issue in detail, so there will be no Russian text in the examples.

    We now turn in more detail to the individual components, their styles and uses.

    Label


    It is a simple text label with the ability to wrap text in words. It has several designers, the most important, in my opinion, the following two:
    public Label (Skin skin)
    
    - creates a label without text.
    public Label (String text, Skin skin)
    
    - creates a label with text.
    There are methods for setting and returning the style - setStyle (), getStyle (), a method for setting the text setText (), and a method for setting the wrapping according to the words setWrapt (). By default, word wrap is disabled. To use it, first set the preferred size to the label (preferred size).
    Otherwise, the properties of the component are not of particular interest, the control of its location, rotation, etc. implemented in the same way as the Actor class.

    The component style class. Apparently, he needs only a font and font color.

    ...
    static public class LabelStyle {
    		public BitmapFont font;
    		/** Optional. */
    		public Color fontColor;
    		public LabelStyle () {
    		}
    		public LabelStyle (BitmapFont font, Color fontColor) {
    			this.font = font;
    			this.fontColor = fontColor;
    		}
    	} 
    ...
    


    Resources corresponding to this class from the settings file:

    resources: {
      		com.badlogic.gdx.graphics.Color: {
      			black: { r: 0, g: 0, b: 0, a: 1 }
      		},
      		com.badlogic.gdx.graphics.g2d.BitmapFont: {
      			default-font: { file: default.fnt }
      		}
      	},
      	styles: {
      		com.badlogic.gdx.scenes.scene2d.ui.Label$LabelStyle: {
      			default: {
      				font: default-font, fontColor: black
      			}
      		}
      	}
    


    Usage example:

    ...
    Skin skin = new Skin(Gdx.files.internal("data/skins/SimpleSkin"));
    Label label = new Label("I am label", skin);
    label.x = 10;
    label.y = 10;
    stage.add(label);
    ...
    


    Textfield


    The next class is TextField. It is a text input field. This class is already more curious, because you can assign a listener to it. The libGDX library was written using the “followers-readers” pattern, but limited - you can install only one listener. The listener is set by the setTextFieldListener () method, which takes a parameter of type TextFieldListener. This is the interface, here is its code:

    ...
    static public interface TextFieldListener {
    	public void keyTyped (TextField textField, char key);
    }
    ...
    


    Apparently, one event is processed - the character is entered.

    The class has several constructors. We will describe two main ones, in my opinion:

    TextField(String text, Skin skin)
    
    - creates a text box with text

    TextField(Skin skin)
    
    - creates an empty text field.

    Some methods of the class:
    setText()
    
    - sets the text
    setPasswordMode()
    
    - instead of the text, the characters that you select using the setPasswordCharacter () method will be displayed
    setMessageText()
    
    - sets a hint text that will be displayed if you have not entered anything in the text field.

    TextField supports copying and pasting text on a PC with standard keys. On Android, copying and pasting is not supported due to Android limitations.

    The component style class. As you can see, only the font is required:

    ...
    static public class TextFieldStyle {
    		/** Optional. */
    		public NinePatch background, cursor;
    		public BitmapFont font;
    		public Color fontColor;
    		/** Optional. */
    		public TextureRegion selection;
    		/** Optional. */
    		public BitmapFont messageFont;
    		/** Optional. */
    		public Color messageFontColor;
    ...
    


    Resources from the settings file:

    ...
    com.badlogic.gdx.scenes.scene2d.ui.TextField$TextFieldStyle: {
      			default: {
      				font: default-font, fontColor: black
      			}
      		}
    ...
    


    And an example of use:

    ...
    TextField textField = new TextField("I am text field", skin);
    textField.y = 30;
    stage.addActor(textField);
    ...
    


    Image



    The Image class is one of the few that does not require a style for its work. Therefore, its description will be quite brief. You can create an object of this class by several designers, one of the simplest is Image (TextureRegion region). The class supports a listener of type ClickListener. Here is the source for this interface:

    ...
    public interface ClickListener {
    	public void click (Actor actor, float x, float y);
    }
    ...
    


    That is, we can handle click events on our image.

    A useful method is setRegion (), which allows you to change the image. You can pass to the designer both the texture and its region. However, scaling, rotation will only work in the case of a texture region.

    Usage example:

    ...
    Image image = new Image(new Texture(Gdx.files.internal("data/skins/default.png")));
    image.y = 100;
    stage.addActor(image);
    ...
    


    This uses texture as a parameter for the constructor. In real applications, it is better to use TextureRegion.

    List



    The List class is a list of text fields with the ability to select a specific field. Analogue of List Swing, or ListBox from Delphi.
    Traditionally, it has several constructors, one of the simplest being List (Object [] items, Skin skin). It creates an object from a list from the items array. You can find out the selected element using the getSelection () method, and its index is getSelectedIndex (). You can set a new list using the setItems () method; you can make any item selected either by name or by index: setSelection (), setSelectionIndex (). List supports ListListener listener. Class source:

    ...
    public interface SelectionListener {
    	public void selected (Actor actor, int index, String value);
    } 
    ...
    


    The selected () method is called when an item is selected.

    Here is a style class:

    ...
    static public class ListStyle {
    	public BitmapFont font;
    	public Color fontColorSelected = new Color(1, 1, 1, 1);
    	public Color fontColorUnselected = new Color(1, 1, 1, 1);
    	public NinePatch selectedPatch;
    ...
    


    As we can see, the colors are already initialized, but the font and selectedPatch will have to be described. A small digression about NinePatch. This is a regular image (.png), in which 1-pixel edges contain some overhead information. This image is used for the selected item. You can read more details here habrahabr.ru/post/113623 Here are excerpts from the settings file that are responsible for our List:

    ...
    com.badlogic.gdx.graphics.g2d.NinePatch: {
      			default-nine : 
      				[
      				{width: 100, height: 100, x: 0, y: 0}
      				]
      		}
    ...
    com.badlogic.gdx.scenes.scene2d.ui.List$ListStyle: {
      			default: {
      				font: default-font, selectedPatch: default-nine
      			}
      		}
    ...
    


    And here is a usage example:

    ...
    List list = new List(new String[] {"Item 1", "Item 2", "Item 3", "Item 4", "Item 5"}, skin);
    list.x = 300;
    stage.addActor(list);
    ...
    


    Selectbox



    The SelectBox class is a drop-down list of several items. In the inactive state, this is a line that shows the selected item. When we activate it, we are shown a list of elements that can be selected by pressing. It has several constructors, the simplest - SelectBox (Object [] items, Skin skin) - creates a drop-down list of elements. The first item is considered selected. The rest of the class is very similar to List. It supports the same listeners as the List - SelectionListener, has the same methods for manipulating list items. Here is a style class:

    ...
    static public class SelectBoxStyle {
    public NinePatch background;
    public NinePatch listBackground;
    public NinePatch listSelection;
    public BitmapFont font;
    public Color fontColor = new Color(1, 1, 1, 1);
    public float itemSpacing = 10;
    ...
    


    As we can see, three NinePatch-a and a font need mandatory initialization.

    Here are excerpts from the settings file:

    ...
    com.badlogic.gdx.scenes.scene2d.ui.SelectBox$SelectBoxStyle: {
      			default: {
      				font: default-font, background: default-nine, listBackground: default-nine, listSelection: default-nine
      			}
      		}
    ...
    


    Usage example:

    ...
    SelectBox selectBox = new SelectBox(new String[] {"Item 1", "Item 2", "Item 3"}, skin);
    selectBox.x = 400;
    stage.addActor(selectBox);
    ...
    


    Slider



    The last Widget descendant class. The Slider class is a slider with maximum and minimum values. The user can change the value of the slider by dragging and dropping. The class has several constructors with the specification of the maximum, minimum values, number of steps. The simplest is Slider (Skin skin). It will create a slider with a maximum value of 100 and a minimum of 0 with a number of gradations of 100. The class can handle value change events using a class of type ValueChangedListener:

    ...
    static public interface ValueChangedListener {
    		public void changed (Slider slider, float value);
    	}
    ...
    


    When you change the value of the slider, the changed () method is called.

    A style class requires two parameters:

    ...
    static public class SliderStyle {
    		NinePatch slider; //Фон ползунка. Растягивается только по горизонтали.
    		TextureRegion knob; // Изображение части, которую мы передвигаем.
    ...
    


    Here are the pieces of code from the settings file:

    ...
    com.badlogic.gdx.graphics.g2d.TextureRegion: {
      			default-region: {width: 10, height: 12, x: 0, y: 0}
      		}
    ...
    com.badlogic.gdx.scenes.scene2d.ui.Slider$SliderStyle: {
      			default: {
      				slider: default-nine, knob: default-region
      			}
      		}
    ...
    


    And here is a usage example:

    ...
    Slider slider = new Slider(skin);
    stage.addActor(slider);
    ...
    


    The first part of the scene2d.ui package review is complete. Let me remind you that we considered only those classes that are inherited from Widget. There is still a large half of the container classes — windows, lists, scrollable lists, panels, etc. These include the (Button) button. As soon as time appears, I will write a sequel, where I will consider the rest of the classes.

    Application: a project with a demonstration of opportunities.
    Appendix: class diagram compiled by me in the ArgoUML program.

    Also popular now: