Button with Image and Text

ui

#1

Hi,

I’m trying to create a custom button with text and image, I manage to do this as follow :

Screenshot_20180209_113513

public class ButtonImageText extends ButtonImage {

/**
 * @param createImage
 */
public ButtonImageText(Image createImage, String text) {
	super(createImage);
	m_image = createImage;

	m_style = new EditableStyle();
	m_style.setBackgroundColor(MicroEJColors.LOGIN_BUTTON_BG);
	m_style.setForegroundColor(Colors.BLACK);
	m_style.setFontProfile(new FontProfile("source_sans_pro", 20, Font.STYLE_PLAIN));
	m_style.setAlignment(GraphicsContext.HCENTER | GraphicsContext.VCENTER);
	m_style.setTextManager(new SimpleTextManager());
}

public void setText(String text) {
	m_text = text;
}

@Override
public void renderContent(GraphicsContext g, Style style, Rectangle bounds) {
	super.renderContent(g, style, bounds);

	Font font = StyleHelper.getFont(m_style);
	if (m_style.getTextManager() != null) {
		m_style.getTextManager().drawText(g, m_text, font, m_style.getForegroundColor(), bounds,
				m_style.getAlignment());
	}
}

private final Image m_image;
private String m_text;
private final EditableStyle m_style;

}

The issue is the font is not using the correct background color (blue) and I got a grey (initial style of the button). Is there another way to do so ?

Thank you


#2

Hello Charles,

The problem comes from the anti-aliasing policy during the drawing of your text on the background of your image button. Performance-wise, it will be better to set a non-transparent background so that the drawing is faster thanks to not reading the color of the pixels behind the text.

In your case, you use a plain image as the background that forces you to read the pixels when drawing the text.

It can be simply done by removing the background color of your GraphicsContext before drawing your text : g.removeBackgroundColor();

public class ButtonImageText extends ButtonImage {
    
    private final Image m_image;
    private String m_text;
    private final EditableStyle m_style;

    /**
     * @param createImage
     */
    public ButtonImageText(Image createImage, String text) {
       super(createImage);
       m_image = createImage;

       m_style = new EditableStyle();
       m_style.setBackgroundColor(MicroEJColors.LOGIN_BUTTON_BG);
       m_style.setForegroundColor(Colors.BLACK);
       m_style.setFontProfile(new FontProfile("source_sans_pro", 20, Font.STYLE_PLAIN));
       m_style.setAlignment(GraphicsContext.HCENTER | GraphicsContext.VCENTER);
       m_style.setTextManager(new SimpleTextManager());
    }

    public void setText(String text) {
    m_text = text;
    }

    @Override
    public void renderContent(GraphicsContext g, Style style, Rectangle bounds) {
        super.renderContent(g, style, bounds);
            
        // Remove the background from the graphics context before drawing the text
        g.removeBackgroundColor();

        Font font = StyleHelper.getFont(m_style);
        if (m_style.getTextManager() != null) {
	        m_style.getTextManager().drawText(g, m_text, font, m_style.getForegroundColor(), bounds,
		    	m_style.getAlignment());
        }
    }
}

Please note that it is also considered a good practice to set the styles of your components in an external class StylesheetPopulator.java and link it to your button using a class selector, for example :

// Sets the login button style.
style.clear();
style.setForegroundColor(Colors.BLACK);
style.setFontProfile(new FontProfile("source_sans_pro", 20, Font.STYLE_PLAIN));
style.setAlignment(GraphicsContext.HCENTER | GraphicsContext.VCENTER);
style.setTextManager(new SimpleTextManager());
Selector loginButtonSelector = new TypeSelector(ButtonImageText.class);
stylesheet.addRule(loginButtonSelector, style);

The best solution would be to use a normal button associated with a SimpleImageBackground that will also allow you to use the default events (onPressed…) :

MyPage.java

import ej.widget.basic.Button;
...
public class MyPage {
	Button btnvalid;

	public MyPage() {
	...
	btnvalid = new Button(NLSHelper.get(NLSMessages.LOGIN));
	btnvalid.addClassSelector("TMP");
	...
	}
}

StylesheetPopulator.java

public class StylesheetPopulator {
	...
	private static final int ACTIVE_FOREGROUND = MicroEJColors.POMEGRANATE;
	...
	// Set the style of my text button with an image background
	style.clear();
	style.setForegroundColor(Colors.BLACK);
	ej.microui.display.Image image = ej.microui.display.Image.createImage(Images.BLUE_BUTTON);
	style.setBackground(new SimpleImageBackground(image, ACTIVE_FOREGROUND, false));
	style.setDimension(new FixedDimension(image.getWidth(), image.getHeight()));
	style.setAlignment(GraphicsContext.HCENTER | GraphicsContext.VCENTER);
	style.setTextManager(new SimpleTextManager());
	Selector loginButtonSelector = new ClassSelector("TMP");
	stylesheet.addRule(loginButtonSelector, style);

	// Change the background image of my button when it is pressed (so that it is more dynamic on the screen)
	ej.microui.display.Image imagePressed = ej.microui.display.Image.createImage(Images.BLUE_BUTTON_PRESSED);
	style.setBackground(new SimpleImageBackground(imagePressed, ACTIVE_FOREGROUND, false));
	stylesheet.addRule(new AndCombinator(loginButtonSelector, new StateSelector(State.Active)), style);
	...
}

I hope this solution suits you. Don’t hesitate to come back at us if you need it.

Jean-Baptiste Piraux, MicroEJ.


Gray out or set dimmed a disabled widget
#3

Thank you it’s working fine !