Quantcast
Channel: Active questions tagged python - Stack Overflow
Viewing all articles
Browse latest Browse all 14040

Implement Custom QWidgets as Popup for a QTimeEdit

$
0
0

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 input
  • class 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 QTimeEdit
  • If there is not enough space under the Custom QTimeEdit, it should show above the Custom QTimeEdit
  • If there is not enough space to the right, it should move slightly to the left and vice versa
  • Most 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.


Viewing all articles
Browse latest Browse all 14040

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>