I want to add new line in the given cursor position in QTextEdit.
I tried what's below.
Here new line is added to the end:
self.textEdit.moveCursor(QTextCursor.PreviousWord)
self.textEdit.moveCursor(QTextCursor.PreviousWord)
self.textEdit.append()
This has no effects at all:
self.textEdit.moveCursor(QTextCursor.PreviousWord)
self.textEdit.moveCursor(QTextCursor.PreviousWord)
self.textEdit.insertHtml('<br>')
Calling setHtml or insertHtml with no actual content (text, resource, table, etc) will usually be ignored.
In this specific case, it's enough to add a blank space before or after the break:
self.textEdit.insertHtml('<br/> ')
Using append() will not work for a given position of the cursor, as the documentation explains:
Appends a new paragraph with text to the end of the text edit.
(emphasis mine)
Related
I've been trying to be more explicit in my assignment of character formats for a text editor so that I can understand what I might be able to customize with my current skill range. While the basic copy-paste versions of my format methods worked pretty well, the version below keeps working and then not working in frustrating ways and need help figuring out what might be causing it.
The editor was originally intended to be a WYSIWYG editor styled via tags for documentation. Qt's confusing use of Html hasn't made that easy.
My basic flow is to extract a copy of the current format, check its current state, invert it, and reapply the format to the position or selection it was extracted from.
# textEdit is a QTextEdit with a loaded document.
# This function is one of several related pairs called by a switchboard.
# It's intent is to invert the italic state of the current position/selection.
def toggle_italic_text(textEdit):
# Get the cursor, and the format's state at its current selection/position.
cursor = textEdit.textCursor()
charFormat = cursor.charFormat()
currentState = charFormat.fontItalic()
# Invert the state within the format.
print(currentState)
charFormat.setFontItalic(not currentState)
print(charFormat.fontItalic())
# Reapply the format to the cursor's current selection/position.
cursor.mergeCharFormat(charFormat)
When I first implemented it, this worked find. Now, it only works on selections, and even then it seems to identify the wrong state depending which direction I make a selection. After experimenting with it, it appears that if I make a selection to the right, it inverts correctly. If I make a selection to the left, it doesn't.
When trying to assign it to a position without a selection, the printed state changes from False to True, which is desired, yet the effect doesn't apply as I type. If I run it repeatedly in place, it continues to change from False to True, meaning the change is being lost.
The function is being called consistently and running through completely. The stored state of the charFormat copy does change.
Why has this pattern stopped working? Am I using charFormats wrong? Why does the direction of selection change the results?
As far as what changed on my end, I had been getting lost in my styling efforts after needing to apply styles through QFonts, QCharFormats, QPalette, and CSS stylesheets (and doc.defaultStylesheet) targeting both widgets and html tags. I desperately wanted my styles to be controlled through one approach, but couldn't figure out the hierarchy or find an approach that applied widely enough. In the end, I stripped out everything except for the stylesheet assigned to the window.
If there's no issue with the code itself, I'm really hoping for hints at what might be disrupting things. It took me awhile to get used to the idea that cursors and formats are copies meant to be changed and reapplied, while the document and its blocks are the real structure.
The important thing that must be considered about QTextCursor.charFormat() is this:
Returns the format of the character immediately before the cursor position().
So, not only this doesn't work very well with selections that include multiple character formats, but you also have to consider the cursor position, which might change in a selection: it could be at the beginning (so it would return the format of the character before the selection), or at the end (returning the format of the last character in the selection).
If you want to invert the state based on the current cursor position (if at the beginning, use the first character, if at the end, use the last), then you can use the following:
def toggle_italic_text(self):
cursor = self.textEdit.textCursor()
if not cursor.hasSelection():
charFormat = cursor.charFormat()
charFormat.setFontItalic(not charFormat.fontItalic())
cursor.setCharFormat(charFormat)
# in this case, the cursor has to be applied to the textEdit to ensure
# that the following typed characters use the new format
self.textEdit.setTextCursor(cursor)
return
start = cursor.selectionStart()
end = cursor.selectionEnd()
newCursor = QtGui.QTextCursor(self.textEdit.document())
newCursor.setPosition(start)
if cursor.position() == start:
cursor.setPosition(start + 1)
charFormat = cursor.charFormat()
charFormat.setFontItalic(not charFormat.fontItalic())
newCursor.setPosition(end, cursor.KeepAnchor)
newCursor.mergeCharFormat(charFormat)
If you want to invert all states in the selection, you need to cycle through all characters.
While you could just change the char format for each character, that wouldn't be a very good thing for very large selections, so the solution is to apply the italic only when the char format actually changes from the previous state, and when at the end of the selection.
def toggle_italic_text(self):
# ...
start = cursor.selectionStart()
end = cursor.selectionEnd()
newCursor = QtGui.QTextCursor(self.textEdit.document())
newCursor.setPosition(start)
cursor.setPosition(start)
prevState = cursor.charFormat().fontItalic()
while cursor.position() < end:
cursor.movePosition(cursor.Right)
charFormat = cursor.charFormat()
if charFormat.fontItalic() != prevState or cursor.position() >= end:
newPos = cursor.position()
if cursor.position() < end:
newPos -= 1
newCursor.setPosition(newPos, cursor.KeepAnchor)
charFormat.setFontItalic(not prevState)
newCursor.mergeCharFormat(charFormat)
prevState = not prevState
newCursor.setPosition(cursor.position() - 1)
The user is prompted with a file dialog and chooses a full path which is then put inside a QTableWidgetItem cell within a parent QTableWidget. Currently, when there is an overflow of text in the item and what it can display, it will show the left portion first.
If the full path is C:\Users\JohnDoe\Example_File1.txt it will show:
C:\Users\JohnDoe\Ex...
I want the user to be able to see the right portion (the file basename) first before the overflow cutoff occurs such that it will read:
...Doe\Example_File1.txt
I tried implement the following code which changed the alignment but did not appear to work as described above:
obj = self.QTable1 #A 10x3 table
for x in range(obj.rowCount()):
item = obj.item(x,2) #Change alignment for 3rd column (Where paths are stored)
item.setTextAlignment( QtCore.Qt.AlignRight)
You must textElideMode to Qt.ElideLeft and disable wordWrap:
self.QTable1.setTextElideMode(QtCore.Qt.ElideLeft)
self.QTable1.setWordWrap(False)
When I create a new document with python-docx and add paragraphs, it starts at the very first line. But if I use an empty document (I need it because of the user defined styles) and add paragraphes the document would always start with an empty line. Is there any workaround?
You can call document._body.clear_content() before adding the first paragraph.
document = Document('my-document.docx')
document._body.clear_content()
# start adding new paragraphs and whatever ...
That will leave the document with no paragraphs, so when you add new ones they start at the beginning.
It does, however, leave the document in a technically invalid state. So if you didn't add any new paragraphs and then tried to open it with Word, you might get a repair error on loading.
But if the next thing you're doing is adding paragraphs of your own, this should work just fine.
Also, note that this is technically an "internal" method and is not part of the documented API. So there's no guarantee this method's name won't change in a future release. But frankly I can't see any reason to change or remove it, so I expect it's safe enough :)
Every time textChanged() is emitted, the text of QTextBrowser is processed and then re-inserted in that QTextBrowser.
That causes trouble with the current Cursor.
How do I do that after typing something at | and re-inserting the text, the cursor is behind the newly inserted character (here: X) ?
Hello| World
Where it should be:
HelloX| World
Where it is:
|HelloX World
I need some help because I don't understand the according part of the QT documentation.
If you're inserting text after the cursor, as yor example suggests, you, you should use the text cursor's insertText method instead of replacing the whole content of the editor - should save you some trouble:
editor.textCursor().insertText('X')
Otherwise you should be able to restore the previous position like this:
old_position = editor.textCursor().position()
# ...
new_cursor = editor.textCursor()
new_cursor.setPosition(old_position)
editor.setTextCursor(cursor)
I have a text widget in my python Tkinter script and i am trying to get the value that the user enter. My intention is to write the data from the text widget together with other values from the script(ie. x,y,z) to the txt file(faultlog.txt) as a single line with semi-column separated. This is what i tried.
...
text=Text(width=30,height=1)
text.place(x=15,y=75)
data=text.get(1.0,END)
lines=[]
lines.append('{};{};{};{} \n'.format(data,x,y,z))
faultlog=open("faultlog","a")
faultlog.writelines(lines)
faultlog.close()
...
Instead of giving me a single line output in the text file, python is writing this to the txt file (assuming the data that user enter is "abcdefgh")
abcdefgh
;x;y;z
just to make things clear, this is what i want
abcdefgh;x;y;z
What did i do wrong? I hope the question is clear enough, i am a beginner so please make the answer simple.
When you get all text of the widget, there is also included a "\n" at the end. You can remove this last character like this:
data=text.get(1.0,END)[:-1]
Note that this always works independently of the length of the text length:
>>> "\n"[:-1]
''
>>> ""[:-1]
''