class CalendarDialog(QDialog): def __init__(self, xlim): super(CalendarDialog, self).__init__() self.initUI(xlim) def initUI(self, xlim): Vl = QVBoxLayout() Grid = QGridLayout() ## number of Headerlines Grid.addWidget(QLabel('Select start time'), 0, 0) Grid.addWidget(QLabel('Select end time'), 0, 1) xs = num2date(xlim[0]) xt = num2date(xlim[1]) xmin = QDate(xs.year, xs.month, xs.day) xmax = QDate(xt.year, xt.month, xt.day) self.tstart = QCalendarWidget() self.tstart.setDateRange(xmin, xmax) self.tstart.setSelectedDate(xmin) self.tend = QCalendarWidget() self.tend.setDateRange(xmin, xmax) self.tend.setSelectedDate(xmax) Grid.addWidget(self.tstart, 1, 0) Grid.addWidget(self.tend, 1, 1) Vl.addLayout(Grid) self.buttons = QDialogButtonBox() self.ok_button = self.buttons.addButton(self.buttons.Ok) self.buttons.addButton(self.buttons.Cancel) self.buttons.accepted.connect(self.accept) self.buttons.rejected.connect(self.closeWindow) Vl.addWidget(self.buttons) self.setLayout(Vl) self.setWindowTitle('Select time') self.setGeometry(300, 300, 250, 150) self.show() def getResults(self): if self.exec_() == QDialog.Accepted: # get all values tstart = self.tstart.selectedDate().getDate() tend = self.tend.selectedDate().getDate() return tstart, tend else: return None def closeWindow(self): self.close() return None
class 시간날짜편집기(QWidget): def __init__(self): super().__init__() self.initUI() def initUI(self): self.cal = QCalendarWidget() self.cal.setGridVisible(True) # 격자표시 설정 self.cal.setDateRange(QDate(2020, 1, 1), QDate.currentDate()) self.cal.clicked[QDate].connect(self.PastDate) self.label1 = QLabel(self) self.date = self.cal.selectedDate() self.label1.setText(self.date.toString()) self.label2 = QLabel(self) previousBtn = QPushButton('이전 달') previousBtn.clicked.connect(self.preMonth) nextBtn = QPushButton('다음 달') nextBtn.clicked.connect(self.nextMonth) vbox = QVBoxLayout() vbox.addWidget(self.cal) vbox.addWidget(self.label1) vbox.addWidget(self.label2) vbox.addWidget(previousBtn) vbox.addWidget(nextBtn) self.setLayout(vbox) self.setWindowTitle('QCalendarWidget') self.setGeometry(300, 300, 500, 400) self.show() def PastDate(self, date): self.label1.setText(date.toString()) self.label2.setText( f'2020년 1월 1일부터 {QDate(2020,1,1).daysTo(date)}일이 지났습니다.') def preMonth(self): self.cal.showPreviousMonth() def nextMonth(self): self.cal.showNextMonth()
def initUI(self): # Window size + Title self.setGeometry(self.left, self.top, self.width, self.height) self.setWindowTitle(self.title) # Grid Layout grid = QGridLayout() self.setLayout(grid) # Plot Canvas m = PlotCanvas(self) self.m = m # Load solar system print("PLOTTING ORBITS") self.sol = SolSystem() m.planetOrbit(self.sol) # Calendar selection cal = QCalendarWidget(self) cal.setGridVisible(True) cal.setDateRange(QtCore.QDate(1850, 1, 1), QtCore.QDate(2100, 1, 1)) cal.clicked[QtCore.QDate].connect(self.selectDate) # Confirm, Exit, Save buttons confirmButton = QPushButton('Confirm', self) exitButton = QPushButton('Exit', self) saveButton = QPushButton('Save', self) # (widget, rowNo, colNo, GridRowSpan, GridColSpan) grid.addWidget(m, 0, 0, 100, 90) grid.addWidget(cal, 0, 90, 60, 10) grid.addWidget(confirmButton, 60, 91, 3, 3) grid.addWidget(saveButton, 60, 94, 3, 3) grid.addWidget(exitButton, 60, 97, 3, 3) # Connect button to events confirmButton.clicked.connect(self.confirm) exitButton.clicked.connect(self.quit) saveButton.clicked.connect(self.save) # Show UI self.show()
class MyMainWindow(QMainWindow): displaying: bool = False # 是否在循环刷新vtk控件 frame_rate = 25 # 帧率 origin_delta_tdb = 0.05 delta_tdb = origin_delta_tdb def __init__(self, parent=None): super(MyMainWindow, self).__init__(parent) # 设置标题,大小,图标 self.setWindowTitle("2016HO3") self.resize(1200, 700) self.setWindowIcon(QIcon("data/icon.jpg")) # 初始化数据 self.dataProvider = DataProvider("data/de430.bsp", "data/status.eph") self.dataProvider.current_tdb = date2TDB( QDate.currentDate()) # 设置为当前日期 # 初始化VTK控件 self.vtkWidget = MyVTKWidget() # VTK控件对象 self._init_planets() # 插入行星显示主体 self._update_data() # 更新球体坐标到当前日期 # 初始化 UI self._initUI() # connections self.okButton.clicked.connect(self._on_OKButton_clicked) self.calendar.selectionChanged.connect(self._onCalChanged) self.speedButton_moreSlower.clicked.connect( self._on_speedButton_moreSlower) self.speedButton_slower.clicked.connect(self._on_speedButton_slower) self.speedButton_origion.clicked.connect(self._on_speedButton_origion) self.speedButton_faster.clicked.connect(self._on_speedButton_faster) self.speedButton_moreFaster.clicked.connect( self._on_speedButton_moreFaster) # log log("MainWindow Ready.", "info") self.window_status_label.setText("Ready") return def _initUI(self): # 分割窗口,并添加控件 # 右半部分 rSplitter = QSplitter(Qt.Vertical) rFrame = QFrame() rLayout = QVBoxLayout() rLayout.addWidget(self.vtkWidget) rLayout.setContentsMargins(0, 0, 0, 0) # ? rFrame.setLayout(rLayout) rSplitter.addWidget(rFrame) # status bar self.window_status_label = QLabel() self.window_status_label.setMinimumWidth(200) self.window_status_label.setAlignment(Qt.AlignRight) self.statusBar = QStatusBar() self.statusBar.setMinimumWidth(300) self.statusBar.addPermanentWidget(self.window_status_label) rSplitter.addWidget(self.statusBar) # 拉伸比例 rSplitter.setStretchFactor(0, 9) rSplitter.setStretchFactor(1, 1) # 左边 self.lSplitter = QSplitter(Qt.Vertical) lFrame = QFrame() lLayout = QVBoxLayout() # 大标题2016HO3 lLabel0 = QLabel() lLabel0.setText("2016HO3") lLabel0.setFont(QFont("Microsoft YaHei", 30, QFont.Bold)) lLabel0.setAlignment(Qt.AlignCenter) lLayout.addWidget(lLabel0) # 0 lLayout.setStretch(0, 1.5) # Select start date lLabel = QLabel() # lLabel.setText("Select start date: ") # lLabel.setFont(QFont("Microsoft YaHei", 20, QFont.Bold)) lLabel.setAlignment(Qt.AlignCenter) lLayout.addWidget(lLabel) # 1 lLayout.setStretch(1, 1) # 日历 self.calendar = QCalendarWidget() self.calendar.setGridVisible(True) self.calendar.setDateRange(QDate(1900, 1, 1), QDate(2195, 12, 24)) self.calendar.setMaximumHeight(300) # lLayout.addWidget(self.calendar) # 2 # 速度控制控件 self.speed_box = QWidget() self.speed_layout = QHBoxLayout() self.speed_box.setLayout(self.speed_layout) speed_button_width = 40 # 按钮宽度 self.speedButton_moreSlower = QPushButton("<<<") self.speedButton_moreSlower.setMaximumWidth(speed_button_width) self.speedButton_slower = QPushButton("<") self.speedButton_slower.setMaximumWidth(speed_button_width) self.speedButton_origion = QPushButton("▶") self.speedButton_origion.setMaximumWidth(speed_button_width) self.speedButton_faster = QPushButton(">") self.speedButton_faster.setMaximumWidth(speed_button_width) self.speedButton_moreFaster = QPushButton(">>>") self.speedButton_moreFaster.setMaximumWidth(speed_button_width) self.speed_layout.addWidget(self.speedButton_moreSlower) self.speed_layout.addWidget(self.speedButton_slower) self.speed_layout.addWidget(self.speedButton_origion) self.speed_layout.addWidget(self.speedButton_faster) self.speed_layout.addWidget(self.speedButton_moreFaster) lLayout.addWidget(self.speed_box) lLayout.setStretch(2, 4) # 日历标签 self.calendar_label = QLabel() self.calendar_label.setFont(QFont("Microsoft YaHei", 10, QFont.Bold)) self.calendar_label.setAlignment(Qt.AlignCenter) self._onCalChanged() lLayout.addWidget(self.calendar_label) # 3 lLayout.setStretch(3, 1) # OK按钮 self.okButton = QPushButton("▶") self.okButton.setMinimumHeight(50) self.okButton.setFont(QFont("Microsoft YaHei", 20, QFont.Bold)) lLayout.addWidget(self.okButton) # 4 lLayout.setStretch(4, 1) # 空标签(为了占地方) tempLabel = QLabel() tempLabel.setMaximumHeight(50) lLayout.addWidget(tempLabel) # 5 lLayout.setStretch(5, 1) lFrame.setLayout(lLayout) self.lSplitter.addWidget(lFrame) # 总布局 splitter_main = QSplitter(Qt.Horizontal) splitter_main.addWidget(self.lSplitter) # 左边 splitter_main.addWidget(rSplitter) # 右边 splitter_main.setStretchFactor(0, 1) splitter_main.setStretchFactor(1, 5) self.setCentralWidget(splitter_main) return def _init_planets(self): # TODO 改半径,改为实际大小 # 太阳 self._build_planet_actors('Sun', np.array([0, 0, 0]), 0.2, "White") # 地球 self._build_planet_actors('Earth', np.array([0, 0, 0]), 0.09, "SkyBlue") # 2016HO3 self._build_planet_actors('2016HO3', np.array([0, 1, 0]), 0.03, "Pink") # Mercury self._build_planet_actors('Mercury', np.array([0, 1, 0]), 0.05, "Gold") # Venus self._build_planet_actors('Venus', np.array([0, 1, 0]), 0.04, "Green") # 光照 # sun_light = vtkLight() # sun_light.SetColor(1, 1, 1) # sun_light.SetPosition(0, 0, 0) # self.vtkWidget.renderer.AddLight(sun_light) return None def _build_planet_actors(self, key: str, Center: np.array(3), radius: float, color: str): sphereSource = vtk.vtkSphereSource() # Make the surface smooth. sphereSource.SetPhiResolution(100) sphereSource.SetThetaResolution(100) mapper = vtk.vtkPolyDataMapper() mapper.SetInputConnection(sphereSource.GetOutputPort()) actor = vtk.vtkActor() actor.SetMapper(mapper) actor.GetProperty().SetColor(Colors.GetColor3d(color)) sphereSource.SetCenter(Center[0], Center[1], Center[2]) sphereSource.SetRadius(radius) # 标签 vText = vtkVectorText() vText.SetText(key) textMapper = vtkPolyDataMapper() textMapper.SetInputConnection(vText.GetOutputPort()) textActor = vtkFollower() textActor.SetMapper(textMapper) textActor.SetScale(0.05) # textActor.AddPosition(Center[0], Center[1], Center[2]) textActor.SetPosition(Center[0], Center[1], Center[2]) textActor.SetCamera(self.vtkWidget.renderer.GetActiveCamera()) # 加入数据集 self.dataProvider.add_sphere_source(key, sphereSource, textActor) self.vtkWidget.renderer.AddActor(actor) self.vtkWidget.renderer.AddActor(textActor) return def _on_OKButton_clicked(self): log("OK clicked", "info") if not self.displaying: self.displaying = True self.okButton.setText("||") log("go, displaying=" + self.displaying.__str__(), "debug") self._display_loop() else: # displaying self.displaying = False self.okButton.setText("▶") log("pause, displaying=" + self.displaying.__str__(), "debug") QApplication.processEvents() return def _display_loop(self): log("start displaying", "info") self.window_status_label.setText("Displaying") while self.displaying: frame_start = time.time() # 帧开始时间 frame_time = 1 / self.frame_rate # 帧时长 # update data (takes time) self._update_data() # 控制帧率 time_spent = time.time() - frame_start time_left = frame_time - time_spent if time_left > 0: time.sleep(time_left) self._refresh_vtkDisplay() QApplication.processEvents() self.window_status_label.setText("Pause") log("displaying circle quit", "info") return def _update_data(self): current_tdb = self.dataProvider.current_tdb new_tdb = current_tdb + self.delta_tdb self.dataProvider.update_to_tdb(new_tdb) return def _refresh_vtkDisplay(self): self.vtkWidget.GetRenderWindow().Render() # 刷新 # Show current tdb self.vtkWidget.commentTextActor.SetInput("TDB=%.4f\ncomment" % self.dataProvider.current_tdb) QApplication.processEvents() return def _onCalChanged(self): date = self.calendar.selectedDate() tdb = date2TDB(date) self.calendar_label.setText("%s TDB = %.2f" % (str(date.toPyDate()), tdb)) # todo # TODO 重新设置速率步长 large_step = 0.3 small_step = 0.1 def _on_speedButton_moreSlower(self): step = self.large_step if self.delta_tdb - step > 0: self.delta_tdb -= step log("speed more slower, delta_tdb=%f" % self.delta_tdb, "info") def _on_speedButton_slower(self): step = self.small_step if self.delta_tdb - step > 0: self.delta_tdb -= step log("speed slower, delta_tdb=%f" % self.delta_tdb, "info") def _on_speedButton_origion(self): self.delta_tdb = self.origin_delta_tdb log("speed origion", "info") def _on_speedButton_faster(self): step = self.small_step self.delta_tdb += step log("speed faster, delta_tdb=%f" % self.delta_tdb, "info") def _on_speedButton_moreFaster(self): step = self.large_step self.delta_tdb += step log("speed more faster, delta_tdb=%f" % self.delta_tdb, "info") def closeEvent(self, *args, **kwargs): log("Window Closed.", "Info") exit()