Disabled QGraphicsItem prevents scrolling of QGraphicsView - python

I have multiple QGraphicsItems with the ItemIsSelectable, ItemIsMovable and ItemSendsGeometryChanges flags.
Sometimes I want to disable selection and movement of those items, and I'm currently doing this by calling QGraphicsItem.setEnabled(False). However, when the cursor is on top of a disabled QGraphicsItem, the scroll wheel doesn't scroll the view anymore. I have tried to find a solution through Google, but I haven't found any working solutions.
So, my question is: Is there an easy way to *not* make disabled items prevent scrolling if the cursor is hovering over them?
If not, I can just write an own function that disables the mentioned flags instead of calling setEnabled() on the QGraphicsItem, but I'm still wondering why scrolling doesn't work, and if I really can't let disabled items ignore the scrolling event.
One thing I've tried already, is disabling Qt.MiddleButton with a setAcceptedMouseButtons() call, but that didn't seem to change anything.
My setup: Windows 7, Python 2.7.3 and PyQt4

void QGraphicsItem::setEnabled(bool enabled)
Disabled items are visible, but they do not receive any events
Mouse events are discarded
That is the explanation why your mouse events - scroll wheel - are not working.
And why trying to change designation of mouse buttons doesn't make a difference - the item simply doesn't care :-)
If you want to disable movement and selection of a QGraphicsItem, the best way is to unset their QGraphicsItem::ItemIsSelectable and QGraphicsItem::ItemIsMovable flags.
This really seems simpler... As you probably already noticed.
The alternative - as the linked answer shows - is to install a scene event filter, have other items filter the disabled items events. The following question has good info:
Event filter on QGraphicsItem

Related

How to add a "remove button" at the right side of the hovering (or each) item of a wx.ComboBox popup

What I want is a mean to remove an item from the combobox without having to add a separate remove button somewhere else. So I want a remove button to appear at the right side on a combobox dropdown item when I hover over my mouse pointer on it. And, it is also OK if all the items have remove button at the right side and do not need hovering.
The images bellow will illustrate what I am saying [...please ignore my mspaint skils]
[combobox with remove button for hovering item]
https://i.imgur.com/kIMtF3G.jpg
[combobox with remove button for each item]
https://i.imgur.com/iyG23vG.jpg
[NOTE: Sorry, I cannot post images directly because it needs at least 10 reputation to post images.]
[I am new to python and wxpython. So please ignore my ignorance if any. And for the same reason any simple code sample will be greatly helpful.]
Regards.
The wx.ComboBox does not have this feature. The wxPython GUI toolkit uses the target platform's native widgets. If those widgets don't support doing it, then neither does wxPython.
However, wxPython does have custom widgets or you could create your own widget to do this sort of thing.
I also think you could use a context-menu for this task. You would need to right-click to make it work. Another method would be to bind to a mouse event and try to figure out where in the widget you are, but I think that method would be error prone.

wxpython treectrl show bitmap picture on hover

So i'm programming python program that uses wxPython for UI, with wx.TreeCtrl widget for selecting pictures(.png) on selected directory. I would like to add hover on treectrl item that works like tooltip, but instead of text it shows bitmap picture.
Is there something that already allows this, or would i have to create something with wxWidgets?
I am not too familiar with wxWidgets, so if i have to create something like that how hard would it be, lot of code is already using the treectrl, so it needs to be able to work same way.
So how would i have to go about doing this? And if there might be something i might be missing id be happy to know.
Take a look at the wx.lib.agw.supertooltip module. It should help you to create a tooltip-like window that displays custom rich content.
As for triggering the display of the tooltip, you can catch mouse events for the tree widget (be sure to call Skip so the tree widget can see the events too) and reset a timer each time the mouse moves. If the timer expires because the mouse hasn't been moved in that long then you can use tree.HitTest to find the item that the cursor is on and then show the appropriate image for that item.

wx.lib.EVT_COLOURSELECT interfering with wx.lib.FloatCanvas.EVT_MOUSEWHEEL

The Problem:
It seems like one event is disabling another event. Before calling event B, event A works just fine. After event B fires, event A no longer works. Both events are custom ones that people made for their wxPython libraries (FloatCanvas and ColourSelect). I'd like to trace the generated events to make sure that, after event B, event A is still being fired (but perhaps not triggering the handler code?)
The Details:
I have a wxPython app where I create a wx.Panel object with two child items - a plot and a legend. This top level panel handles the majority of the events.
The plot is a wx.Panel object with a single wx.lib.FloatCanvas.FloatCanvas canvas in it.
The legend is a wx.Panel with multiple wx.StaticText and wx.lib.colourselect.ColourSelect objects in it (I'm plotting discrete data points).
On the plot, I bind FloatCanvas.EVT_MOUSEWHEEL to my zoom in/out function. On the legend, I bind the wx.lib.colourselect.EVT_COLOURSELECT event to my update_colors function which then sends the event to the parent panel via wx.PostEvent(event).
The parent panel then receives EVT_COLOURSELECT from the child and executes code that changes the colors of my plots.
Source Code:
I haven't had time to write a small sample that demo's the problem, but you can see the problem by running the source code:
https://github.com/dougthor42/wafer_map
Run the wm_app.py file and then go through the following test steps.
Testing Steps:
Scroll/zoom in and out - works just fine
Change a plot color (fires EVT_COLOURSELECT). If you're testing with the source code you do this by clicking on a legend color box and choosing a new color.
Attempt to zoom in and out again. Doesn't work!
Verify that all other events (key down, click-and-drag, mouse move) all work.
Things I've Tried:
Obviously these didn't work or else I wouldn't be here :-P
Unbinding the mousewheel event and rebinding it when the top level panel receives the event from the child.
Completely disabling the handlers for EVT_COLOURSELECT in both the parent panel and the legend.
I thought that perhaps there was something going on in my handlers. Turns out, just
triggering EVT_COLOURSELECT causes the EVT_MOUSEWHEEL to stop working.
Changing FloatCanvas.EVT_MOUSEWHEEL to some other event, for example FloatCanvas.EVT_RIGHT_DOWN
This does actually work! I loose the 'speed' info from the mouse wheel, but right-clicking
before and after step 2 both work.
Seems to indicate that it's an issue with the mouse scroll event specifically.
Has anyone had a problem where events interfere with each other?
It turns out that there wasn't any interference with events - at least not the events that I mentioned.
After a ton of fiddling and attempts at making a bare-bones version that still demonstrated the problem (which I was unsuccessful at doing), I figured out the root cause. Sadly, I did not figure out a workaround.
The Problem:
My plot wx.Panel was binding wx.MOUSE_LEFT_DOWN. It seems that this was preventing the parent wx.Frame window from giving focus to the Panel that held the plot and the legend.
The Solution:
I removed the bind to wx.EVT_LEFT_DOWN and that seems to fix the underlying issue. However, this is still not the ideal case because it causes two other problems:
I can no longer use my left mouse button on the plot. Not a big deal, I guess, because I can always bind right-mouse.
A user must first left-click on the plot area to give it focus before the mouse scroll or any keyboard shortcuts will work. This doesn't necessarily stem from not binding wx.EVT_LEFT_DOWN, but rather (I believe), from something that Windows does. See Focus-follows-mouse in wxPython? for a bit more info.
Failed Workaround:
I tried a workaround: adding code that sends the wx.EVT_LEFT_DOWN event to the parent but either that still didn't work or I was doing it wrong. Here's the left-click event handler that I tried:
def left_click(self, event):
print("left click!")
parent = wx.GetTopLevelParent()
wx.PostEvent(self.parent, event)
So anyway, this question is kinda solved. Hopefully what I've got here helps someone else out.

PySide Button Auto Repeat doesn't start until mouse is moved

I have a PySide application with a single button that implements auto-repeat. But the auto-repeat functionality doesn't seem to be working correctly.
If I simply click and hold the button, its function is only called once no matter how long I wait or what the auto-repeat settings are. But as soon as I move the mouse, the button's functionality is called repeatedly, just as it should be.
This is with Python 2.6, PySide 1.1.2, running on Windows 7 64 bit.
self.btn.setAutoRepeat(True)
self.btn.setAutoRepeatDelay(200)
self.btn.setAutoRepeatInterval(100)
I was having a similar problem using normal QT4.x on linux. The issue was that something was connected to the clicked signal. I think it was stealing/changing the focus of the mouse. I just changed that item to connect to the the released signal. That doesn't mean you can't connect to clicked, but just be sure that there are no focus stealing side-effects.

Customize PyQt multi-touch pan gestures on QListWidget

I'm having a problem with a simple Notepad application I'm writing to teach myself basic Python/PyQt.
Specifically, I want to know how to change the multi-touch pan gesture sensitivity on a QListWidget.
As it is now, when I drag up and down with 2 fingers, it seems like the list is moving up/down one step for each pixel I move with my fingers. This is nothing I've implemented myself, it seems to work out of the box for list widgets
I want the movement to mimic the speed of my fingers i.e one move up/down of the widget items for every x*height_of_item_in_pixels. Is this doable without major hacking into the gesture system?
How would I go about this?
I'm using PyQt 4.8.3 with Python 2.6
Quite a bit late, but maybe I can help others who stumble upon this question:
The solution is to set the scroll mode for the QListWidget to ScrollPerPixel (instead of the default ScrollPerItem):
list_widget.setVerticalScrollMode(list_widget.ScrollPerPixel)
A minimal example:
import sys
from PyQt5 import QtWidgets
# create app
app = QtWidgets.QApplication(sys.argv)
# create list widget
list_widget = QtWidgets.QListWidget()
# populate list widget with dummy items
for index in range(100):
list_widget.addItem(QtWidgets.QListWidgetItem('item {}'.format(index)))
# THIS IS THE IMPORTANT PART: set the scroll mode
list_widget.setVerticalScrollMode(list_widget.ScrollPerPixel)
# OPTIONAL: enable pan by mouse (and one-finger pan)
QtWidgets.QScroller.grabGesture(list_widget.viewport(),
QtWidgets.QScroller.LeftMouseButtonGesture)
# show the list widget
list_widget.show()
# run the event loop
app.exec_()
Note: This example also shows how to implement panning using the mouse, which is useful for testing on devices without touch-screen. Moreover, the mouse pan setting also enables one-finger pan, in addition to the default two-finger pan gesture (at least on Windows, tested on Surface Pro tablet).
More than likely this functionality exists because the multitouch event is being interpreted by your operating system as a scroll of some type and QT is recieving the scroll action, rather than the multitouch action directly.

Categories

Resources