PyQt4 QSpinBox.selectAll() не работает должным образом

Python 2.5.4 PyQt4

Я подклассифицировал QDoubleSpinBox для генерации сигнала о событии focusIn:



#Custom widgets for DPL GUI
from PyQt4.QtCore import * 
from PyQt4.QtGui import * 

class DPLDoubleSpinBox(QDoubleSpinBox):

    __pyqtSignals__ = ("valueChanged(double)", "focusIn()")

    def __init__(self, *args):
        QDoubleSpinBox.__init__(self, *args)

    def event(self, event):
        if(event.type()==QEvent.FocusIn):
            self.emit(SIGNAL("focusIn()"))
            #self.clear() Works as expected
            self.selectAll() #See below                  

        return QDoubleSpinBox.event(self, event)

if __name__ == "__main__":

    import sys

    app = QApplication(sys.argv)
    widget = DPLDoubleSpinBox()
    widget2 = DPLDoubleSpinBox()
    widget.show()
    widget2.show()
    sys.exit(app.exec_())

Если щелкнуть внутри одного поля, а затем убить другое окно, оно работает. Если щелкнуть внутри одного, затем другого, а затем сфокусировать любое другое окно на рабочем столе, оно, похоже, работает.

Я думаю, что это проблема фокуса, но не могу отследить ее. Мне просто нужно, чтобы выбрать все при нажатии. Я пытался сделать это через указатель редактирования строки, но я получаю те же результаты. Попытка заставить фокусироваться на других виджетах, но результат все тот же.

Вы можете подключить пользовательский слот для стрельбы, когда он выдает "focusIn()". Вы можете затем anyQSpinBox.selectAll(), и это работает, но не само по себе.

4 ответа

Я знаю, что этому вопросу уже более двух лет, но, поскольку он является одним из первых результатов поиска в Google "qspinbox select on focus", я бы хотел оставить решение для будущих поколений.

Проблема заключается в поведении QSpinBox.lineEdit(). С focusInEvent, вы можете вызвать selectAll(), но по какой-то причине mousePressEvent из QLineEdit очищает выделение сразу после события фокуса. Смотрите здесь для объяснения.

Решение состоит в том, чтобы установить фильтр событий для виджета QSpinBox.lineEdit () или подкласса QLineEdit и вызвать QSpinBox.setLineEdit(). В любом случае, приведенная выше ссылка покажет вам, как добиться желаемого поведения, сохраняя логический флаг и фильтруя как focusInEvent, так и mousePressEvent.

В соответствии с этим поставить QTimer.singleShot позвонить selectAll внутри переопределения focusInEvent, а затем происходит волшебство.

      class SpinBox(QSpinBox):
    def focusInEvent(self, event: QFocusEvent) -> None:
        QTimer.singleShot(0, self.selectAll)

или вот так (не рекомендуется):

      b = QSpinBox()
b.focusInEvent = lambda _: QTimer.singleShot(0, b.selectAll)

Я изменил событие на QEvent.Enter

Теперь будет self.selectAll()

Я могу обойтись без этого, потому что это приложение для сенсорного экрана, поэтому для пользователя не будет очевидным, что что-то не так. Я все еще хотел бы знать, что мне не хватает, или это просто ошибка.

Продолжение @benjamin-kloster в этой древней теме, поскольку ссылка на форум не работает, но его ответ был очень полезным.

Вы можете просто создать подкласс QDoubleSpinBox и обработать событие FocusIn. Для меня это было наиболее полезно, так как я просто хотел выбрать все при нажатии, чтобы вы могли легко вставлять значения в счетчик.

Я использовал QtDesigner для пользовательского интерфейса, поэтому вам нужно перенести свой виджет в подкласс ниже.

      class Spinny(QDoubleSpinBox):
    def __init__(self, *args):
        QDoubleSpinBox.__init__(self, *args)

    def focusInEvent(self, event) -> None:
        if(event.type()==QEvent.FocusIn):
            QTimer.singleShot(0, self.selectAll)
Другие вопросы по тегам