PDA

View Full Version : Slider keyPressEvent handling



drmacro
26th August 2017, 18:22
I'm using a QSlider and I've sub classed it and implemented the keyPressEvent.

I'm not entirely sure of the sequence of things, but, I can see with print statements that the keyReleaseEvent fire, then keyPressEvent, and subsequently the valueChanged signal gets fired.

In this case, the up/down arrow key is of interest and is handled in the keyPressed event.

Depending on other states in the program I need to decide if, in the valueChanged code, whether to update the associated data and send udp output or just update the data.

Since the value changed code is in the main window and the keyRelease code in in the slider class how do I communicate between them to let the valueChange code make the decisions.

Also, is it good practice to do a lot of work in the keyRelease that calls code in the main window code? For instance calling methods in children of the main window and/or setting values in the mainWindow.

wysota
28th August 2017, 09:22
It's easiest to just emit a signal (if QAbstractSlider::valueChanged() is not enough for you)

drmacro
28th August 2017, 13:45
valueChanged() is fine if all you want to do is know the value is changed.

In this case I need to take different actions depending on whether the user has dragged the slider with the mouse, used the up/down key or has used other widgets that cause the value to change.

I don't know how to tell the difference in valueChanged(), at least I have not found the way to tell.

(There may well be a way, or I need to implement in a different way...I don't claim much experience in Qt. The docs and the examples always leave me wondering: "...ok, so that method does exactly what?, and when did it do it. :p )

wysota
28th August 2017, 14:04
You can emit a custom signal (assuming you can subclass and replace the slider) or install an event filter on the given instance to spy on its events.

drmacro
28th August 2017, 14:14
I already have subclass-ed the slider for other purposes.

I've played with custom signals and event filters. But, I guess I don't grok enough that's it intuitive to me how to make it do what I need. :(

wysota
28th August 2017, 14:45
Show us what you had tried.

drmacro
28th August 2017, 15:19
Leads back to my original question, since I think what I'm doing is not the best...

At the moment I think my implementation is kludgey since I set a flag and check the flag in MySlider.

The following is called after the ui is instantiated:


def addChanStrip(self):
self.max_slider_count = 32
for idx in range(The_Show.mixers.__len__()):
.
.
.
for chn in range(The_Show.mixers[idx].mxrconsole.__len__()):
.
.
.
# Add slider for this channel
sldr = MySlider() # slider with decibel ticks
sldr.setContextMenuPolicy(Qt.CustomContextMenu)
sldr.customContextMenuRequested.connect(self.sldr_ action_click)
sldr.sliderMoved.connect(self.slidermove)
sldr.valueChanged.connect(self.slidervalchanged)
sldr.sliderReleased.connect(self.sldrmovedone)
sldr.sliderPressed.connect(self.slder_pressed)
.
.
.

def slidervalchanged(self, val):
sending_slider = self.sender()
logging.info('In slidervalchanged, sending_slider name: {0}'.format(sending_slider.objectName()))
logging.info('SliderDown is : {}'.format(sending_slider.isSliderDown()))
if sending_slider.isSliderDown() or self.slider_keypress:
self.cuehaschanged = True
CE_msg = osc_message_builder.OscMessageBuilder(address='/cue/editstarted')
CE_msg.add_arg(True)
CE_msg = CE_msg.build()
self.CEResponsethread.queue_msg(CE_msg, self.CueAppDev)
.
.
.
if sending_slider.isSliderDown() or self.slider_keypress:
print('In slidervalchanged, sending_slider name: {0}, updating level state'.format(sending_slider.objectName()))
self.updatecuelevelstate()
if self.slider_keypress: self.slider_keypress = False # todo not sure setting flag in MySlider is good...





class MySlider(QtWidgets.QSlider):
def __init__(self, parent=None):
super(MySlider, self).__init__(parent)
.
.
.
def keyPressEvent(self, k_ev):
print('In keyReleaseEvent for slider {}'.format(self.objectName()))
if k_ev.key() in [Qt.Key_Up, Qt.Key_Down, Qt.Key_PageDown, Qt.Key_PageUp]:
self.window().slider_keypress = True
QtWidgets.QSlider.keyPressEvent(self, k_ev)
.
.
.

wysota
28th August 2017, 15:37
And what is wrong with this implementation?

drmacro
28th August 2017, 15:43
Well, I guess that is really my question.

Is this a bodgy way of doing it, is there a better/preferred way, etc.

wysota
29th August 2017, 06:32
It's quite low-level but it is okay.

drmacro
29th August 2017, 14:24
What would a higher level implementation be?

Can you point me to example/s or docs that detail the approach (i.e. not just "this function does this and has these arguments", but something that educates on the what, how, who calls what when, etc.) (to me the examples in the Qt web pages are always too superficial, but maybe I just don't see how to interpret and extrapolate to more complex situations... :p )
I'm asking because I've found no good sources...

wysota
29th August 2017, 14:35
You would emit custom signals related to the logic of your application and then connect to those signals and put your logic there. It's a minor detail, like I said before.

drmacro
29th August 2017, 14:44
So, emit a signal when?

When there is a up/down arrow pressed? When the slider is moved by the the mouse, when the value is changed for viewing but, not for an actual change is state to the device being controlled?

I guess I need to experiment with emitting a signal and responding to it before I can envision how to use it for my purposes.

wysota
29th August 2017, 15:41
So, emit a signal when?
When some interesting (in terms of your application logic) state is reached or event happens.


When there is a up/down arrow pressed? When the slider is moved by the the mouse, when the value is changed for viewing but, not for an actual change is state to the device being controlled?
I can't answer that question, I don't know what your application aims to do.