Change the events for different parts of the same widget - python

I have created a margin in a gtk.TextView widget. Now I want to make sure that the default event handler for mouse click, which is moving the text cursor to the clicked position, works only when clicked to the right of the margin.
Is this possible?

Try connecting to the button-press-event but doing it before the widget's own connection. If you connect after the view does it, this will be the default (GObject signal handlers are handled in reverse order of connection by default). Then determine if the event should be let through or not, by returning TRUE (to stop the event) or FALSE as required.

Related

Hook Mouse clicks and intercept them

I am currently trying to stop mouse clicks while my Script is running and still work with them.
If you are confused about the use case I will elaborate at the end of the question.
Currently I can get clicks like this:
import mouse
import time
def mouseHook(event):
if type(event) == mouse.ButtonEvent:
print(event)
mouse.hook(mouseHook)
while 1:
time.sleep(0.25)
But this still lets the clicks go through, how would I intercept them?
use case: simulate a monitor and while mouse is on that monitor send all movements, clicks and keypresses to MacBook (similar to Synergy, Mouse without Borders or Share Mouse)
The hook used by the application only 'hooks' into the process, which means it gets information from it, but can't insert or modify it's code.
For reference on windows that would use (https://learn.microsoft.com/en-us/previous-versions/windows/desktop/legacy/ms644988(v=vs.85))
The easiest way would be to have your application ignore the mouseclicks.

How do I paint over an QAbstractSlider?

I've got this cool widget I'm working on and I simply want to paint this central straight line, over the slider widget that I've created.
Since the PaintEvent activates at initialization, anything called in the main class is displayed above the painted lines. With this in mind, can I call a paintevent function to initialize after my slider widgets have already been called/initialized?
Moreover, would it be smart to use threading.event() to stall the paint event function until after these sliders have been called, when I set the event?
Any advice would be great
*** UPDATE ***
event.is_set() blocking doesn't have an effect and the painter still paints below the QAbstractSlider

Tkinter bind copy event needs to work in background as well

I have a simple copy paste event, which should trigger a function while my program runs:
root = tkinter.Tk()
root.bind('<Control-c>', parse_item)
root.mainloop()
parse_item grabs the contents of the clipboard and makes some calculations.
The problem I have is:
It only works if my program is in focus. I need to be with the mouse in the program, then the bind event will trigger.
What I need:
The bind event should also trigger if the program is not in focus (for example the program is minimized). It should always trigger while the program runs.
It only works if my program is in focus. I need to be with the mouse in the program, then the bind event will trigger.
You cannot do that with tkinter. It can only operate on events in widgets that it controls, and only when it has focus. You would have to use a platform-specific tool to intercept events from other programs.

GTK focus-out-event

I am showing a user a popup menu when they right click.
According to the popup behaviour, I want to destroy the popup when it looses focus(when user clicks outside the popup window). For that I tried to connect the popup window to "focus-out-event", using Glade. But for some reason, that event is not getting fired. I tried to print something on the terminal when the event is fired, but nothing gets printed.
I am new to Python and GTK, and now I have no clue how to proceed further.
#handler to catch the focus out event
def on_popup_menu_add_attachment_focus_out_event(self, *args):
print("Destroying the popup.....")
focus-out-signal and its handler
I just changed the Type as Top Level and it worked!

wx's idle and UI update events in PyQt

wx (and wxPython) has two events I miss in PyQt:
EVT_IDLE that's being sent to a frame. It can be used to update the various widgets according to the application's state
EVT_UPDATE_UI that's being sent to a widget when it has to be repainted and updated, so I can compute its state in the handler
Now, PyQt doesn't seem to have these, and the PyQt book suggests writing an updateUi method and calling it manually. I even ended up calling it from a timer once per 0.1 seconds, in order to avoid many manual calls from methods that may update the GUI. Am I missing something? Is there a better way to achieve this?
An example: I have a simple app with a Start button that initiates some processing. The start button should be enabled only when a file has been opened using the menu. In addition, there's a permanent widget on the status bar that displays information.
My application has states:
Before the file is opened (in this state the status bar show something special and the start button is disabled)
File was opened and processing wasn't started: the start button is enabled, status bar shows something else
The processing is running: the start button now says "Stop", and the status bar reports progress
In Wx, I'd have the update UI event of the button handle its state: the text on it, and whether it's enabled, depending on the application state. The same for the status bar (or I'd use EVT_IDLE for that).
In Qt, I have to update the button in several methods that may affect the state, or just create a update_ui method and call it periodically in a timer. What is the more "QT"-ish way?
The use of EVT_UPDATE_UI in wxWidgets seems to highlight one of the fundamental differences in the way wxWidgets and Qt expect developers to handle events in their code.
With Qt, you connect signals and slots between widgets in the user interface, either handling "business logic" in each slot or delegating it to a dedicated method. You typically don't worry about making separate changes to each widget in your GUI because any repaint requests will be placed in the event queue and delivered when control returns to the event loop. Some paint events may even be merged together for the sake of efficiency.
So, in a normal Qt application where signals and slots are used to handle state changes, there's basically no need to have an idle mechanism that monitors the state of the application and update widgets because those updates should occur automatically.
You would have to say a bit more about what you are doing to explain why you need an equivalent to this event in Qt.
I would send Qt signals to indicate state changes (e.g. fileOpened, processingStarted, processingDone). Slots in objects managing the start button and status bar widget (or subclasses) can be connected to those signals, rather than "polling" for current state in an idle event.
If you want the signal to be deferred later on in the event loop rather than immediately (e.g. because it's going to take a bit of time to do something), you can use a "queued" signal-slot connection rather than the normal kind.
http://doc.trolltech.com/4.5/signalsandslots.html#signals
The connection type is an optional parameter to the connect() function:
http://doc.trolltech.com/4.5/qobject.html#connect , http://doc.trolltech.com/4.5/qt.html#ConnectionType-enum
As far as I understand EVT_IDLE is sent when application message queue is empty. There is no such event in Qt, but if you need to execute something in Qt when there are no pending events, you should use QTimer with 0 timeout.
In general, the more Qt-ish way is to update the button/toolbar as necessary in whatever functions require the update, or to consolidate some of the functionality and directly call that function when the program needs it (such as an updateUi function).
You should be aware that in Qt, changing an attribute of a Ui element doesn't cause an immediate redraw, but queues a redraw in the event system, and multiple redraw calls are compressed into one where possible.
As for the multiple changes relating to state, have a look at this blog post about a hopefully-upcoming addition to Qt to more easily handle states. It looks like this would take care of a lot of your complaints, because in your multiple functions, you could just transition the state variable, and the other parts of the UI should update to match. It's not positive this will make it into the next Qt release (although I would bet on it, or something similar), and I have no idea how closely PyQt tracks the Qt releases. Or alternately, you could use the concept and create your own class to track the state as needed.

Categories