QTimeEdit has no 'popup' widget and it's overall design makes it "not nice to use".
Therefore I coded two custom QWidget classes:
class Clock_hourWidget(QWidget):
class/object returns/emits first valid hour inputclass Clock_minuteWidget(QWidget):
class/object returns/emit first valid minute input
And i embedded them into a Custom QTimeEdit:
import mathimport sysfrom PyQt5 import QtCore, QtGui, QtWidgetsfrom PyQt5.QtWidgets import QTimeEdit, QApplicationfrom PyQt5.QtCore import QTime, Qt, QTimerfrom PyQt5.QtGui import QIconclass Clock_hourWidget(QtWidgets.QWidget): return_hour = 15 first = True def __init__(self, hours, callback, parent=None): super(Clock_hourWidget, self).__init__(parent) self.setWindowFlags(Qt.Popup) self.callback = callback self.setFixedSize(150,150) self.hours = hours def mousePressEvent(self, event): if self.rect().contains(event.localPos().toPoint()): self.first = False self.return_hour = self.hours self.close() @property def hour(self): if self.first: result = -1 else: result = self.return_hour return result def closeEvent(self, event): self.callback(self.hour) event.accept()class Clock_minuteWidget(QtWidgets.QWidget): return_minutes = 30 def __init__(self, minutes, callback, parent=None): super(Clock_minuteWidget, self).__init__(parent) self.setWindowFlags(Qt.Popup) self.setFixedSize(150,150) self.callback = callback self.minutes = minutes def mousePressEvent(self, event): if self.rect().contains(event.localPos().toPoint()): self.return_minutes = self.minutes self.close() @property def minute(self): return self.return_minutes def closeEvent(self, event): self.callback(self.minute) event.accept()class CustomTimeEdit(QTimeEdit): def __init__(self, parent=None): super(CustomTimeEdit, self).__init__(parent) self.setDisplayFormat("HH:mm") self.setCalendarPopup(False) # calendar_icon = QIcon.fromTheme("calendar") # self.setButtonSymbols(calendar_icon) def mousePressEvent(self, event): if event.button() == Qt.LeftButton: self.open_clock_hourwidget() def return_hour(self, hour): self.clock_hourwidget = None if hour != -1: self.hours = hour self.minutes = self.time().minute() self.setTime(QTime(self.hours, self.minutes)) self.clock_minutewidget = Clock_minuteWidget(self.minutes, self.clock_finalizer) pos = self.mapToGlobal(self.rect().bottomLeft()) pos = self.adjust_Popup_positioning(pos, self.clock_minutewidget) self.clock_minutewidget.move(pos) self.clock_minutewidget.show() def open_clock_hourwidget(self): self.hours = self.time().hour() self.clock_hourwidget = Clock_hourWidget(self.hours, self.return_hour) pos = self.mapToGlobal(self.rect().bottomLeft()) pos = self.adjust_Popup_positioning(pos, self.clock_hourwidget) self.clock_hourwidget.move(pos) self.clock_hourwidget.show() def adjust_Popup_positioning(self, pos, widget): screen = QApplication.desktop().screenNumber(QApplication.desktop().cursor().pos()) screen_geometry = QApplication.desktop().screenGeometry(screen) if pos.y() + widget.height() > screen_geometry.height(): pos = self.mapToGlobal(self.rect().topLeft()) pos.setY(pos.y() - widget.height()) if pos.x() < screen_geometry.left(): pos.setX(screen_geometry.left()) elif pos.x() + widget.width() > screen_geometry.right(): pos.setX(screen_geometry.right() - widget.width()) return pos def clock_finalizer(self, minute): self.clock_minutewidget = None self.setTime(QTime(self.hours, minute))if __name__ == "__main__": app = QtWidgets.QApplication(sys.argv) time_edit = CustomTimeEdit() time_edit.show() sys.exit(app.exec_())
I want the popup to behave like the CalendarPopup of QDateEdit (crossed out functionality already in above code snippet):
The popup should open up under the Custom QTimeEditIf there is not enough space under the Custom QTimeEdit, it should show above the Custom QTimeEditIf there is not enough space to the right, it should move slightly to the left and vice versaMost importantly and seemingly undoable: if the user clicks outside the popup OR if the popup (maybe the whole application) looses focus (by pressing windows key or alt-tab for example): the popup closes.- The button of Custom QTimeEdit should look and behave like the CalendarPopup Button of QDateEdit/QDateTimeEdit (
setCalendarPopup(True)
): Looks should change depending on used style and platform
I can provide full code if needed but for simplicity reasons i tried to cut it down as much as possible.