QLineEdit: show new text before processing textEdited signal - pyqt5

I have a QLineEdit and a slot that processes the textEdited signal.
I don't want to validate the text, just use it to filter a list of names (different widget) with the ones matching the text in the QLineEdit.
I have found that the text shown in the QLineEdit is only updated after the signal is processed, and the question is: can I make the new text show in the QLineEdit first and then process the signal?
Now I have:
1. let's say user presses 'A' key in the QLineEdit
2. textEdited signal is emitted (but QLineEdit is not visually updated yet)
3. signal is processed in my slot (filtering a QListWidget)
4. QLineEdit is updated, showing the effect of pressing the key 'A'
If step 3 takes a long time there is too much delay between the key is pressed and it's shown in the QLineEdit, so I want:
1. let's say user presses 'A' key in the QLineEdit
2. textEdited signal is emitted (but QLineEdit is not updated yet)
3. signal is processed in my slot (filtering a QListWidget)
i) update the QLineEdit object to reflect the pressed key 'A'
ii) filter the QListWidget
How can I do that? I need something like a QLineEdit.refresh() method? As I said I don't need to validate de text, I just want to use it to filter the content of a QListWidget, so I want everything the user edit to be shown as fast as possible.
EDIT: I've found that QCoreApplication.processEvents() does the work, but it affects the process of the signal, and some pressed keys don't trigger the signal, although I don't understand why. It seems that if the user say edits the QLineEdit pressing two keys "too fast" then the call to processEvents() in my slot (while processing the first key) processes the second key, so the second key is not processed by my slot. Does it make sense?

Use a single-shot timer:
self.timer = QtCore.QTimer()
self.timer.setSingleShot(True)
self.timer.setInterval(300)
self.timer.timeout.connect(self.filterList)
self.edit.textChanged.connect(lambda: self.timer.start())
This will keeping re-starting the timer until there's a pause greater than the timer interval, at which point the timeout signal will be sent and the slot connected to it will be called.
You may need to adjust the interval to suit the typing speed.

Related

Apex, Dynamic action, Confirm action, not picking up correct text - what am I missing?

I'm obviously missing something and hoping someone might be able to help.
I've an Interactive Grid, and a button.
When the button is pressed the dynamic action on the button has 2 steps.
Action 1 - Execute Javascript to take a value from one of the IG cells and put it into a page item.
Action 2 - Confirm Action - Are you sure you wish to delete &P10_JOB_ID.
I've made the page item, &P10_JOB_ID, visible and I can see the value has correctly been changed to the value from the IG.
I write P10_JOB_ID into a database table - I get the correct value
But the confirm message isn't picking up the correct value from P10_JOB_ID.
Namely it uses the value in P10_JOB_ID when the page starts, but then as I move around the IG pressing the button and changing the value of P10_JOB_ID, the text in the confirm message never changes.
Can anyone suggest what I might have missed, I'm baffled.
Thanks a lot
Substitutions like &P10_JOB_ID. are made when the page is rendered, not dynamically, so reflect the value at time of page load.
You will need to use Javascript to perform the conform action, something like:
apex.page.confirm ('Are you sure you wish to delete ' + $v('P10_JOB_ID') + '?', 'DELETE');
$v is an APEX Javascript function that returns the current value of a page item.
I used 'DELETE' as an example of a request value; you may want to do something different here.
Ok - having the setting of value and confirm as 2 separate actions is what causes the problem.
As per fac586
That is the expected behaviour. Static text substitutions are performed once during page show processing. They are not evaluated dynamically in the browser at runtime as values change.
Drop the second action and extend the first to display the confirm dialog using the apex.message.confirm JS API method, accessing the item value using the $v shorthand method.

[Vue]Prevent focused input field's data being changed by upcoming new data?

at this moment I have a input field, let say it's being :value bind to a data called apiData,
which will be covered by new data from api call every 10s.
Is there any way to prevent my input field data being changed if the input field is being focused? Cos if i'm typing in the input field while new data returned, what I typed would be gone and covered by the new data.
The input field is
<input
v-on:keyup.enter="$event.target.blur()"
#focus="$event.target.value=''"
#blur="$event.target.value=oddsCell['odds']"
:value="oddsCell['odds']"
/>
You can use the #focus event handlers to set a flag which indicates that the field is being edited right now and prevent the model variable from being overwritten. And the #blur event handler to reset the flag once editing is done.

In Vue.js, how can I get a keypress event to get the latest version of the input?

In the following code:
https://codepen.io/anon/pen/WYJopq
I monitor key presses and try to clone the input into another input as follows:
[![methods: {
clone: function() {
this.mirror = this.original;
}
}]
But the cloned input is always one keystroke behind:
https://i.stack.imgur.com/y2uCA.gif
How do I update my code so that the cloned input exactly matches the original input?
(Note: I know for this simple example, there's an idiomatic Vue.js way to do things, but I'm specifically interested in doing this via keystroke monitoring)
With a keyboard, we have three events fired in the following order:
keydown - fired before character inserted
keypress - fired when a character is getting inserted
keyup - fired when character is already inserted
In this scenario, if you need input with updated characters, you should use keyup event which is after the character is inserted into the input.
Having said this, you should probably use #input event as relying on the keyboard means you are not thinking about other ways via which text can be inserted into the input box. For example, copy-paste or using an on-screen keyboard:
<input type="text" v-model="original" #input="clone()" />

How to respond to focus changes on ComposableModel? (Spec)

I'm trying to create a DateInputFieldModel (subclass of ComposableModel).
It uses a TextInputFieldModel as inputField.
I set inputField autoAccept: true..
I don't want to use return/enter to accept.
While typing, I'm checking with acceptBlock whether the input text is interpretable as a date.
In my case, for instance one digit is already interpretable as a date.
When you type 5, this would mean the 5th of the current month of the current year.
When the input field loses focus (tab or mouse), I'd like to render the final representation of the date into the inputField, and update the date value of my DateInputFieldModel.
Any pointers on how to achieve this?
The underlying Morph gets send #keyboardFocusChange:
You probably need to add #whenFocusChanged: somewhere in the ComposableModel hierarchy and make sure it is called from the correct AbstractMorphicAdapter subclasses
In response to Stephan Eggermont's suggestion I altered
following method
MorphicTextInputFieldAdapter>>adapt: aModel
super adapt: aModel.
aModel
whenBuiltDo: [ :w |
w widget color: Smalltalk ui theme backgroundColor.
w widget widget textMorph
onAnnouncement: MorphGotFocus, MorphLostFocus
send: #announce: to: aModel ]
This works but the drilldown w widget widget textMorph is a bit awkward.
In my DateInputFieldModel I subscribed to the announcements
inputField on: MorphLostFocus send: #lostFocus to: self.

Replay stimulus multiple times in PsychoPy

I'm building an experiment where in each trial, the subjects can replay stimulus as many times as they wish by pressing certain keys.
For example, there're 2 sounds: s1 and s2. s1 is associated with key 'a', and s2 is associated with key 'j'. Whenever the subject presses 'a', s1 will be played. Same for s2. Space bar is used to terminate the present trial and jump to the next trial.
Now I'm able to play stimulus after key press, by having '$event.getKeys('a')' in the condition field in s1 sound component, and '$event.getKeys('j')' in s2 sound component. But this will only play each stimulus once in a trial. The second time the keys are pressed, there are no sounds.
So my question is, what should I do so that in each trial, a stimulus can be played EACH time a designated key is pressed?
The Builder sound component is not ideal for this: as you noticed, if a condition is specified for the onset, it can only trigger the sound once per trial.
An alternative is to create a non-graphical sound object in a code component, and then check for key presses on every frame of each trial, and trigger the sound as required. Insert a Code component. In the "Begin Experiment" tab, put something like this:
j_sound = sound.Sound(u'A', secs=0.5)
a_sound = sound.Sound(u'B', secs=0.5)
Then, in the "Each frame" tab, put something like this:
response = event.getKeys(keyList=['a','j'])
if 'a' in response:
a_sound.play()
elif 'j' in response:
j_sound.play()
This could be improved to handle key presses made while a sound is already playing, but should get you started.