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)