How do you enable auto-scrolling on GtkSourceView2? - python

I am having a problem with GtkSourceView used from Python.
Two major problems:
1) When a user types text into the GtkSourceView, and types past the bottom of the visible text, the GtkSourceView does not autoscroll to the users cursor.
This wouldnt be so bad, except:
2) The arrow keys, page up and page down keys, do not cause the GtkSourceView to scroll either.
The mouse scrollbar does work on the GtkSourceView.
Does anyone have knowledge/experience of this?
My code is here http://launchpad.net/kabikaboo

Ok I just figured this out.
I was adding the GtkSourceView2 into a GtkScrolledWindow.
Only, it was adding a ViewPort first via ScrolledWindow.add_with_viewport().
This disables part of the scrolling behavior via keyboard.
Instead, use ScrolledWindow.add(), and the ViewPort is skipped and the GtkAdjustments take care of the scrolling!

Related

Python Selenium: Show Tooltip on Mouse Pointer (Three.js/React/Canvas)

So this is a bit of a tricky situation. Using Three.js/ReactJS and canvas.
Scenario: When I click and drag a sphere beyond its boundaries a tooltip will show a warning message over the mouse pointer. When I release the mouse the tooltip will disappear. When I click and drag the sphere back to a position inside the boundaries, the tooltip will not be displayed once inside the boundaries.
Bear in mind this is tied into the state of the app handled by react, and in this instance the tooltip is being updated when the conditions are met and updated in the state.
The tooltip element is present however, the attributes and content gets updated on a click and hold when the sphere is out of bounds...
using
ActionChains(page.driver).move_to_element_with_offset(sphere_order_panel, -1047, 398).click_and_hold().move_to_element_with_offset(sphere_order_panel, -1633, 265).click_and_hold().perform()
clicks on the element and drags it to the position outside of its boundaries, but the tooltip is NOT updated... i've put a breakpoint on the page once i manually click into the page, my sphere gets snapped to my mouse location (meaning click_and_hold is indeed working... but i check the html and verify that the tooltip is not updated. however if i manually use my mouse and click on the sphere the tooltip will update! is selenium automation not executing the click_and_hold correctly? I don't think this is the case.
Is there a way to add the mouse pointer to the page using selenium?
Or is there a way to use execute_script() to use javascript on the page to satisfy my conditions to get the tooltip to be updated?
I'm really stuck on this.. and this is a tricky situation (for me at least)
Any help greatly appreciated.
to get around my issue, I had to do this
chain = ActionChains(page.driver).move_to_element_with_offset(sphere_order_panel, -1047, 398).click_and_hold()
chain = chain.move_to_element_with_offset(sphere_order_panel, -1047, 398)
chain.perform()

Alternative to wxStaticText in wxPython?

I have a problem in which I update StaticText fairly often(once every second) and every time it updates, it tears the frame. This is very bothersome on Windows but on Linux it never happened. I tried doing TextCtrl Readonly but I get ugly boxes around text I was wondering if there was a better option for updating text in wxPython frequently that wouldn't tear the screen. Thanks in advance!
I wish I understood better what you meant by "tearing" the frame - I don't seem to have problems with changing StaticText values after a window is created (though sometimes it's necessary to call Layout on a Panel or Dialog).
However, if you're really just looking for read-only TextCtrl's without the "ugly boxes" you should use TextCtrl(style = wx.NO_BORDER | wx.TE_READONLY). The combination will give you what you want - what appears to be a StaticText, but that can't be user-edited and doesn't display a border. You'll also be able to select its value (which may or may not be an advantage).

Scrolling in QScrollArea pyqt

How can I auto scroll for the scroll area? For example, when there is a new update instead of the view of the scroll area staying the same, I want to go down with the new text. Think of it as in a CMD console, when you type a command it autoscroll with the output.
I was just going to respond to the other answer, but I just didn't know the best way to phrase it in the space allotted.
QScrollArea's are very useful widgets to use when designing custom PyQt widgets - I use them often. Things like rollout widgets, card widgets, anything where you could be displaying multiple sub-widgets with the need for scrolling can be a very useful utility. I don't agree with the idea that a QScrollArea isn't much use on its own.
The QTextEdit answer solves the problem the developer was facing - but only because it so happens the question is really about that. If you're trying to scroll a text edit, go with that answer.
However, if you are searching for an answer to the actual question and come across this thread, then the way to scroll down a QScrollArea is by actually modifying the scrollbar's value.
area = QScrollArea(parent)
vbar = area.verticalScrollBar()
vbar.setValue(vbar.maximum())
If you want to scroll to particular areas or anything (like implementing the ensureCursorVisible) then you want to take the location on the area's widget that you want to scroll to, figure out the percentage of the height of it, and apply that value to the vertical scrollbar. (Pseudocode)
Use QTextEdit.moveCursor to set the location you want to scroll to, and then use QTextEdit.ensureCursorVisible to scroll to it:
textedit.moveCursor(QtGui.QTextCursor.End)
textedit.ensureCursorVisible()

Read Only Text widget in python3-tkinter; cross platform

How to suppress end user ability to edit/add/delete text in a Text widget? (Python v3.2.. and tkinter)
The point is to suppress only the ability to change/add/delete text but not to castrate other features. Perhaps a NoEdit Text widged would be a better name.
I've tried .text['state'] = 'disabled' and it works almost OK in Windows (it still allows user to select/copy text highlights the selection, page up/down and up/down buttons work. The only thing broken seems to be the cursor made invisible.)
But on MacIntosh everything is broken. No highlights, no select/copy,... UGH
Since Tkinter has practically no documentation in Python, I've searched and found some TCL advise, to derive a new class and suppress the insert and delete functions.
So, I've tried as so:
class roText(tk.Text):
def insert(self,*args,**kwargs):
print(" Hey - Im inside roText.insert")
pass
def delete(self,*args,**twargs):
pass
def pInsert(self,*args,**twargs):
super().insert(*args,**twargs)
Unfortunately it didn't work right. Apparently tkinter does not use those insert and delete functions when end user enters/deletes code. Perhaps those TCL insert/delete are something else, and I lost something in translation from TCL and Swahili. What functions does tkinter.Text use for end user editing text? Hopefully they are not internal...
So, is there a way to modify the Text widget to suppress only end user editing?
Is there a way to do it without diving inside and overriding internal Tkinter code, so the stuff doesn't get broken by next releases of Tkinter?
Looking at the Idle shell window, I see that they've managed to suppress edits (except for the last line). So there is a way. But what is it and how costly?
Sorry for bumping an old question, but I was searching for an answer to this question also and finally found a solution. The solution I found involves overriding the key bindings when the text widget has focus and is pretty simple. Found here.
To override the bindings of a widget there is a bind function where you pass a string of what is to be overridden and the new function you want it to call.
self.txtBox.bind("<Key>", self.empty)
Somewhere else in the class you'll need to define the function to handle the event.
def empty(self, event):
return "break"
By returning the string "break" the event handler knows to stop after your function, instead of continuing with the default action.
I hope this answers your question. Cheers.
The reason the disabled state doesn't seem to work on the Mac is because it turns off the binding that gives focus to the widget. Without focus, the highlighting on a Mac doesn't show up. If you set the state to disabled but then assign a binding to <ButtonPress-1> to explicitly set focus to the disabled text widget, you can then select and copy text and the highlighting will show.
As for the cursor disappearing... arguably, that's what's supposed to happen. The cursor tells the user "this is where text will get inserted". Since no text will get inserted, having that visual clue would be confusing to the user. What you could do instead, if it was really important, is to insert a small image wherever they click to simulate the cursor.
To answer your question about whether the widget actually uses the insert and delete methods: the methods on the actual underlying widget are what the default bindings use, so overriding them in a subclass has no effect. You would need to redo all the default bindings for that to work. It's doable, but a lot of work.
Unfortunately, this is one area where programming in Tcl really shines, because you can simply disable the insert and delete commands of the widget. Of course, you can do that directly in Tkinter also since ultimately it runs tcl code to do everything, but that would involve writing some tcl code which is not a very good solution from the perspective of a Python coder.
I think the best solution is to use the disabled state, then add in just enough bindings to do what you want.
Here's a simple example that works by explicitly setting focus on a mouse button click. With this code I'm able to click and swipe to select a region, or double- or triple-click to select words and lines:
import Tkinter as tk
class SampleApp(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
self.text = tk.Text(width=40, height=20)
self.text.bind("<1>", self.set_focus)
self.text.insert("end", "\n".join(dir(tk.Tk)))
self.text.configure(state="disabled")
self.text.pack(fill="both", expand=True)
def set_focus(self, event):
'''Explicitly set focus, so user can select and copy text'''
self.text.focus_set()
if __name__ == "__main__":
app = SampleApp()
app.mainloop()
#BryanOakley It took me a while to test your suggestion since I have no Mac.
Unfortunately Mac implementation of Python is buggy.
I've added focus, ie my disable function which I call after creating a window and inserting text, now calls first:
self.txt['state'] = 'disabled'
and then
self.txt.focus_set()
Which is what I think you've suggested.
It "kind of" worked. Ie: when selecting text (click and drag or double-click) highlighting works most of the time. Python must have some bad memory references or such bugs: Sometimes highlighting doesn't work at first, then it starts working (in the same window) after more clicking. Sometimes when program is invoked it works right of the bat. Sometimes selecting with Shift-rightArrow key will work but selecting with the mouse will not. Then starts working again. Or it will work fine in one window but not in another one (both of the same class), then starts working in all windows...etc...
The good thing is that adding focus did not affect badly Windows (ie all works fine as without focus.
I guess at this point I will just hope that future/next release of Python for Mac will fix those bugs..
BTW, it seems that Mac is a bit of an orphan for Python. Implementation is much uglier then for Windows. I mean the fonts look worse, the buttons, etc.. Or it could be due to different screen resolutions and Python ports that poorly account for those. Not sure
Anyway. Thank you for your help and suggestion to use focus for Mac.

How do I scroll a wxPython wx.html.HtmlWindow back down to where it was when the user clicked a link?

I am using a wxPython wx.html.HtmlWindow to display part of my interface. The user can scroll down a list of links in a window smaller than the list. When they click on a link, I need to repaint the web page, but I want to return the page position back to where they clicked it.
I've tried MouseEvent.GetLogicalPosition() on the event, but it wants a DC and the best I've been able to do is get the same information as GetPosition(), so I must not be feeding it the right one.
I also tried HtmlWindow.CalcScrolledPosition(), but apparently that isn't available in HtmlWindow because I get a NotImplementedError...
What I would like is a scroll position that can be derived from the MouseEvent, or the OnLinkClicked information.
I know about HtmlWindow.ScrollToAnchor(), but it's flaky and unaesthetic -- I would prefer to bypass it if possible so that I can scroll back exactly to where the user clicked.
Thanks!
how about having a look at the source of wxHtmlWindow for inspiration? for example at wxHtmlWindow::LoadPage(): it
// store[s the current] scroll position into history item:
int x, y;
GetViewStart(&x, &y);
(*m_History)[m_HistoryPos].SetPos(y);
this saved scroll position is used in wxHtmlWindow::HistoryBack():
Scroll(0, (*m_History)[m_HistoryPos].GetPos());
Refresh();
to go back to the saved position.
i would assume that this built-in "go-to-the-last-position-in-window" handling isn't the most "flaky and unaesthetic". could something similar work for you, too?
Maybe a bit late, but with some tips from ax, and some hints from here, I think that calling:
scrollpos = wx.html.HtmlWindow.GetViewStart()[1]
and storing that, and then later doing a call to:
wx.html.HtmlWindow.Scroll(0, scrollpos)
works for me. Of course, you do need to change wx.html.HtmlWindow to an actual reference to an instance.
Here is what I am doing to scroll page to previous position.
I do this to avoid blinking.
pos = self.GetViewStart()[1]
self.Freeze()
self.SetPage(src)
if save_scroll_pos:
self.Scroll(0, pos)
self.Thaw()
Usually, click events are trigged by MouseUp events. If you track the mouse position by capturing any MouseDown events, you will know where the last click (MouseUp) happened, and that should allow you to reconstruct things.
For this particular problem, you might have to do a bit more work in MouseDown like checking if they are within the wxHtmlWindow control and if so, then saving something like a line number.

Categories