So, the the tkinter text editor!
The editor obviously needs to have text styles, which need to change typed text to whatever formatting is currently selected, using tags. But the problem is that the tag name needs to change when the formatting changes, otherwise the tag would be applied to the whole text.
(This was a problem that I was struggling to identify for quite some time)
To avoid this, you would need a LOT of tags (like bold, both, calibri etc), so the code would look like this
if style == 'bold':
tag_add('bold', 'insert -1c', 'insert')
tag_configure('bold', font=('Calibri', 12, 'bold'))
if stlye == 'italic':
etc etc
This is awful code, and makes different fonts/sizes impossible.
Is there a correct way of organising multiple tags like this, something like
tag.add(currentstyle, 'insert -1c', 'insert')
tag.config(currentstyle, font=(currentfont, currentsize, currentweight, currentslant))
Thanks for your help
UPDATE
solved with no small amount of help from Bryan
tagname = '{}-{}-{}-{}'.format(font, fontsize, weight, slant)
textbox.tag_add(tagname, 'insert -1c', 'insert')
textbox.tag_configure(tagname, font=(font, fontsize, weight, slant))
now every tag has a unique name
Yes, you will need to create a unique tag for every different font you use. In practice this isn't so bad, because most documents only use 3-4 variations, or perhaps a worst case of maybe a dozen. The only real difficulty is that if you want both bold and italics you have to create a bold tag, an italics tag, and a bold-italics tag.
This is awful code, and makes different fonts/sizes impossible.
It doesn't make it impossible, just slightly difficult. Your code is actually pretty close to how you would do it.
When a user changes the style of a character, you need to create a canonical form for the style name by combining the current style and any new attributes. For example, if the character is currently bold 12 point and they change it to italic 14 point, the new tag might be "italic-12". If they want to keep the bold it might be "bold-italic-12". You then need to check for whether you have a tag by that name, and create it if you don't, then remove any previous font tag and add the new font tag.
This is really only a problem with fonts. For other attributes such as colors and borders you can simply use all the different tags separately (ie: if you create a tag for "background-blue" and "foreground-red", you can apply both of those tags separately to the text.
I provide an example that does something similar to this here: https://stackoverflow.com/a/3736494/7432
Related
I'm trying to scrape text from a website. Sometimes, the text is written in bullet points, sometimes just in plain text.
Text in Bullet points (XPath): /article/div[#class='border-bottom-grau'][1]/ul/li[1]
Text in Plain text (XPath): /article/div[#class='border-bottom-grau'][1]/p
I need the respectice text to be extracted (without div/ul/li/p tags etc). This is what I have tried so far:
info_Aufgabengebiet = info.xpath(".//article/div[#class='border-bottom-grau'][1][descendant::text()]").extract()
Output: see image Output
I also experimented with descendant-or-self, a /text() at the end, but neither worked. Simply, I want to extract all text no matter in bullet point or plain text. Pullet points should just be added, maybe with a ";" or ",".
Any help is much appreciated
Thanks
You can use XPath with combined conditions
"/article/div[#class='border-bottom-grau'][1]/ul/li[1] | /article/div[#class='border-bottom-grau'][1]/p"
The union operator | mentioned in the other answer is a good solution. Alternately, depending on your output needs, you might try
/article/div[#class='border-bottom-grau'][1]//*[self::p or self::li]
When adding slides via a modified python-pptx, placeholders appear for the slide number on each slide. Instead of the actual slide number, however, the words "Slide Number" appears in that field.
Other answers mention using a static text box, but we need the placeholder to be used, as we transfer create slides to a variety of client masters. A standard textbox would not correctly adjust to varied layouts. We also need the box to float, so that we can place photos behind it on some pages. Finally, it must be dynamic, as we often shuffle pages afterward, so passing it the index as a static number would cause issues.
Is there a string or command that can be inserted into the placeholder that would automatically pull the slide's position in the deck? The master uses the combination "<#>", but this doesn't work when passed as a string.
Apologies for my ignorance, I've only been working with python and python-pptx for a couple weeks (huge thanks to its creators!).
An "auto-update" slide-number in PowerPoint is a field. The XML looks like this:
<a:fld id="{1F4E2DE4-8ADA-4D4E-9951-90A1D26586E7}" type="slidenum">
<a:rPr lang="en-US" smtClean="0"/>
<a:t>2</a:t>
</a:fld>
So the short answer to your question is no. There is no string you can insert in a textbox that triggers this XML to be inserted and there is no API support for adding fields yet either.
The approach would be to get a <a:p> element for a textbox and insert this XML into it using lxml calls (a process commonly referred to as a "workaround function" in other python-pptx posts).
You can get the a:p element like so:
p = textbox.text_frame.paragraphs[0]._p
Something like this might work, and at least provides a sketch of that approach:
from pptx.oxml import parse_xml
from pptx.oxml.ns import nsdecls
# ---get a textbox paragraph element---
p = your_textbox.text_frame.paragraphs[0]._p
# ---add fld element---
fld_xml = (
'<a:fld %s id="{1F4E2DE4-8ADA-4D4E-9951-90A1D26586E7}" type="slidenum">\n'
' <a:rPr lang="en-US" smtClean="0"/>\n'
' <a:t>2</a:t>\n'
'</a:fld>\n' % nsdecls("a")
)
fld = parse_xml(fld_xml)
p.append(fld)
The number enclosed in the a:t element is the cached slide number and may not be automatically updated by PowerPoint when opening the presentation. If that's the case, you'll need to get it right when inserting, but it will be automatically updated when you shuffle slides.
i am trying to program text editor by using tkinter.
this is the mark function:
self.text.tag_add("Mark",tk.SEL_FIRST,tk.SEL_LAST)
self.text.tag_config("Mark",background="yellow",foreground="black")
and this is the unmark function
self.text.tag_add("UnMark",tk.SEL_FIRST,tk.SEL_LAST)
self.text.tag_config("UnMark",background="white",foreground = "black")
but the problem is when i mark the text and then unmark it, i cant mark it again.
the mark function dont work when i try to mark the text again that i unmarked it.
The reason is because the "UnMark" tag has a higher priority than the "Mark" tag. You can add the "Mark" tag, but the configuration of "UnMark" takes precedence.
I recommend instead of an "UnMark" tag, you simply remove the "Mark" tag when you don't want something to be marked.
I have had a program in PyQt5. The program have had a QTextEdit field for printing clear HTML using Python’s method html.escape(). Every string have added in the field using .append(). Some tags in some strings needed to be highlighted. And I have used next code:
self.textEdit.append('{0}{color}{1}{endcolor}{2}'.format(begin,
color_text, end, color='<font color="red">', endcolor='</font>')
Lately I found a module in Internet that can print strings number. This module use QPlainTextEdit. Also I found a module for syntax highlight, that was arranged by QSyntaxHighlighter and it’s for QPlainTextEdit too. It all works good, but now I can‘t highlight additional tags using code above. I have to highlight not only html syntax, but also additional some tags by other color. I tried to create another QSyntaxHighlighter that would highlight a whole text it get.
def format(color, style=''):
_color = QColor()
_color.setNamedColor(color)
_format = QTextCharFormat()
_format.setForeground(_color)
return _format
class PythonHighlighter (QSyntaxHighlighter):
def __init__(self, document):
QSyntaxHighlighter.__init__(self, document)
def highlightBlock(self, text):
self.setFormat(0, len(text), format('red'))
self.setCurrentBlockState(0)
Then in necessary place I write:
highlight = syntax.PythonHighlighter(self.textEdit.document())
self.textEdit.show()
self.textEdit.appendPlainText(...)
I thought to apply this highlighter to places of html that between{color} and {endcolor} above in code. Can I apply highlighter only to part of field? How? And if I can't, which are there methods to solve my problem?
P.S. Sorry for mistakes in my English. You can tell me about them.
Have somebody experencies with odfpy ?
I parsed document with this python package and I got paragraphs with his text and stylenames, now I need to detect which type of text font is in this paragraphs text?
Do you have any ideas ?
The styles are defined separately from the text. The nodes that contain text will be inside nodes that have a style as an attribute. An example might look like this:
<text:p text:style-name="P5">
<text:span text:style-name="T1">Do donkeys eat macadamia nuts? And if they don't, why don't they?
</text:span>
</text:p>
In this example, two styles (P5 or T1) might specify a font for the text. You will need to look at the document's style definition section.
This code will create a dictionary containing the document's styles.
def get_styles(doc):
styles= {}
for ast in doc.automaticstyles.childNodes:
name= ast.getAttribute('name')
style= {}
styles[name]= style
for k in ast.attributes.keys():
style[k[1]]= ast.attributes[k]
for n in ast.childNodes:
for k in n.attributes.keys():
style[n.qname[1] + "/" + k[1]]= n.attributes[k]
return styles
You can then examine the relevant styles that correspond to the text you care about. Inside each style will be a style:text-properties element, and that element will have a style:font-name attribute that specifies a font.