For a Python3/PyQt4 project, I'm looking for the fastest way to change the text appearance of several words in a QTextEdit object. The text is not written in HTML (it's a pure text string), is read-only and is made of several words. Each word has a special 'attribute' defined in my code, defining its appearance when this word is hovered over.
The appearance of all words sharing the same attribute must change when one of these words is hovered over.
I need speed since :
I did more or less the same program but the the words' appearance changed when the user clicked on them and I guess my code is too slow to be used with hover events. (see details below)
It's a Python project based on PyQt4, not a C++ one based on Qt.
Any help would be appreciated !
MORE DETAILS :
I can see two ways to achieve my goal :
(1) Write my text in the editor, detect which word the mouse "flies over", get the other words to be highlighted and painfully select them, one by one, inserting some HTML code to modify their appearance. It's the painfully part that I find too complex and too slow : is there a fastest way to do this ?
(2) Writing my text as an HTML one and work with the CSS since a QTextEditor can use them. Alas, the easy way can't work. But perhaps is it possible to "re-load" the CSS of the text and use a more clever trick ?
I'm wondering is it even possible to get the word under mouse cursor from the QTextEdit.
You said the text cannot be edited, so I maybe the QTextEdit is not the best possible widget for this job. Create your own widget and draw the text by yourself. Then you know the word positions so finding the word under the mouse is easy. And when some attribute is activated or deactivated, you can redraw only the affected words.
Related
I recently made a simple notepad-like text editor but now I want to implement things like syntax highlighting certain words and automatic indentation as you type. How could I do this dynamically as the user types. So far everything I've done is event-based so I'm guessing I need to have some sort of loop that constantly checks the contents of the textbox as the user is typing? Is tkinter not suited for this? Appreciate it if you steer me in the right direction as to how I can implement this.
Tkinter is quite well suited to this sort of thing. It's possible to make a very smart text editor if you're willing to put in some effort.
This answer shows how to get the text widget to fire an event whenever something in the text widget changes. It's a little complicated, but fairly foolproof.
If you want something simpler, you can simply bind on <Any-KeyRelease> which will fire an event whenever the user releases a key. You can then use the information in the event object to decide what to do. It won't handle the case where you cut and paste with the mouse, for example, and your binding will fire for arrow keys and other non-inserting keys, which is why I recommend the more complicated solution.
This answer shows an example of using a binding on <space> to do do a simple spellcheck, and also shows a fairly simplistic implementation of a toolbar with a "bold" button.
I am still working on my text editor, and now I want to make it run faster. So I thought I may somehow get currently visible text, and parse it as I want. So is there a way to get currently visible lines?
P.S. Or maybe there is another way to increase StyledTextCtrl's performance? Thanks.
Use GetFirstVisibleLine() to determine the first visible line. Lines are numbered starting at zero.
Use LinesOnScreen() to determine how many lines are visible on the screen.
You can use GetLine(line) to get a string of an individual line.
Right now, I am writing a python program using ObjectListView package. When the list is empty, the back ground will show words "This list is empty". But I want to change it into an animation. How to realize it?
Do I have to change the ObjectListView library to realize it?
"This list is empty" is shown in a StaticText control (named stEmptyListMsg). You can change the message and the font by calling SetEmptyListMsg and SetEmptyListMsgFont respectively.
If you want to replace the StaticText with an animation, then, I think, you should write your own custom ListCtrl based on ObjectListView or ListCtrl.
This link can help you to create an animation: http://www.daniweb.com/software-development/python/code/216673/wxpython-animated-gif#
I am looking for help - I am updating my Tkinter wiki (http://sourceforge.net/projects/infolder/) trying to add to it some folding/outline capabilities.
For it to work I need to place in the text widget (the main window where all the action happens) some un-deletable symbol indicating folding (e.g. a small triangle image indicating hidden text lines).
Unfortunately I noticed from these Q&A's that undeletable stuff is not easy to create in Tkinter:
How can you mark a portion of a text widget as readonly?
unremovable text in tkinter
As a 2nd option, I could try to show folding levels by a forced indent, so that e.g. if I'm at a one-level deep, the start-of-line is not at column 1 but at column 5...
This is it possible in Tkinter, without too much work?
thanks for any help...
Your question says that undeleteable regions are "not easy", but you also show they are possible by linking to an answer that shows how. So, what question are you asking?
As for "forced indent", look at the lmargin1 and lmargin2 tag attributes.
So I currently have a ScrolledPanel that contains a number of TextCtrls that are placed in a vertical BoxSizer programmatically. The reason I'm doing this instead of just appending lines to one big scrolled TextCtrl is so that I can also add other controls in between the TextCtrl, such as images or stylized expand/contract folding stuff.
However, this particular implementation is causing a problem - namely that it is impossible for the user to select text across multiple TextCtrls. Is there a way to do this that will be fast, clean, idiomatic, and not especially kludgy? Is my best bet to write a pointer-location text selection algorithm that essentially reinvents the wheel for the text selection stuff of the underlying native libraries, or is there an easier way to embed other controls inside a multiline scrollable TextCtrl, or even select text across multiple TextCtrls natively?
I would stay away from trying to reimplement text selection controls if at all possible, since that is bound to turn very messy very fast. Another way you could tackle this issue would be to use a single multi-line textctrl widget with the other widgets tacked on over it. This is also messy, but less so.
You can place the other widgets over the textctrl simply by placing them directly over the same position as the textctrl, so long as the other widgets have the same parent as the textctrl. This should work, so long as you don't overlap with the vscrollbar (or, better yet, remove it entirely with style=wx.TE_NO_VSCROLLBAR).
The next thing you'll need to do is pre-fill and space your textctrl so that the user has control of text only right after the position of each widget. You should have each line of text with a different spacing setting, set with the spacing options of wx.TextAttr (the more generic versions of double-spacing, etc), which you calculate based on the particular widget spacing you've given your app. This is necessary to force the user to type only exactly where you want them to.
Next, you'll need to set up a binding to the textctrl newline character that recalculates the spacing needed for each line. Once you've figured out how to handle spacing, this shouldn't be too difficult.
Finally, after you select the text, just reset everything to the same spacing, or whatever else suits your fancy, so that you don't get awkward linebreaks when you paste it back in elsewhere.
I know this is a complicated answer, but it's a complicated issue you raised. This is, I believe, the most efficient way to solve it, and avoids all the bugs that would arise from completely overhauling the textctrl, but it does involve messing around with auto-correcting linebreaks and spacings, which can be a little tricky at first.