Welcome!
This is the community forum for my apps Pythonista and Editorial.
For individual support questions, you can also send an email. If you have a very short question or just want to say hello — I'm @olemoritz on Twitter.
UI label with italics?
-
I'm trying to create a label that has one of the words italicized for vocabulary lists, eg:
लाल laal red
नीला neela blue
...Is this possible? I only see Label.font and Label.text_color which seem to be for the whole label. Is it possible maybe to concatenate several labels with different attributes?
-
@peiriannydd, probably the easiest way about this would be to use ui.WebView and just put divs with whatever fonts and colors you want there. You would not even have to manage layout much.
Next easiest is to use separate labels, as you say. You can use for example ”ArialMT” and ”Arial-ItalicMT” fonts, or use the list here to find other combos. If you go this route, I would recommend anchors to make the ”label stacking” easy.
Most difficult option would be to use ObjC AttributedText to get the different styles within one label. Search the forum for ”AttributedText” for examples. @JonB and @cvp are probably the best experts around for this option.
-
@peiriannydd try this @JonB 's marvelous example here
-
-
@peiriannydd Quick and dirty
import ui from objc_util import * # main view v = ui.View() v.frame = (0,0,300,300) v.background_color = 'white' v.name = 'ui.Label with italic sub-part' # label l = ui.Label() l.frame = (10,10,200,32) t = 'लाल laal red' l.text = t l.font = ('ArialMT',20) v.add_subview(l) # italic sub-part UIFont = ObjCClass('UIFont').fontWithName_size_('Arial-ItalicMT',20) mystr = ObjCClass('NSMutableAttributedString').alloc().initWithString_(t) tt = 'red' st = t.find(tt) ll = len(tt) mystr.addAttribute_value_range_(ns('NSFont'),UIFont,NSRange(st,ll)) # red sub-part UIColor=ObjCClass('UIColor').redColor() mystr.addAttribute_value_range_(ns('NSColor'),UIColor,NSRange(st,ll)) lobj = ObjCInstance(l._objc_ptr) lobj.setAttributedText_(mystr) v.present('sheet')
-
You might also consider a table view , which is natural for this application...you don’t need to muck around with locations of all the elements, or deal with scrolling.
Tableviewcells have a few different cell styles to show a title (your word) and a subtitle (definition/translation) either below, or left or right aligned after the title.
For example using Pythonista, See https://forum.omz-software.com/topic/941/tableviewcell-detail_text_label/3
-
@cvp, I took your code and put an HTML-ish syntax around it. Now using this code:
from richlabel import RichLabel r = RichLabel( font=('Arial', 24), background_color='white', alignment=ui.ALIGN_CENTER, number_of_lines=0, ) r.set_rich_text("\n".join([ "Plain", "<f Zapfino><c red>Color</c></f>", "<b>Bold <i>italic</i></b>", "and <i><f system 32>just</f> italic</i>", ])) r.present('fullscreen')
... you get this:
The
c
orcolor
tag takes any Pythonista color definition (name, hex or tuple).f
orfont
tag expects a font name or a size or both.Code is here.
Would be good to hear ideas/alternatives on the markup syntax.
-
@mikael Nice, as usual...
-
@mikael very nice!
-
@mikael you could add an outline tag
# red sub-part UIColor=ObjCClass('UIColor').redColor() mystr.addAttribute_value_range_(ns('NSColor'),UIColor,NSRange(st,ll)) outlineWidth = -3 # width in percentage of font size # >0 => stroke only # <0 => stroke and fill color outlineColor = ObjCClass('UIColor').colorWithRed_green_blue_alpha_(0,0,0,1) mystr.addAttribute_value_range_(ns('NSStrokeColor'), outlineColor, NSRange(st,ll)) mystr.addAttribute_value_range_(ns('NSStrokeWidth'), outlineWidth, NSRange(st,ll))
-
@cvp, fancy!
Ok, so now there is an
o
oroutline
tag that you can use as-is or with an optional color and/or width. Results with this string:r.set_rich_text("\n".join([ "Plain", "<f Zapfino><c red>Color</c></f>", "<b>Bold <i>italic</i></b>", "and <i><f system 32>just</f> italic</i>", "Outlines:", "<o>DEFAULT</o>", "<o 3>THICK</o>", "<o 3 blue>COLORED</o>", "<o -2><c orange>FILLED</c></o>", ]))
... look like this:
-
@mikael sincerely, you're a champion
-
@cvp, now that you got me started, how could we say anything important without underlining it? (Strikethrough thrown in because it was just 4 extra lines of code.)
Underline tag is
u
orunderline
, strikethrough iss
orstrike
. Both take a suitable combination of style qualifiers:thick
,double
,dot
,dash
,dashdot
,dashdotdot
,byword
.So now with this:
"Plain", "<f Zapfino><c red>Color</c></f>", "<b>Bold <i>italic</i></b>", "and <i><f system 32>just</f> italic</i>\n", "<u>Outlines:</u>\n", "<o>DEFAULT</o>", "<o 3>THICK</o>", "<o 3 blue>COLORED</o>", "<o -2><c orange>FILLED</c></o>\n", "<s double byword>really not cool</s>"
... we get this:
-
@mikael one more time, whaaaa
-
@mikael and a last one for today
UIColor=ObjCClass('UIColor').redColor() mystr.addAttribute_value_range_(ns('NSColor'),UIColor,NSRange(st,ll)) shadow = ObjCClass('NSShadow').alloc().init() shadow.setShadowOffset_(CGSize(2,2)) shadowColor = ObjCClass('UIColor').colorWithRed_green_blue_alpha_(0,0,0,1) shadow.setShadowColor_(shadowColor) shadow.setShadowBlurRadius_(3) mystr.addAttribute_value_range_(ns('NSShadow'), shadow, NSRange(st,ll))
-
@cvp, you ruthless taskmaster!
So, no more
s
tag, you now need to use the longerstrike
orshadow
.shadow
can be customized with color (default'grey'
), offset (default(2,2)
) and blur (default3
).Now with:
"Plain", "<b>Bold <i>italic</i></b>", "and <i><f system 32>just</f> italic</i>", "", "<f Zapfino><c red>Color</c>", "<shadow>Shadow</shadow></f>", "<u>Outlines:</u>", "<b>", "<o>DEFAULT</o>", "<o blue>COLORED</o>", "<o -3><c orange>FILLED</c></o>", "</b>", "<strike double byword>really not cool</s>"
We get:
-
-
@mikael Finally, it is perhaps better to define the text in html and use standard functions
import ui from objc_util import * # main view v = ui.View() v.frame = (0,0,300,200) v.background_color = 'white' v.name = 'ui.Label with html' # label l = ui.Label() l.frame = (10,0,200,200) l.number_of_lines = 0 v.add_subview(l) html = """ <html> <head> <title>Title of the document</title> <style> .shadow { text-shadow: 2px 2px #1c87c9; } </style> </head> <body> <h2>Text-shadow property example</h2> <p>Some paragraph for example.</p> <p class="shadow">Some paragraph with the text-shadow property.</p> </body> </html> """ data = ns(html.encode()) mystr = ObjCClass('NSMutableAttributedString').alloc().initWithHTML_documentAttributes_(data,None) lobj = ObjCInstance(l._objc_ptr) lobj.setAttributedText_(mystr) v.present('sheet')
-
@cvp, ooo, cool. The solution that ends all solutions.
... Although, there are several things I do not like about HTML styling and layouts, so I might still use the other option if I need rich text in my labels.
One thing I meant to ask: what does the objc_ptr do? Code seems to work without it.
-