Python: Create strikethrough / strikeout / overstrike string type
Question:
I would appreciate some help in creating a function that iterates through a string and combines each character with a strikethrough character (u0336). With the output being a striked out version of the original string. Like this..
Something like.
def strike(text):
i = 0
new_text = ''
while i < len(text):
new_text = new_text + (text[i] + u'u0336')
i = i + 1
return(new_text)
So far I’ve only been able to concatenate rather than combine.
Answers:
def strike(text):
result = ''
for c in text:
result = result + c + 'u0336'
return result
Cool effect.
How about:
from itertools import repeat, chain
''.join(chain.from_iterable(zip(text, repeat('u0336'))))
or even more simply,
'u0336'.join(text) + 'u0336'
Edited
As pointed out by roippi other answers so far are actually correct, and this one below is wrong. Leaving it here in case others get the same wrong idea that I did.
Other answers so far are wrong – they do not strike out the first character of the string. Try this instead:
def strike(text):
return ''.join([u'u0336{}'.format(c) for c in text])
>>> print(strike('this should do the trick'))
'̶t̶h̶i̶s̶ ̶s̶h̶o̶u̶l̶d̶ ̶d̶o̶ ̶t̶h̶e̶ ̶t̶r̶i̶c̶k'
This will work in Python 2 and Python 3.
If you want to include spaces in the strikethrough, you’ll have to replace normal spaces with non-break spaces:
def strikethrough(mytext):
''' replacing space with 'non-break space' and striking through'''
return("u0336".join(mytext.replace(" ","u00a0"))+ "u0336")
Although 'u0336'
can solve some problems, it may not work in different language situations.
Like: 我是誰 → ̶我̶是̶誰.
As you can see, the otherwise good text has turned into strange symbols that we can’t read.
So I write the code below:
import tkinter as tk
root = tk.Tk()
root.state('zoomed')
class strikethrough(tk.Frame):
def __init__(self, frame, text, **options):
super().__init__(frame)
c = tk.Canvas(self, **options)
textId = c.create_text(0, 0, text = text, fill = "#FFFFFF", font = ("", 30, "bold"))
x1, y1, x2, y2 = c.bbox(textId)
linewidth = 3
lineXOffset = 3
lineId = c.create_line(x1, 0, x2, 0, width=linewidth)
c.pack(fill="both", expand=1)
c.bind("<Configure>", lambda event: TextPositionChange(c, textId, lineId, linewidth, lineXOffset))
self.canvas, self.textId = c, textId
def TextPositionChange(canvas, TextId, LineId, LineWidth, LineXOffset):
x1, y1, x2, y2 = canvas.bbox(TextId)
xOffSet, yOffSet = (x2-x1)/2, (y2-y1)/2
x, y = canvas.winfo_width()/2-xOffSet, canvas.winfo_height()/2-yOffSet #left_top_position
canvas.moveto(TextId, x, y)
canvas.moveto(LineId, x-LineXOffset, y+(y2-y1)/2-LineWidth/2)
frame = strikethrough(root, "我是誰", bg="#777777")
frame.place(relx=0.5, rely=0.5, relwidth=0.5, anchor="center")
root.mainloop()
I would appreciate some help in creating a function that iterates through a string and combines each character with a strikethrough character (u0336). With the output being a striked out version of the original string. Like this..
Something like.
def strike(text):
i = 0
new_text = ''
while i < len(text):
new_text = new_text + (text[i] + u'u0336')
i = i + 1
return(new_text)
So far I’ve only been able to concatenate rather than combine.
def strike(text):
result = ''
for c in text:
result = result + c + 'u0336'
return result
Cool effect.
How about:
from itertools import repeat, chain
''.join(chain.from_iterable(zip(text, repeat('u0336'))))
or even more simply,
'u0336'.join(text) + 'u0336'
Edited
As pointed out by roippi other answers so far are actually correct, and this one below is wrong. Leaving it here in case others get the same wrong idea that I did.
Other answers so far are wrong – they do not strike out the first character of the string. Try this instead:
def strike(text):
return ''.join([u'u0336{}'.format(c) for c in text])
>>> print(strike('this should do the trick'))
'̶t̶h̶i̶s̶ ̶s̶h̶o̶u̶l̶d̶ ̶d̶o̶ ̶t̶h̶e̶ ̶t̶r̶i̶c̶k'
This will work in Python 2 and Python 3.
If you want to include spaces in the strikethrough, you’ll have to replace normal spaces with non-break spaces:
def strikethrough(mytext):
''' replacing space with 'non-break space' and striking through'''
return("u0336".join(mytext.replace(" ","u00a0"))+ "u0336")
Although 'u0336'
can solve some problems, it may not work in different language situations.
Like: 我是誰 → ̶我̶是̶誰.
As you can see, the otherwise good text has turned into strange symbols that we can’t read.
So I write the code below:
import tkinter as tk
root = tk.Tk()
root.state('zoomed')
class strikethrough(tk.Frame):
def __init__(self, frame, text, **options):
super().__init__(frame)
c = tk.Canvas(self, **options)
textId = c.create_text(0, 0, text = text, fill = "#FFFFFF", font = ("", 30, "bold"))
x1, y1, x2, y2 = c.bbox(textId)
linewidth = 3
lineXOffset = 3
lineId = c.create_line(x1, 0, x2, 0, width=linewidth)
c.pack(fill="both", expand=1)
c.bind("<Configure>", lambda event: TextPositionChange(c, textId, lineId, linewidth, lineXOffset))
self.canvas, self.textId = c, textId
def TextPositionChange(canvas, TextId, LineId, LineWidth, LineXOffset):
x1, y1, x2, y2 = canvas.bbox(TextId)
xOffSet, yOffSet = (x2-x1)/2, (y2-y1)/2
x, y = canvas.winfo_width()/2-xOffSet, canvas.winfo_height()/2-yOffSet #left_top_position
canvas.moveto(TextId, x, y)
canvas.moveto(LineId, x-LineXOffset, y+(y2-y1)/2-LineWidth/2)
frame = strikethrough(root, "我是誰", bg="#777777")
frame.place(relx=0.5, rely=0.5, relwidth=0.5, anchor="center")
root.mainloop()