class MyForm(QMainWindow): zoom = 0 pos = None constellation = None step = 0 rotation = False coordChange = False def __init__(self, sky): super().__init__() self.sky = sky self.initUI() def initUI(self): self.setStyleSheet( ''' .QDateTimeEdit, .QLineEdit { background: rgbs(0, 0, 0, 0.5); color: #DDDDDD; border: 1px solid #5A5A5A; border-radius: 5; selection-color: #0a214c; selection-background-color: #C19A6B;} ''') self.initEditors() self.setFocusPolicy(Qt.ClickFocus) self.setGeometry(300, 300, self.sky.width, self.sky.height) self.setWindowTitle('Starry Sky') self.timer = QBasicTimer() self.timer.start(50, self) self.show() def initEditors(self): self.datetime = QDateTimeEdit(self) self.datetime.setFocusPolicy(Qt.ClickFocus) self.datetime.setGeometry(30, 10, 138, 30) self.datetime.setDisplayFormat('dd.MM.yyyy HH:mm') self.datetime.setMaximumDateTime(QDateTime.fromString( '31.12.2099 23:59:59', 'dd.MM.yyyy HH:mm')) self.datetime.setMinimumDateTime(QDateTime.fromString( '01.01.2000 00:00:00', 'dd.MM.yyyy HH:mm')) self.datetime.setDateTime(QDateTime.currentDateTime().toUTC()) self.datetime.dateTimeChanged.connect(self.dateTimeChanged) self.dateTimeChanged(self.datetime.dateTime()) self.coordTheta = QLineEdit(self) self.coordTheta.setFocusPolicy(Qt.ClickFocus) self.coordTheta.setGeometry(10, 50, 85, 30) self.coordTheta.setInputMask('#00°00\'00"') self.coordTheta.setText('+90°00\'00"') self.coordTheta.setValidator(MyValidator(90, -90)) self.coordTheta.textChanged.connect(self.coordChanged) self.coordPhi = QLineEdit(self) self.coordPhi.setFocusPolicy(Qt.ClickFocus) self.coordPhi.setGeometry(100, 50, 85, 30) self.coordPhi.setInputMask('000°00\'00"') self.coordPhi.setText('000°00\'00"') self.coordPhi.setValidator(MyValidator(360)) self.coordPhi.textChanged.connect(self.coordChanged) def coordChanged(self, event): if self.coordChanged: self.coordChanged = False return self.sky.change_direction( str(self.coordTheta.text()), str(self.coordPhi.text())) self.repaint() def dateTimeChanged(self, event): self.sky.set_angle(event.toMSecsSinceEpoch() - MSecsSinceEpoh + event.offsetFromUtc() * 1000) def timerEvent(self, e): self.step += 1 if self.rotation: self.sky.inc_angle() self.datetime.setDateTime(self.datetime.dateTime().addMSecs(45000)) self.repaint() def paintEvent(self, e): qp = MyPainter() qp.begin(self) qp.setBrush(QBrush(Qt.SolidPattern)) qp.drawRect(0, 0, self.size().width(), self.size().height()) self.drawPoints(qp) self.drawLabels(qp) qp.end() def drawPoints(self, qp): for star in self.sky.get_stars(): color = QColor(*colors[star.color]) pos = self.get_gradient_position(star) if star.constellation == self.constellation: qp.drawStar(star.x, star.y, color, star.r + 3, pos) if star.letter: qp.drawLetter(star.x, star.y, color, star.letter) else: qp.drawStar(star.x, star.y, color, star.r, pos) def drawLabels(self, qp): if self.sky.in_pole(): return qp.setPen(QColor(255, 255, 255)) for coord, label in zip(self.sky.get_labels(), labels): qp.drawText(coord.x, coord.y, label) def wheelEvent(self, event): self.zoom += event.angleDelta().y() self.sky.zoom(self.zoom) self.repaint() def refresh_coord(self, theta, phi): self.coordChanged = True self.coordTheta.setText(self.to_text(theta)) self.coordChanged = True self.coordPhi.setText(self.to_text(phi)) def to_text(self, angle): integer = int(angle) angle %= 1 angle *= 60 minute = int(angle) angle %= 1 angle *= 60 secunde = int(angle) return '{0:03d}°{1:02d}\'{2:02d}\'\''.format(integer, minute, secunde) def get_gradient_position(self, star): return positions[int(star.m * 100 + self.step) % len(positions)] def get_delta_in_fract(self, pos): size = self.size() delta = self.pos - pos return delta.x() / size.width(), delta.y() / size.height() def resizeEvent(self, event): self.sky.resize(Point(self.size().width(), self.size().height())) self.repaint() def mousePressEvent(self, event): self.pos = event.pos() def mouseMoveEvent(self, event): if event.buttons() == Qt.RightButton: self.sky.rotate_screen( *map(Point.create_from_QPoint, (event.pos(), self.pos))) elif event.buttons() == Qt.LeftButton: phi, theta = self.sky.rotate_camera( *self.get_delta_in_fract(event.pos())) self.refresh_coord(phi, theta) else: return self.pos = event.pos() self.repaint() def mouseDoubleClickEvent(self, event): if event.buttons() == Qt.LeftButton: star = self.sky.get_nearest_star( Point.create_from_QPoint(event.pos())) if star: self.constellation = star.constellation else: self.constellation = None self.repaint() def keyPressEvent(self, event): if event.key() == Qt.Key_P: self.rotation ^= 1 return if event.key() == Qt.Key_Escape: self.constellation = None return if event.key() == Qt.Key_Left: phi, theta = self.sky.rotate_camera(-0.1, 0) if event.key() == Qt.Key_Right: phi, theta = self.sky.rotate_camera(0.1, 0) if event.key() == Qt.Key_Up: phi, theta = self.sky.rotate_camera(0, -0.1) if event.key() == Qt.Key_Down: phi, theta = self.sky.rotate_camera(0, 0.1) with suppress(UnboundLocalError): self.refresh_coord(phi, theta)