Pyqt5: How to format text without using QFont? - python

Well as the title already tells, I want to simply format a text without using QFont(). At the moment I'm using it like that:
font = QFont()
font.setBold(True)
label = QLabel()
label.setFont(font)
label.setText("Hello World!")
So far so good. But if I want to have a certain part in a text of a label bold, it gets quite annoying, because I have to create an extra QLabel and use setBold() and put this part into the right position. Is there a way (e.g. markdown) to bold a certain part of a text of a label?
Like that:
label = QLabel()
label.setText("**Hello** World!")

Qt uses a subset of HTML for rich text. This is also the default setting. Try:
label.setText("<b>Hello</b> World!")
The label text format is controlled by the textFormat property. The default is Auto, for possible values see https://doc.qt.io/qt-5/qt.html#TextFormat-enum.
If you use a recent version of Qt (at least 5.14) you can also use Markdown as you suggested:
label.setTextFormat(Qt.MarkdownText)
label.setText("**Hello** World!")
Reference: https://doc.qt.io/qt-5/richtext-html-subset.html

Related

How to filter PDF text by font?

PDF example
A PDF may contain multiple fonts, how can I only keep 1 font with the most words with Python?
disclaimer: I am the author of borb (the library I will use in this example)
Oddly enough, there is an fairly close match example in the borb examples repository for filtering by font. You can find that example here.
In this example, we extract all the text in a particular font in the PDF (e.g. all text written in Courier).
You can easily base yourself on this code to build something that checks the number of characters for each particular font (and at a later stage, return only the font with the most characters).
I'll repeat the example here for completeness:
import typing
from borb.pdf.document.document import Document
from borb.pdf.pdf import PDF
from borb.toolkit.text.font_name_filter import FontNameFilter
from borb.toolkit.text.simple_text_extraction import SimpleTextExtraction
def main():
# create FontNameFilter
l0: FontNameFilter = FontNameFilter("Courier")
# filtered text just gets passed to SimpleTextExtraction
l1: SimpleTextExtraction = SimpleTextExtraction()
l0.add_listener(l1)
# read the Document
doc: typing.Optional[Document] = None
with open("output.pdf", "rb") as in_file_handle:
doc = PDF.loads(in_file_handle, [l0])
# check whether we have read a Document
assert doc is not None
# print the names of the Fonts
print(l1.get_text_for_page(0))
if __name__ == "__main__":
main()
Aside from the imports, everything is quite straightforward. You specify the string of the font you want to filter on. This filter object will process the parsing/rendering of the PDF, and will only push events to its children if they are relevant (if the font information matches).
We add SimpleTextExtraction as its child, and so doing only get the text which is rendered in the desired font.
After we've set up this entire thing, we need to actually process (parse) the Document which is what happens in the next lines.
Some caveats:
PDF documents might contain so-called 'subset fonts'. This is when a font is artificially made smaller by throwing out unused letters. ie if a PDF never uses the 'uppercase X' letter then the font does not need to store information on how to render it. Typically, the names of subset fonts are not the same as those of their original font. You might get something like Courier+AEOKFF.
If this happens to be the case, check out the code of FontNameFilter and make another version that only checks the name using startswith, which out to do the trick.

Python Wand: how to get the text bolded?

How to generate bolded text using python wand library? I cant get it to work.
http://docs.wand-py.org/en/0.4.1/wand/drawing.html - regarding documentation styles that are supported:
'undefined;
'normal'
'italic'
'oblique'
'any'
there is no bold style?
sample usage i wanted to do a footer with a date that I get from contents file:
with Image(width=150, height=25,) as img:
draw.font_family = 'MS Reference Sans Serif'
draw.font_size = 14.0
draw.push()
draw.font_style = 'italics'
metrics = draw.get_font_metrics(img, contents['date'], multiline=False)
draw.text(int((img.width - metrics.text_width)/2), int((metrics.text_height)), contents['date'])
draw.pop()
draw(img)
img.save(filename='./temp/footer.png')
Maybe there is some way to make it bold in some quick way? Would really appreciate any help.
"bold" is not a font_style, it's a font_weight: http://docs.wand-py.org/en/0.4.1/wand/drawing.html#wand.drawing.Drawing.font_weight
And the integer values it takes are the values fonts typically use, where 400 is "normal" and 700 is "bold". (These are also used in CSS. See e.g. https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight#Common_weight_name_mapping.)
Although mercator offered a correct answer to the title question, this answer focusing on the nested question:
Maybe there is some way to make it bold in some quick way?
Try using the bold variant typeface directly.
Either specific the bold-font file provided by Microsoft ...
draw.font = 'refsanb.ttf`
... or use the font style with a "Bold" suffix.
draw.font_family = 'MS Reference Sans Serif Bold'

wxpython TextCtrl color specific part of the text

I'm using wxpython to create GUI with python, now, is there a way to color specific part of the text?
Example (using Tkinter):
http://i.stack.imgur.com/fGAVA.png
Here is my Print function:
def Print(self, String):
''' Print Received Data '''
self.text_serverLog.AppendText(datetime.now().strftime("[%H:%M:%S] " + String + "\n"))
I found the function SetForegroundColour but sadly its color the whole TextCtrl.
I'm using Win7, python 2.7, wxpython.
Thanks.
You can use the wx.TextCtrl in RichText mode by setting its style flag to wx.TE_RICH or wx.TE_RICH2. You can also use the aforementioned RichTextCtrl or the StyledTextCtrl (1 or 2). There's also FancyText, but I think that's more of a helper for drawing text than a real control the user can edit. Regardless, all of these widgets have examples in the wxPython demo package, which you can find at the wxPython website's download page.

Finding the currently selected tab of Ttk Notebook

I have a Ttk Notebook widget containing 8 Frames - so, 8 tabs. Each frame contains a Text widget. I have a button outside the Notebook widget, and I want to insert text into the current tabs Text widget when this button is pressed.
This would seem to require working out which widget in the Notebook is currently selected, but I can't seem to find how to do this. How would I find the currently selected tab?
Alternatively, how can I implement what I want to?
If it helps, here's the code for my notebook:
self.nb = Notebook(master)
self.nb.pack(fill='both', expand='yes', padx=10, pady=10)
self.frames = []
self.texts = []
for i in xrange(8):
self.frames.append(Frame())
self.nb.add(self.frames[i])
self.texts.append(Text(self.frames[i]))
self.texts[i].pack(fill='both')
You can retrieve the selected tab through select method. However, this method returns a tab_id which is not much useful as is. index convert it to the number of the selected tab.
>>> nb.select()
'.4299842480.4300630784'
>>> nb.index(nb.select())
2
Note that you coud also get more information about the selected tab using tab
>>> nb.tab(nb.select(), "text")
'mytab2'
You might look at Notebook reference documentation : http://docs.python.org/3/library/tkinter.ttk.html#notebook
You can get currently selected tab using the "current" keyword:
noteBook.index("current")
Check this website:
https://docs.python.org/2/library/ttk.html#tab-identifiers
24.2.5.3. Tab Identifiers
There are two simple ways to see which tab is selected:
nb.select() # returns the Tab NAME (string) of the current selection
and
nb.index('current') # returns the Tab INDEX (number) of the current selection
The .select() method can also be used to select which tab is currently active, via nb.select(tabId). Without the arg, it returns the tabId (in "name" form) of the current selection.
The .index(tabId) converts a tabId into a numerical index. It also can take the string "end" which will return the number of tabs. So, nb.index(tkinter.END) is like a len() method for a notebook widget.
When there are no tabs, .select() returns an empty string, but .index('current') throws an exception. So, if you want the index, I would say
if nb.select():
idx = nb.index('current')
is the best way to go.
In your particular case, you would probably want to grab the current notebook tab name and then convert that name into the actual child text widget, via the nametowidget() method, for manipulation. So...
tabName = notebook.select()
if tabName:
textWidget = notebook.nametowidget(tabName) # here, 'notebook' could be any widget
textWidget.insert(pos, text, tags)
The nametowidget(name) method maps a Tkinter name to the actual widget. It is a method callable by any actual widget.
I am not a expert at all but hope i can help with some "fresh eyes".
I imagine it could be something involving
def buttonclick():
somevariablename = focus_get()
#Print your text into the somevariable notebook could be
#something like(not sure about the syntax):
focusednotebook = somevariablename
focusednotebook.insert('1.0', 'your text here')
yourbutton = Button(parent, text = "button name", command = buttonclick)
yourbutton.pack()
Hope it works or get you in the right direction.
Please feel free to edit as I am fairly new here amd with python :-)
Getting the tageted tab in tk.Notebook it's easy all you have to do is to use the notebook object and target the index of the current tab. This can be done as follows
# creating a notebook object
notebook = ttk.Notebook(root, height=height, width=width, padding=20)
# Adding tabs
notebook.add(bin_tab, text="Binary Conversion")
notebook.add(oct_tab, text="Octal Conversion")
notebook.add(hex_tab, text="Hexadecimal Conversion")
print(notebook.index("current")) # returns 0, 1, 2depending on how many tabs you have in my case i have 3 which means index from 0 to 2

How can I change the font size in GTK?

Is there an easy way to change the font size of text elements in GTK? Right now the best I can do is do set_markup on a label, with something silly like:
lbl.set_markup("<span font_desc='Tahoma 5.4'>%s</span>" % text)
This 1) requires me to set the font , 2) seems like a lot of overhead (having to parse the markup), and 3) would make it annoying to change the font size of buttons and such. Is there a better way?
If you want to change font overall in your app(s), I'd leave this job to gtkrc (then becomes a google question, and "gtkrc font" query brings us to this ubuntu forums link which has the following snippet of the the gtkrc file):
style "font"
{
font_name = "Corbel 8"
}
widget_class "*" style "font"
gtk-font-name = "Corbel 8"
(replace the font with the one you/user need)
Then the user will get consistent experience and will be able to change the settings easily without need for them to poke in the code and without you needing to handle the overhead of maintaining your personal configuration-related code. I understand you can make this setting more specific if you have a more precise definition for the widget_class.
YMMV for different platforms, but AFAIK this file is always present at some location if GTK is being used, and allows to the user to be in charge of presentation details.
In C, you can do:
gtk_widget_modify_font(lbl, pango_font_description_from_string("Tahoma 5.4"));
In PyGTK, I believe it's something like:
pangoFont = pango.FontDescription("Tahoma 5.4")
lbl.modify_font(pangoFont)

Categories