mouseMoved to ignore QCursor.setPos()? - qt

I'm calling QCursor.setPos() while the cursor is inside my widget. When I do, mouseMoveEvent is called, when I don't want it to be. In Java/Swing I can move the cursor without sending events. Can I do something similar so calls to QCursor.setPos() so don't send a mouseMoveEvent?

This seems to work for me:
myWidget->clearFocus();
QCursor::setPos(pos);
myWidget->setFocus();

Looks like there is no way to setPos without trigger mouseMoveEvent,
maybe you consider create a :
bool disableMoveProcess;
and make it as a flag for provent your logic running?
I use this method for calling QListWidgetItem::setSelected
without make QListWidget::itemSelectionChanged trigger my code.

I ended up just keeping track of the difference in between mouse movements, so if I get a mouse movement of 5 to the right, for example, I store the five and ignore the next event if it moves me 5 to the left (which means it's probably called by setPos). Not really elegant, but it appears to work reliably.

Related

Qt: change QGraphicsItem receiver during mouse move

I am currently trying to implement a Bezier pen tool. The course of events looks like this:
click on point (QGraphicsItem), start moving while clicked
in QGraphicsScene mouseMoveEvent, prevent moves of point (with a boolean flag) until when distance from point.pos() to event.scenePos() reaches a threshold. When this happens unselect and mouseRelease point, add a node (QGraphicsItem) – select it and give it mousePress state (plus unset the boolean flag)
the user can move node after that, then release mouse.
(The node is a child item of the point.)
I tried to do this inside the scene’s mouseMoveEvent (I have a conditional branch to know when to do this):
point.setSelected(False)
point.ungrabMouse()
node.setPos(event.scenePos()-point.pos()) # positioning relative to point since it’s a childItem()
node.grabMouse()
event.accept()
But after doing this it occured that the node was only getting mouseMoveEvent’s after I release the mouse… (I print them in the console, the node itself did not move.)
So I figured, maybe the scene needs to eat a mouseReleaseEvent before sort of "releasing focus". I found an article that is tangent to the subject here.
So then instead of using ungrabMouse()/grabMouse(), I tried this:
mouseRelease = QEvent(QEvent.MouseButtonRelease)
self.sendEvent(point, mouseRelease)
node.setPos(event.scenePos()-point.pos()) # positioning relative to point since it’s a childItem()
mousePress = QEvent(QEvent.MouseButtonPress)
self.sendEvent(node, mousePress)
Now when I reach the distance threshold, I can see that only point gets selected (good) however as I move further both point and node are selected and moving… I would expect that since I have unselected and released (parent) point, it would not keep moving.
The article I linked to does do something different but it says "It turns out, we have to simulate a mouse release event to clear Qt’s internal state." which might be relevant to the current situation however I do not know what extra steps might need to be taken in order to “clear Qt’s internal state”… so I’m hoping a QGraphics aficionado can weigh in and help me out figuring this.
Thanks for having a look here.
A combination of sending mouse events and grabbing mouse manually works… has to be ungrabbed manually on mouseRelease though.

QDoubleSpinBox: Stop emitting intermediate values

I am subclassing QDoubleSpinBox to add some features (like incrementing the value based on the location of the cursor in the lineedit) and to change some features I find annoying. One of the latter is that intermediate values are emitted: e.g. if you want to enter the value 323 it will emit 3 then 32 then finally 323. I'd like to set it to only emit on entry (i.e. only actually change value on entry).
Anyway, I can't figure out how to capture these intermediate edits. I overrode setValue to see if I could stop it there somehow, but it apparently isn't called (or at least my override isn't). I'm not sure how the value is actually getting set while editing in line edit.
More generally, the logic of this box escapes me. Is there some documentation that explains e.g. "if you type a digit into the lineedit then this series of routines is called... while if you hit the up arrow, this series of routines is called?"
In case it matters, I'm using PyQt5
EDIT: Here is another case in which having access to this is important. Say I want to implement an undo/redo structure for the box. The only way I can think of to get access to the changed values is to connect to the valueChanged signal. But if I'm subclassing the box it seems a little convoluted to listen for a signal rather than just watch the value change 'internally' Or am I missing something here?
You could use the following signal:
void QAbstractSpinBox::editingFinished() [signal]
This signal is emitted editing is finished. This happens when the spinbox loses focus and when enter is pressed.
based on the documentation of QAbstractSpinBox:
http://qt-project.org/doc/qt-5.1/qtwidgets/qabstractspinbox.html#editingFinished
There is nothing that combines the arrow based changes and the editingFinished changes.
My use case was to let the user enter the value without getting the signal on each new digit, while still making ↑, ↓, Page Up, Page Down keys and arrow buttons work as usual, emitting the signal on each activation.
QAbstractSpinBox::editingFinished signal doesn't provide this functionality: it's only ever emitted when focus is lost or Return/Enter is pressed.
What does work exactly as I need is the keyboardTracking property of QAbstractSpinBox. If it's true (the default), the spinbox emits valueChanged on each digit typed. If you set it to false, it behaves exactly as I described in the beginning of this answer.

flex how to refresh already created view

How can I refresh view after a certain event?
I have a view which contains multiple groups. I want to show or hide some groups.
onCreationComplete() or initialize() method works only at the beginning of the view creation.
Try invalidateDisplayList() on the view
Let me know if that doesn't do the trick and we'll try some other tricks.
I personally don't like the answer that says to call invalidateDisplayList (sorry no offense Nate nothing personal). I feel it's too vague and doesn't explain what this does under the hood and furthermore you shouldn't have to call it directly in cases such as the one explained in the OPs question. You can simply create booleans that are bindable for each of the groups you'd like to show/hide then in the event handler set those booleans to the appropriate value and if they are bound to the visible and include in layout properties of the containers those containers will internally call invalidateDisplayList after calling set visible and consequently commitProperties.
This is basically what happens under the hood as I understand it: The way this works is values aren't committed or used to update the display until the next frame this way it doesn't get bogged down doing unnecessary layout calculations. So you update the bindable property which fires an event which triggers a notification in the listener (in this case a function that sets the property on your control), that in turn passes along the value to the control which sets an internal flag to update the property and calls invalidateProperties. When it hits the next frame redraw it sees that the properties flag is dirty (true) and then calls commitProperties, this computes/sets the appropriate values (possibly also invalidating then "fixing" the size using invalidateSize() and measure()) and calls invalidateDisplayList, then during the same frame it sees that the display list flag is dirty so it calls updateDisplayList, here it uses the values of the properties to draw appropriately.
You should also be able to achieve this using states, which add or remove children from the display list based on an array of "actions" for each state.

Implementing Undo/Redo within a TextArea

Im wondering how to implement undo redo functionality with a TextArea. I already have an undoredo framework functionality working, now I have two questions.
When do I start/stop a new undo/redo command, eg when a user hits undo, how far back do I go.
How do I implement this(1.) in a normal TextArea
My thinking:
I thinking that I should create a new undo command, when anything but a alphanumber+space is hit. To do this I would use the keyDown event and test if the key is alpha num if it is not I will reset the command.
Sound good?
Listening for keydown events would miss any text editing that user does with the mouse (cut/copy/paste).
I think a better approach would be to listen for 'change' event on the control (which fires whenever the content changes through user input), and just push the full content of the control (its 'text' or 'htmlText' attribute) with every change event into a undo-buffer (an Array of Strings). I assume that the memory usage is not an issue (it probably isn't, depending on the expected size of the controls content and number of undo levels).
This way, you implement undo/redo just by copying the corresponding control state (moving up and down through array, basically) in the undo buffer back into the control.
The 'proper' approach would be to track the actual edits, and would be condsiderably more complicated.
1.When do I start/stop a new undo/redo command, eg when a user hits undo, how far back do I go.
Do you think your users will need to undo multiple steps? If so, then you may want to have a history (e.g. Paint .NET) and allow infinite undo-s. Otherwise, just remember the most recently performed action.
1.) You should listen for the Event.CHANGE event on the TextField and create a history step each time the event is fired. A history step consists in your case of two values: old and new.
Old is the value of the TextField before change, new is its value after the change.
2.) Your history is a sequence of actions or you can use the Memento Pattern. I think actions are much easier to use. A history action has two methods, undo() and redo(). So in undo() you have to say textField.text = oldContent and in the redo() method you say textField.text = newContent. Your history will also need a pointer to the current action.
3.) To make it a little bit better. You should not listen only for Event.CHANGE but instead listen for the first CHANGE and then the next FOCUS_OUT for that TextField. In that case, a history step is only created once I stop editing the TextField. But it depends on your TextField and how you want to distribute history steps. A multiline TextField should not create a history step only on FOCUS_OUT :)

How to determine last deselected item in a TileList?

My TileList has allowMultipleSelection on. I am using itemClick to call a function. I can use listEvent.currentTarget.selectedItem to determine what object was just clicked on if I am selecting, but when I ctrl + click to deselect an item, it automatically selects something else in the TileList, thus changing the selectedItem. It seems like ctrl + clicking to deselect changes the target before the itemClick function is run. Is there a way to figure out what was just deselected?
I can use selectedItems to get the same end functionality I need. However, I am concerned about performance when the selectedItems collection gets really long. We are using blazeds to send the data back and forth and it would be much faster if we sent the one item that was added/removed then the whole thing each time.
I'm a bit surprised that you seem to be saying that "itemClick" isn't being dispatched in each case. I wonder if you should try listening to the "change" event instead?
What about adding a property called "previouslySelectedItems" and doing a comparison between that and "selectedItems" to figure out what changed? After the comparison is done, set previouslySelectedItems = selectedItems.

Resources