class ClusterDialog(QDialog): editClusterName = None def __init__(self, lifeline, defaultName, parent = None): super(ClusterDialog, self).__init__(parent) self.lifeline = lifeline layout = QVBoxLayout(self) message = QLabel('Enter group name') layout.addWidget(message) self.editClusterName = QLineEdit(defaultName) self.editClusterName.setFixedHeight(30) self.editClusterName.setFixedWidth(400) self.editClusterName.textChanged.connect(self.validateCluster) layout.addWidget(self.editClusterName) self.validation_msg = QLabel(' ') layout.addWidget(self.validation_msg) buttons = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel, QtCore.Qt.Horizontal, self) buttons.accepted.connect(self.accept) buttons.rejected.connect(self.reject) layout.addWidget(buttons) self.validateCluster() def validateCluster(self): cnt = 0 for l in self.lifeline: if self.editClusterName.text() in l.getClassName() and not l.getFlagCluster() and not l.getClusterLifeline(): cnt += 1 available_flag = True for l in self.lifeline: if self.editClusterName.text() in l.getClassName() and l.getFlagCluster(): available_flag = False break if available_flag: self.validation_msg.setText("group name includes %d life-lines" % (cnt)) else: self.validation_msg.setText("group name is not available") def getClusterText(self): return self.editClusterName.text() @staticmethod def getClusterName(lifelines, defaultName, parent = None): dialog = ClusterDialog(lifelines,defaultName,parent) result = dialog.exec_() return (result, dialog.getClusterText())
class PyCalcUi(QMainWindow): """PyCalc's View (GUI).""" def __init__(self, win_title: str = 'PyCalc', win_size: Tuple[int, int] = (235, 235), icon_path: Union[Path, str, None] = Path(R'.\coffeebean.ico') ) -> None: """View initializer.""" super().__init__() # Set some main window's properties self.setWindowTitle(win_title) self.setFixedSize(win_size[0], win_size[1]) if isinstance(icon_path, Path): icon_path = str(icon_path.resolve()) self.setWindowIcon(QIcon(icon_path)) # Set the central widget self._centralWidget = QWidget(self) self.setCentralWidget(self._centralWidget) self.generalLayout = QVBoxLayout() self._centralWidget.setLayout(self.generalLayout) # Create the display and the buttons self._createDisplay() self._createButtons() def _createDisplay(self) -> None: """Create the display.""" # Create the display widget self.display = QLineEdit() # Set some display's properties self.display.setFixedHeight(35) self.display.setAlignment(Qt.AlignRight) self.display.setReadOnly(True) # Add the display to the general layout self.generalLayout.addWidget(self.display) def _createButtons(self) -> None: """Create the buttons.""" self.buttons: Dict[str, QPushButton] = {} buttonsLayout = QGridLayout() # Button text | position on the QGridLayout buttons: Dict[str, Tuple[int, int]] = {'7': (0, 0), '8': (0, 1), '9': (0, 2), '/': (0, 3), 'C': (0, 4), '4': (1, 0), '5': (1, 1), '6': (1, 2), '*': (1, 3), '(': (1, 4), '1': (2, 0), '2': (2, 1), '3': (2, 2), '-': (2, 3), ')': (2, 4), '0': (3, 0), '00': (3, 1), '.': (3, 2), '+': (3, 3), '=': (3, 4), } # Create the buttons and add them to the grid layout for btnText, pos in buttons.items(): self.buttons[btnText] = QPushButton(btnText) self.buttons[btnText].setFixedSize(40, 40) buttonsLayout.addWidget(self.buttons[btnText], pos[0], pos[1]) # Add buttonsLayout to the general layout self.generalLayout.addLayout(buttonsLayout) def setDisplayText(self, text: str) -> None: """Set display's text.""" self.display.setText(text) self.display.setFocus() def displayText(self) -> str: """Get display's text.""" return cast(str, self.display.text()) def clearDisplay(self) -> None: """Clear the display.""" self.setDisplayText('')
class ParameterInteger(QWidget): def check_int(self, s): if s[0] in ("-", "+"): return s[1:].isdigit() return s.isdigit() def clamp(self, value, min_value, max_value): if value < min_value: return min_value elif value > max_value: return max_value else: return value def __init__(self, parent=None, value=0, name="", label_text="", min_value=None, max_value=None, label_width=64, height=22, min_visible=0, max_visible=10, change_callback=None): QWidget.__init__(self, parent) self.VERTICAL_MARGIN = 0 self.HORIZONTAL_MARGIN = 0 self.name = name self.label_text = label_text self.min_value_raw = min_value self.max_value_raw = max_value self.min_value = min_value if min_value is not None else -sys.maxsize self.max_value = max_value if max_value is not None else sys.maxsize self.value = self.clamp(value, self.min_value, self.max_value) self.min_visible = max(self.min_value, min(min_visible, self.value)) self.max_visible = min(self.max_value, max(max_visible, self.value)) self._is_callback_define = False if change_callback is not None: self._change_callback = change_callback self._is_callback_define = True self._last_call = None self.label = QLabel(label_text) self.label.setFixedWidth(label_width) self.label.setFixedHeight(height) self.value_textbox = QLineEdit() self.value_textbox.setFixedWidth(52) self.value_textbox.setFixedHeight(height) self._update_value_label() self.slider = QSlider(Qt.Horizontal) self.slider.setFixedHeight(height) self._update_visible_interval() self.slider.setValue(value) layout = QHBoxLayout() layout.setContentsMargins(self.HORIZONTAL_MARGIN, self.VERTICAL_MARGIN, self.HORIZONTAL_MARGIN, self.VERTICAL_MARGIN) layout.addWidget(self.label) layout.addWidget(self.value_textbox) layout.addWidget(self.slider) self.setLayout(layout) self.slider.valueChanged.connect(self.slider_valueChanged) self.value_textbox.returnPressed.connect(self.textbox_enter) self.value_textbox.editingFinished.connect(self.textbox_enter) self.slider.sliderReleased.connect(self.slider_sliderReleased) def _update_visible_interval(self): self.slider.setRange(self.min_visible, self.max_visible) def _update_value_label(self): self.value_textbox.setText(str(self.value)) def slider_valueChanged(self, value): self.value = value self._update_value_label() self.value_change() def slider_sliderReleased(self): self.try_change_visible(self.value) self.slider.setValue(self.value) def try_change_visible(self, new_value): delta = self.max_visible - self.min_visible # increase visible interval if new value out of the current if new_value <= self.min_visible: self.min_visible = max(self.min_value, new_value - delta) if new_value >= self.max_visible: self.max_visible = min(self.max_value, new_value + delta) self._update_visible_interval() def textbox_enter(self): text = self.value_textbox.text() # check is this text is integer if self.check_int(text): new_value = int(text) # clamp value if new_value < self.min_value: new_value = self.min_value if new_value > self.max_value: new_value = self.max_value self.try_change_visible(new_value) self.slider.setValue(new_value) self._update_value_label() self.value_change() else: self._update_value_label() self.value_textbox.clearFocus() def value_change(self): if self._is_callback_define: if self._last_call is None or self._last_call != self.value: self._last_call = self.value self._change_callback(param_name=self.name, param_value=self.value)
class PyCalcUi(QWidget): """PyCalc's View (GUI).""" def __init__(self, parent: QWidget = None, ) -> None: """View initializer.""" super().__init__() self.setFixedSize(235, 235) self.generalLayout = QVBoxLayout() self.setLayout(self.generalLayout) # Create the display and the buttons self._createDisplay() self._createButtons() # Connect signals and slots self._connectSignals() def _createDisplay(self) -> None: """Create the display.""" # Create the display widget self.display = QLineEdit() # Set some display's properties self.display.setFixedHeight(35) self.display.setAlignment(Qt.AlignRight) self.display.setReadOnly(True) # Add the display to the general layout self.generalLayout.addWidget(self.display) def _createButtons(self) -> None: """Create the buttons.""" print("creating button") self.buttons: Dict[str, QPushButton] = {} buttonsLayout = QGridLayout() # Button text | position on the QGridLayout buttons: Dict[str, Tuple[int, int]] = {'7': (0, 0), '8': (0, 1), '9': (0, 2), '/': (0, 3), 'C': (0, 4), '4': (1, 0), '5': (1, 1), '6': (1, 2), '*': (1, 3), '(': (1, 4), '1': (2, 0), '2': (2, 1), '3': (2, 2), '-': (2, 3), ')': (2, 4), '0': (3, 0), '00': (3, 1), '.': (3, 2), '+': (3, 3), '=': (3, 4), } # Create the buttons and add them to the grid layout for btnText, pos in buttons.items(): self.buttons[btnText] = QPushButton(btnText) self.buttons[btnText].setFixedSize(40, 40) buttonsLayout.addWidget(self.buttons[btnText], pos[0], pos[1]) # Add buttonsLayout to the general layout self.generalLayout.addLayout(buttonsLayout) def setDisplayText(self, text: str) -> None: """Set display's text.""" self.display.setText(text) self.display.setFocus() def displayText(self) -> str: """Get display's text.""" return cast(str, self.display.text()) def clearDisplay(self) -> None: """Clear the display.""" self.setDisplayText('') ERROR_MSG = 'ERROR' def _calculateResult(self) -> None: """Evaluate expressions.""" result = self._evaluateExpression(self.displayText()) self.setDisplayText(result) def _buildExpression(self, sub_exp: str) -> None: """Build expression.""" if self.displayText() == self.ERROR_MSG: self.clearDisplay() expression = self.displayText() + sub_exp self.setDisplayText(expression) def _connectSignals(self) -> None: # Connect signals and slots. for btnText, btn in self.buttons.items(): if btnText not in {'=', 'C'}: btn.clicked.connect(partial(self._buildExpression, btnText)) self.buttons['='].clicked.connect(self._calculateResult) self.display.returnPressed.connect(self._calculateResult) self.buttons['C'].clicked.connect(self.clearDisplay) def _evaluateExpression(self, expression: str) -> str: """Evaluate an expression.""" try: result = str(eval(expression, {}, {})) except Exception: result = PyCalcUi.ERROR_MSG finally: return result
class NewWindow(QMainWindow): def __init__(self): super(NewWindow, self).__init__() # def setupUi(self, NewWindow): self.latlong = "0" self.textEdit = QTextEdit() self.mainWidget = QWidget() self.mainLayout = QVBoxLayout() font0 = QFont("Arial", 12) font0.setBold(True) font01 = QFont("Arial", 12) font02 = QFont("Arial", 12) self.text1 = QLabel("<b>Domyślne Współrzędne:</b><br/>" "Szerokość: 51° 06' 00''<br/>" "Długość: 17° 01' 00''<br/>" "(Współrzędne geograficzne Wrocławia)") self.solarpanelcordinates = QLabel('WSPÓŁRZĘDNE PANELU SŁONECZNEGO: ') self.solarpanelcordinates.setFont(font0) # self.solarpanelcordinates.setFrameStyle(QFrame.Box | QFrame.Sunken) # self.solarpanelcordinates.setMidLineWidth(6) self.text1.setFont(font01) self.text1.setFrameStyle(QFrame.Box | QFrame.Raised) self.text1.setMidLineWidth(6) self.result4 = QLabel('') self.result4.setFont(font02) self.result4.setMidLineWidth(3) self.result5 = QLabel('') self.result5.setFont(font02) self.result6 = QLabel('') self.result6.setFont(font02) self.result7 = QLabel('') self.result7.setFont(font02) self.result8 = QLabel('') self.result8.setFont(font02) self.result9 = QLabel('') self.result9.setFont(font02) self.mainLayout.addWidget(self.text1) self.mainLayout.addWidget(self.solarpanelcordinates) self.mainLayout.addWidget(self.result4) self.mainLayout.addWidget(self.result5) self.mainLayout.addWidget(self.result6) self.mainLayout.addWidget(self.result7) self.mainLayout.addWidget(self.result8) self.mainLayout.addWidget(self.result9) self.mainWidget.setLayout(self.mainLayout) self.setCentralWidget(self.mainWidget) #self.createActions() #self.createMenus() #self.createToolBars() #self.createStatusBar() self.createDockWindows() self.setWindowTitle("Nowe Okno") self.rad = 0 self.o = 0 self.timer = QTimer() self.timer.timeout.connect(self.dLocation) self.timerIsUp = False self.timer2 = QTimer() self.timer2.timeout.connect(self.update) self.timer2.start(1000) #self.newLetter() self.s = ephem.Sun() self.o = ephem.Observer() def createStatusBar(self): self.statusBar().showMessage("Gotowy") def dLocation(self): self.s = ephem.Sun() self.s.compute(epoch=ephem.now()) if self.dateandtimeEdit.text(): self.o.date = self.dateandtimeEdit.text() else: self.o.date = ephem.now() # 00:22:07 EDT 06:22:07 UT+1 self.s.compute(self.o) hour_angle = self.o.sidereal_time() - self.s.ra t = ephem.hours(hour_angle + ephem.hours('12:00')).norm # .norm for 0..24 self.rad = str(ephem.hours(hour_angle + ephem.hours('12:00')).norm) # self.result.setText("R.A.: " + str(self.s.a_ra) + " DEC.: " + str(self.s.a_dec)) # self.result2.setText("HOUR ANGLE: " + str(self.rad) + " SIDERAL TIME: " + str(self.o.sidereal_time())) # self.result3.setText("SUN Altitude: " + str(self.s.alt) + " SUN Azimuth: " + str(self.s.az)) self.result4.setText("R.A.: " + str(self.s.a_ra)) self.result5.setText("DEC.: " + str(self.s.a_dec)) self.result6.setText("HOUR ANGLE: " + str(self.rad)) self.result7.setText("SIDERAL TIME: " + str(self.o.sidereal_time())) self.result8.setText("SUN Altitude: " + str(self.s.alt)) self.result9.setText("SUN Azimuth: " + str(self.s.az)) def createDockWindows(self): dock = QDockWidget("Współrzędne Geograficzne Panelu: ", self) s = ephem.Sun() s.compute(epoch=ephem.now()) dock.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea) self.multiWidget3 = QWidget() font5 = QFont("Arial", 12) font6 = QFont("Arial", 17) self.vLayout3 = QGridLayout() self.result = QLabel(self.latlong) self.latitude = QLabel('Szerokość') self.longitude = QLabel('Długość') self.dateandtime = QLabel('Data i Czas') self.solarpanelcor = QLabel('WSPÓŁRZĘDNE PANELU SŁONECZNEGO: ') self.latitudeEdit = QLineEdit() self.latitudeEdit.setFixedHeight(28) self.latitudeEdit.setFixedWidth(386) self.latitudeEdit.setStatusTip( "Wprowadzona szerokość powinna być w stopniach dziesiętnych (np.: 51.100000)" ) self.longitudeEdit = QLineEdit() self.longitudeEdit.setFixedHeight(28) self.longitudeEdit.setFixedWidth(386) self.longitudeEdit.setStatusTip( "Wprowadzona długość powinna być w stopniach dziesiętnych (np.: 17.03333)" ) self.dateandtimeEdit = QLineEdit() self.dateandtimeEdit.setFixedHeight(28) self.dateandtimeEdit.setFixedWidth(386) self.dateandtimeEdit.setStatusTip( "Wprowadzona data powinna być w formacie: rok/mies/dzień<spacja>godz:min:sek (np.: 2022/12/4 8:12:7)" ) self.button = QPushButton('Wylicz współrzędne / Przerwij liczenie', self) self.button.clicked.connect(self.handleButton3) self.latitude.setFont(font5) self.longitude.setFont(font5) self.dateandtime.setFont(font5) self.button.setFont(font6) self.button.setStatusTip("Rozpoczyna Obliczenia") self.vLayout3.addWidget(self.latitude) self.vLayout3.addWidget(self.latitudeEdit) self.vLayout3.addWidget(self.longitude) self.vLayout3.addWidget(self.longitudeEdit) self.vLayout3.addWidget(self.dateandtime) self.vLayout3.addWidget(self.dateandtimeEdit) self.vLayout3.addWidget(self.button) self.multiWidget3.setLayout(self.vLayout3) dock.setWidget(self.multiWidget3) self.addDockWidget(Qt.RightDockWidgetArea, dock) # self.viewMenu.addAction(dock.toggleViewAction()) def handleButton3(self): self.button.setStatusTip("Przerywa liczenie") if self.timerIsUp == False: if self.latitudeEdit.text() and self.longitudeEdit.text(): self.o.lat = self.latitudeEdit.text() self.o.lon = self.longitudeEdit.text() else: self.o.lon, self.o.lat = '17.03333', '51.100000' # Współrzędne Wrocławia self.timer.start(1000) self.timerIsUp = True else: self.timer.stop() self.timerIsUp = False self.button.setStatusTip("Rozpoczyna Obliczenia")
class NewWindow2(QMainWindow): def __init__(self): super(NewWindow2, self).__init__() self.latlong = "0" self.textEdit = QTextEdit() self.mainWidget = QWidget() self.mainLayout = QVBoxLayout() font0 = QFont("Arial", 12) font0.setBold(True) font01 = QFont("Arial", 12) font02 = QFont("Arial", 12) self.text1 = QLabel("<b>Domyślne Współrzędne:</b><br/>" "Szerokość: 51° 06' 00''<br/>" "Długość: 17° 01' 00''<br/>" "(Współrzędne geograficzne Wrocławia)") self.solarpanelcordinates = QLabel('WSPÓŁRZĘDNE PANELU SŁONECZNEGO: ') self.solarpanelcordinates.setFont(font0) # self.solarpanelcordinates.setFrameStyle(QFrame.Box | QFrame.Sunken) # self.solarpanelcordinates.setMidLineWidth(6) #self.text1.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter) self.text1.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter) self.text1.setFont(font01) self.text1.setFrameStyle(QFrame.Box | QFrame.Raised) self.text1.setMidLineWidth(6) self.result4 = QLabel('') self.result4.setFont(font02) self.result4.setMidLineWidth(3) self.result5 = QLabel('') self.result5.setFont(font02) self.result6 = QLabel('') self.result6.setFont(font02) self.result7 = QLabel('') self.result7.setFont(font02) self.result8 = QLabel('') self.result8.setFont(font02) self.result9 = QLabel('') self.result9.setFont(font02) self.mainLayout.addWidget(self.text1) self.mainLayout.addWidget(self.solarpanelcordinates) self.mainLayout.addWidget(self.result4) self.mainLayout.addWidget(self.result5) self.mainLayout.addWidget(self.result6) self.mainLayout.addWidget(self.result7) self.mainLayout.addWidget(self.result8) self.mainLayout.addWidget(self.result9) self.mainWidget.setLayout(self.mainLayout) self.setCentralWidget(self.mainWidget) self.createActions() self.createMenus() #self.createToolBars() self.createStatusBar() self.createDockWindows() self.setWindowTitle("Nowe Okno") self.rad = 0 self.o = 0 self.timer = QTimer() self.timer.timeout.connect(self.dLocation) self.timerIsUp = False self.timer2 = QTimer() self.timer2.timeout.connect(self.update) self.timer2.start(1000) self.newLetter() self.s = ephem.Sun() self.o = ephem.Observer() # zmienna = [] # i=0 # with open('Breslau.txt', 'r') as f: # for line in f: # zmienna.append(line) # i=i+1 # print(zmienna) # f = self.nameEdit.text() # f = self.latitudeEdit.text() # f = self.longitudeEdit.text() # f = self.dateandtimeEdit.text() # print(self.nameEdit.text()) # print(self.latitudeEdit.text()) # print(self.longitudeEdit.text()) # print(self.dateandtimeEdit.text()) # class MainWindow(QMainWindow): # def __init__(self): # super(MainWindow, self).__init__() # # self.latlong = "0" # self.textEdit = QTextEdit() # self.setCentralWidget(self.textEdit) # self.createActions() # self.createMenus() # #self.createToolBars() # self.createStatusBar() # self.createDockWindows() # self.setWindowTitle("Panel Słoneczny") # self.rad = 0 # self.o = 0 # self.timer = QTimer() # self.timer.timeout.connect(self.dLocation) # self.timerIsUp = False # self.timer2 = QTimer() # self.timer2.timeout.connect(self.update) # self.timer2.start(1000) # self.newLetter() # self.s = ephem.Sun() # self.o = ephem.Observer() def newWindow(self): self.newWin = NewWindow() self.newWin.show() def newWindow2(self): self.newWin2 = NewWindow2() self.newWin2.show() def newLetter(self): self.textEdit.clear() self.text2 = QLabel("<b>Domyślne Współrzędne:</b><br/>" "Szerokość: 51° 06' 00''<br/>" "Długość: 17° 01' 00''<br/>" "(Współrzędne geograficzne Wrocławia)") cursor = self.textEdit.textCursor() cursor.movePosition(QTextCursor.Start) topFrame = cursor.currentFrame() topFrameFormat = topFrame.frameFormat() topFrameFormat.setPadding(16) topFrame.setFrameFormat(topFrameFormat) textFormat = QTextCharFormat() boldFormat = QTextCharFormat() boldFormat.setFontWeight(QFont.Bold) italicFormat = QTextCharFormat() italicFormat.setFontItalic(True) tableFormat = QTextTableFormat() tableFormat.setBorder(1) tableFormat.setCellPadding(16) tableFormat.setAlignment(Qt.AlignRight) cursor.insertTable(1, 1, tableFormat) cursor.insertText("Domyślne Współrzędne: ", boldFormat) self.text2.setText(self.nameEdit.text()) cursor.insertText #self.text1.setText(self.nameEdit.text()) cursor.insertBlock() cursor.insertBlock() cursor.insertText("Szerokość: 51° 06' 00''", textFormat) cursor.insertBlock() cursor.insertBlock() cursor.insertText("Długość: 17° 01' 00''") cursor.insertBlock() cursor.insertBlock() cursor.insertText("(Współrzędne geograficzne Wrocławia)") cursor.setPosition(topFrame.lastPosition()) # cursor.insertText(QDate.currentDate().toString("Dziś jest: d MMMM yyyy:"), # textFormat) # cursor.insertText(QTime.currentTime().toString(" hh:mm:ss"), textFormat) # # cursor.insertText(QTimer.timer(" hh:mm:ss", 1000), textFormat) # cursor.insertBlock() # cursor.insertBlock() # cursor.insertText("Wrocław: ", textFormat) # cursor.insertText("17.03 deg; 51.10 deg", textFormat) # cursor.insertText(",", textFormat) # for i in range(3): # cursor.insertBlock() # cursor.insertText("Text", textFormat) def dLocation(self): self.s = ephem.Sun() self.s.compute(epoch=ephem.now()) if self.nameEdit.text(): self.text1.setText(self.nameEdit.text()) font03 = QFont("Arial", 16) font03.setBold(True) self.text1.setFont(font03) if not self.dateandtimeEdit.text(): self.o.date = ephem.now() # 00:22:07 EDT 06:22:07 UT+1 else: if self.dateandtimeEdit.text(): self.o.date = self.dateandtimeEdit.text() self.text1.setText("<b>Obliczenia dla:</b><br/> " + self.dateandtimeEdit.text()) font03 = QFont("Arial", 16) font03.setBold(True) self.text1.setFont(font03) else: self.o.date = ephem.now() # 00:22:07 EDT 06:22:07 UT+1 #self.o.date = ephem.now() # 00:22:07 EDT 06:22:07 UT+1 self.s.compute(self.o) hour_angle = self.o.sidereal_time() - self.s.ra t = ephem.hours(hour_angle + ephem.hours('12:00')).norm # .norm for 0..24 self.rad = str(ephem.hours(hour_angle + ephem.hours('12:00')).norm) # self.result.setText("R.A.: " + str(self.s.a_ra) + " DEC.: " + str(self.s.a_dec)) # self.result2.setText("HOUR ANGLE: " + str(self.rad) + " SIDERAL TIME: " + str(self.o.sidereal_time())) # self.result3.setText("SUN Altitude: " + str(self.s.alt) + " SUN Azimuth: " + str(self.s.az)) self.result4.setText("R.A.: " + str(self.s.a_ra)) self.result5.setText("DEC.: " + str(self.s.a_dec)) self.result6.setText("HOUR ANGLE: " + str(self.rad)) self.result7.setText("SIDERAL TIME: " + str(self.o.sidereal_time())) self.result8.setText("SUN Altitude: " + str(self.s.alt)) self.result9.setText("SUN Azimuth: " + str(self.s.az)) def update(self): time = QTime.currentTime() self.clock.setText(QTime.currentTime().toString("hh:mm:ss")) def about(self): QMessageBox.about( self, "O Programie", "<p align=justify>Program <b><i>''Panel Słoneczny''</b></i> pozwala na wyliczenie współrzędnych Słońca, " "na podstawie których należy ustawić Panel. Domyślnie program startuje dla " "szerokości i długości geograficznej Wrocławia z obecną dla użytkownika datą i godziną. " "Użytkownik może podać swoją szerokość i długość geograficzną oraz swój czas i datę wpisując " "w odpowiednie pola swoje dane. W polach Szerokość i Długość należy podać w stopniach dziesiętnych " "W polu ''Data i Czas'' własne dane należy wpisywać zgodnie ze schematem: " "rok/mies/dzień godz:min:sek (np.: 2019/02/04 14:02:03). Pisanie zer przed godzinami, minutami i sekundami " "dla liczb poniżej dziesięciu nie jest wymagane (2019/02/04 14:02:03 = 2019/2/4 14:2:3)<p/>" ) def about2(self): QMessageBox.about( self, "Symbole i skróty", "<p align=justify><b><i>Rektascensja (R.A.)</b></i> – (Right Ascension; wznoszenie proste) jest kątem dwuściennym " "pomiędzy płaszczyzną koła godzinnego przechodzącego przez punkt Barana, a płaszczyzną koła godzinnego " "danego ciała niebieskiego). <br/>" "<b><i>Deklinacja (DEC.)</b></i> - kąt zawarty między płaszczyzną równika niebieskiego," "a prostą łączącą punkt na sferze niebieskiej, a środkiem sfery niebieskiej. " "Deklinacja zmienia się w zakresie od 90° (biegun północny) przez 0° (równik niebieski) do -90° (biegun południowy).<br/> " "<b><i>Kąt Godzinny (HOUR ANGLE)</b></i> - kąt dwuścienny zawarty pomiędzy płaszczyzną lokalnego południka " "i płaszczyzną koła godzinnego danego obiektu. Kąt godzinny odmierza się w kierunku zgodnym " "z dziennym ruchem sfery niebieskiej, a przyjmuje on wartości (0h,24h) lub (0°,360°) " "Kąt godzinny zależy od miejsca obserwacji (ulokowania panela) i od lokalnego czasu.<br/> " "<b><i>Czas Gwiazdowy (SIDERAL TIME)</b></i> - czyli kąt godzinny punktu Barana. ( Jeden z dwóch punktów " "przecięcia się ekliptyki z równikiem niebieskim. Moment przejścia Słońca przez punkt Barana " "oznacza początek astronomicznej wiosny na półkuli północnej. Dlatego nazywany jest także punktem " "równonocy wiosennej.)<br/> " "<b><i>Wysokość Słońca (nad horyzontem; SUN Altitude)</b></i> - na daną chwilę wyliczona wysokość Słońca, " "jeżeli jest ujemna to znaczy, że słońce jest pod horyzontem.<br/> " "<b><i>Azymut Słońca (SUN Azimuth)</b></i> - kąt dwuścienny, w programie liczy się w kierunku na wschód " "(stojąc twarzą do północy w prawo; w Astronomii jest tak samo, tzn. w prawo, ale zaczyna od południka)." "Azymut geograficzny i astronomiczny różni się o 180°.<p/> ") def createActions(self): # self.newLetterAct = QAction(QIcon.fromTheme('document-new', QIcon(':/images/new.png')), "&New Letter", # self, shortcut=QKeySequence.New, # statusTip="Create a new form letter", triggered=self.newLetter()) self.newWindowAct = QAction(QIcon.fromTheme('document-new', QIcon(':/images/new.png')), "&Nowe Okno", self, shortcut=QKeySequence.New, statusTip="Create a new form letter", triggered=self.newWindow2) self.saveAct = QAction(QIcon.fromTheme('document-save', QIcon(':/images/save.png')), "&Zapisz", self, shortcut=QKeySequence.Save, statusTip="Zapisz obecne współrzędne", triggered=self.save) self.loadAct = QAction(QtGui.QIcon(':/images/open.png'), "&Wczytaj", self, shortcut=QtGui.QKeySequence.Open, statusTip="Wczytaj współrzędne z pliku", triggered=self.load) self.aboutAct = QAction("&O Programie", self, statusTip="Pokazuje pomoc dla programu", triggered=self.about) self.aboutAct2 = QAction( "&Symbole i skróty", self, statusTip= "Pokazuje objaśnienia używanych w programie skrótów i symboli", triggered=self.about2) self.quitAct = QAction("&Zamknij", self, shortcut="Ctrl+Q", statusTip="Zamyka aplikację", triggered=self.close) self.DefaultAct = QAction( QIcon.fromTheme('document-default', QIcon(':/images/def.png')), "&Rozpocznij dla domyślnej lokacji", self, statusTip="Rozpoczyna obliczenia dla domyślnej lokacji (Wrocław)", triggered=self.handleButton2) def createToolBars(self): self.fileToolBar = self.addToolBar("File") self.fileToolBar.addAction(self.newLetterAct) def createMenus(self): self.fileMenu = self.menuBar().addMenu("&Plik") self.fileMenu.addAction(self.newWindowAct) self.fileMenu.addAction(self.saveAct) self.fileMenu.addAction(self.loadAct) self.fileMenu.addAction(self.DefaultAct) self.fileMenu.addSeparator() self.fileMenu.addAction(self.quitAct) self.fileMenu.addSeparator() self.editMenu = self.menuBar().addMenu("&Edycja") self.viewMenu = self.menuBar().addMenu("&Widok") self.menuBar().addSeparator() self.helpMenu = self.menuBar().addMenu("&Pomoc") self.helpMenu.addAction(self.aboutAct) self.helpMenu.addAction(self.aboutAct2) def createStatusBar(self): self.statusBar().showMessage("Gotowy", 3000) def saving(self): cursor = self.textEdit.textCursor() self.nameEdit.text() cursor.insertBlock() self.latitudeEdit.text() cursor.insertBlock() self.longitudeEdit.text() cursor.insertBlock() self.dateandtimeEdit.text() def save(self): filename, _ = QFileDialog.getSaveFileName(self, "Zapisywanie jako", '.', "Dokumenty textowe(*.txt)") if not filename: return file = QFile(filename) if not file.open(QFile.WriteOnly | QFile.Text): QMessageBox.warning( self, "Panel Słoneczny", "nie mógł zapisać pliku %s:\n%s." % (filename, file.errorString())) return out = QTextStream(file) #QApplication.setOverrideCursor(Qt.WaitCursor) #out << self.textEdit.toPlainText() out << self.nameEdit.text() + "\n" + self.latitudeEdit.text( ) + "\n" + self.longitudeEdit.text( ) + "\n" + self.dateandtimeEdit.text() #out << "self.text1.setText("+self.nameEdit.text()+")" #QApplication.restoreOverrideCursor() self.statusBar().showMessage("Zapisano w '%s'" % filename, 2000) def load(self): filename, _ = QFileDialog.getOpenFileName(self) if not filename: return file = QFile(filename) if not file.open(QFile.ReadOnly | QFile.Text): QMessageBox.warning( self, "Panel Słoneczny", "nie mógł wczytać pliku %s:\n%s." % (filename, file.errorString())) return inf = QTextStream(file) #QApplication.setOverrideCursor(QtCore.Qt.WaitCursor) self.textEdit.setPlainText(inf.readAll()) #with open(file, 'r') as input: with open('Breslau.txt', 'r') as f: # f = self.nameEdit.text() # f = self.latitudeEdit.text() # f = self.longitudeEdit.text() # f = self.dateandtimeEdit.text() # print(self.nameEdit.text()) # print(self.latitudeEdit.text()) # print(self.longitudeEdit.text()) # print(self.dateandtimeEdit.text()) # for line in f: # print (line, end='') f_name = f.readline() #f_name = self.nameEdit.text() self.text1.setText(f_name) f_lat = f.readline() f_lat = self.latitudeEdit.text() f_lon = f.readline() f_lon = self.longitudeEdit.text() f_dnt = f.readline() f_dnt = self.dateandtimeEdit.text() # for line in f: # if 'name' in line: # self.text1.setText(line) #if 'lat' in line: #self.text1.setText(self.textEdit.setPlainText(inf.readAll())) #self.text1.setText(self.nameEdit.text()) #QApplication.restoreOverrideCursor() #self.setCurrentFile(filename) self.statusBar().showMessage("Wczytano plik", 2000) def createDockWindows(self): # dock = QDockWidget('n', self) # dock.setFeatures(dock.NoDockWidgetFeatures) # dock.DockWidgetMovable = False # dock.setAllowedAreas(Qt.TopDockWidgetArea) # self.addDockWidget(Qt.TopDockWidgetArea, dock) dock = QDockWidget("Program", self) dock.setFeatures(dock.NoDockWidgetFeatures) dock.DockWidgetMovable = False dock.setAllowedAreas(Qt.LeftDockWidgetArea) self.multiWidget = QWidget() font1 = QFont("Courier New", 10) self.title = QLabel("SOLAR PANEL Program") font2 = QFont("Courier New", 10) font2.setBold(True) self.author = QLabel("Tomasz Dróżdż") self.author.setFont(font2) self.other = QLabel("Politechnika Wrocławska") self.other2 = QLabel("Automatyka i Robotyka") self.vLayout = QVBoxLayout() self.vLayout.addWidget(self.title) self.vLayout.addWidget(self.author) self.vLayout.addWidget(self.other) self.vLayout.addWidget(self.other2) self.multiWidget.setLayout(self.vLayout) dock.setWidget(self.multiWidget) self.addDockWidget(Qt.LeftDockWidgetArea, dock) dock = QDockWidget("Zegar", self) dock.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea) self.multiWidget2 = QWidget() font3 = QFont("Arial", 13) font4 = QFont("Arial", 20) self.date = QLabel(QDate.currentDate().toString("d MMMM yyyy: ")) self.clock = QLabel(QTime.currentTime().toString("hh:mm:ss")) self.date.setFont(font3) self.clock.setFont(font4) font4.setBold(True) self.vLayout2 = QVBoxLayout() self.vLayout2.addWidget(self.date) self.vLayout2.addWidget(self.clock) self.multiWidget2.setLayout(self.vLayout2) dock.setWidget(self.multiWidget2) self.addDockWidget(Qt.LeftDockWidgetArea, dock) self.viewMenu.addAction(dock.toggleViewAction()) dock = QDockWidget("Współrzędne Geograficzne Panelu: ", self) s = ephem.Sun() s.compute(epoch=ephem.now()) dock.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea) self.multiWidget3 = QWidget() font5 = QFont("Arial", 12) font6 = QFont("Arial", 17) self.vLayout3 = QGridLayout() self.result = QLabel(self.latlong) self.name = QLabel('Nazwa') self.latitude = QLabel('Szerokość') self.longitude = QLabel('Długość') self.dateandtime = QLabel('Data i Czas') # self.result = QLabel('') # self.result2 = QLabel('') # self.result3 = QLabel('') self.solarpanelcor = QLabel('WSPÓŁRZĘDNE PANELU SŁONECZNEGO: ') self.nameEdit = QLineEdit() self.nameEdit.setFixedHeight(28) self.nameEdit.setFixedWidth(386) self.nameEdit.setStatusTip( "Wprowadź nazwę dla konfiguracji współrzędnych i czasu") self.latitudeEdit = QLineEdit() self.latitudeEdit.setFixedHeight(28) self.latitudeEdit.setFixedWidth(386) self.latitudeEdit.setStatusTip( "Wprowadzona szerokość powinna być w stopniach dziesiętnych (np.: 51.100000)" ) self.longitudeEdit = QLineEdit() self.longitudeEdit.setFixedHeight(28) self.longitudeEdit.setFixedWidth(386) self.longitudeEdit.setStatusTip( "Wprowadzona długość powinna być w stopniach dziesiętnych (np.: 17.03333)" ) self.dateandtimeEdit = QLineEdit() self.dateandtimeEdit.setFixedHeight(28) self.dateandtimeEdit.setFixedWidth(386) self.dateandtimeEdit.setStatusTip( "Wprowadzona data powinna być w formacie: rok/mies/dzień<spacja>godz:min:sek (np.: 2022/12/4 8:12:7)" ) self.button = QPushButton('Wylicz współrzędne / Przerwij liczenie', self) self.button.clicked.connect(self.handleButton4) self.name.setFont(font5) self.latitude.setFont(font5) self.longitude.setFont(font5) self.dateandtime.setFont(font5) self.button.setFont(font6) self.button.setStatusTip("Rozpoczyna Obliczenia") # self.button.addAction(self.buttonAct) # self.solarpanelcor.setFont(font5) # self.result.setFont(font6) # self.result2.setFont(font6) # self.result3.setFont(font6) self.vLayout3.addWidget(self.name) self.vLayout3.addWidget(self.nameEdit) self.vLayout3.addWidget(self.latitude) self.vLayout3.addWidget(self.latitudeEdit) self.vLayout3.addWidget(self.longitude) self.vLayout3.addWidget(self.longitudeEdit) self.vLayout3.addWidget(self.dateandtime) self.vLayout3.addWidget(self.dateandtimeEdit) self.vLayout3.addWidget(self.button) # self.vLayout3.addWidget(self.solarpanelcor) # self.vLayout3.addWidget(self.result) # self.vLayout3.addWidget(self.result2) # self.vLayout3.addWidget(self.result3) self.multiWidget3.setLayout(self.vLayout3) dock.setWidget(self.multiWidget3) self.addDockWidget(Qt.RightDockWidgetArea, dock) self.viewMenu.addAction(dock.toggleViewAction()) def handleButton2(self): self.button.setStatusTip("Przerywa liczenie") if self.timerIsUp == False: self.o.lon, self.o.lat = '17.03333', '51.100000' # Współrzędne Wrocławia self.text1.setText("Wrocław") font03 = QFont("Arial", 16) font03.setBold(True) self.text1.setFont(font03) self.timer.start(1000) self.timerIsUp = True else: self.timer.stop() self.timerIsUp = False self.button.setStatusTip("Rozpoczyna Obliczenia") # def handleButton2(self): # print(self.nameEdit.text()) # print(self.latitudeEdit.text()) # print(self.longitudeEdit.text()) # print(self.dateandtimeEdit.text()) def handleButton3(self): self.button.setStatusTip("Przerywa liczenie") if self.timerIsUp == False: if self.latitudeEdit.text() and self.longitudeEdit.text(): self.o.lat = self.latitudeEdit.text() self.o.lon = self.longitudeEdit.text() if self.nameEdit.text(): self.text1.setText(self.nameEdit.text()) font03 = QFont("Arial", 16) font03.setBold(True) self.text1.setFont(font03) else: self.text1.setText("Wrocław") font03 = QFont("Arial", 16) font03.setBold(True) self.text1.setFont(font03) self.o.lon, self.o.lat = '17.03333', '51.100000' # Współrzędne Wrocławia self.timer.start(1000) self.timerIsUp = True else: self.timer.stop() self.timerIsUp = False self.button.setStatusTip("Rozpoczyna Obliczenia") def handleButton4(self): self.button.setStatusTip("Przerywa liczenie") if self.timerIsUp == False: #zastąpic wlasna logika # if self.latitudeEdit.text() and self.longitudeEdit.text(): # self.o.lat = self.latitudeEdit.text() # self.o.lon = self.longitudeEdit.text() if self.nameEdit.text(): self.text1.setText(self.nameEdit.text()) font03 = QFont("Arial", 16) font03.setBold(True) self.text1.setFont(font03) else: if self.latitudeEdit.text() and self.longitudeEdit.text(): self.o.lat = self.latitudeEdit.text() self.o.lon = self.longitudeEdit.text() self.text1.setText("<b>Obliczenia dla:</b><br/> " + "Szerokość: " + self.latitudeEdit.text() + "°" + " " + "Długość: " + self.longitudeEdit.text() + "°") font03 = QFont("Arial", 16) #font03.setBold(True) self.text1.setFont(font03) else: self.text1.setText("Wrocław") font03 = QFont("Arial", 16) font03.setBold(True) self.text1.setFont(font03) self.o.lon, self.o.lat = '17.03333', '51.100000' # Współrzędne Wrocławia self.timer.start(1000) self.timerIsUp = True else: self.timer.stop() self.timerIsUp = False self.button.setStatusTip("Rozpoczyna Obliczenia")
class Calculator(QMainWindow): def __init__(self): super(Calculator, self).__init__() self.setWindowTitle("Calculator") self.setWindowIcon(QIcon('arti.PNG')) self.setFont(QFont('Roboto', 12)) palette = QPalette() palette.setColor(palette.Window, QColor('#000000')) palette.setColor(palette.WindowText, QColor('#FFFFFF')) self.setPalette(palette) self.setGeometry(300, 300, 300, 300) self.generalLayout = QVBoxLayout() self._centralWidget = QWidget(self) self.setCentralWidget(self._centralWidget) self._centralWidget.setLayout(self.generalLayout) self._createDisplay() self._createButtons() def _createDisplay(self): self.display = QLineEdit() self.display.setFixedHeight(45) self.display.setAlignment(Qt.AlignRight) self.display.setReadOnly(True) self.generalLayout.addWidget(self.display) def _createButtons(self): self.buttons = {} buttons_layout = QGridLayout() buttons = { "7": (0, 0), "8": (0, 1), "9": (0, 2), "/": (0, 3), "C": (0, 4), "4": (1, 0), "5": (1, 1), "6": (1, 2), "*": (1, 3), "(": (1, 4), "1": (2, 0), "2": (2, 1), "3": (2, 2), "-": (2, 3), ")": (2, 4), "0": (3, 0), "00": (3, 1), ".": (3, 2), "+": (3, 3), "=": (3, 4), } for btnText, pos in buttons.items(): self.buttons[btnText] = QPushButton(btnText) self.buttons[btnText].setFixedSize(40, 40) buttons_layout.addWidget(self.buttons[btnText], pos[0], pos[1]) self.generalLayout.addLayout(buttons_layout) def setDisplayText(self, text): self.display.setText(text) self.display.setFocus() def displayText(self): return self.display.text() def clearDisplay(self): self.setDisplayText("")
class Window(QWidget): def __init__(self, parent=None): super().__init__(parent) self.setFont(QFont("Berlin Sans FB", 10)) self.setWindowTitle("File ENC") self.setFixedSize(500, 220) self.btn_src = QPushButton("browse") self.btn_dst = QPushButton("browse") self.btn_enc = QPushButton("Encrypt") self.btn_dec = QPushButton("Decrypt") self.btn_src.setFixedSize(60, WIDGET_HEIGHT) self.btn_dst.setFixedSize(60, WIDGET_HEIGHT) self.btn_src.clicked.connect(self.open_file_dialog) self.btn_dst.clicked.connect(self.open_dir_dialog) self.btn_enc.clicked.connect(self.encrypt_file) self.btn_dec.clicked.connect(self.decrypt_file) self.LE_file_path = QLineEdit() self.LE_file_path.setPlaceholderText("Source File Path...") self.LE_file_path.setFixedHeight(WIDGET_HEIGHT) self.LE_file_path.setReadOnly(True) self.LE_dir_path = QLineEdit() self.LE_dir_path.setPlaceholderText("Destination Path...") self.LE_dir_path.setFixedHeight(WIDGET_HEIGHT) self.LE_dir_path.setReadOnly(True) self.LE_key = QLineEdit() self.LE_key.setPlaceholderText("Enter the Cipher Key...") self.LE_key.setFixedHeight(WIDGET_HEIGHT) layout = QGridLayout() layout.setRowMinimumHeight(0, 30) layout.addWidget(self.btn_src, 0, 1) layout.addWidget(self.btn_dst, 1, 1) layout.addWidget(self.btn_enc, 3, 0, 1, 2, alignment=Qt.AlignHCenter) layout.addWidget(self.btn_dec, 4, 0, 1, 2, alignment=Qt.AlignHCenter) layout.addWidget(self.LE_file_path, 0, 0) layout.addWidget(self.LE_dir_path, 1, 0) layout.addWidget(self.LE_key, 2, 0, 1, 2) layout.setHorizontalSpacing(10) layout.setHorizontalSpacing(0) print(layout.rowStretch(0)) self.setLayout(layout) self.show() def open_file_dialog(self): fname = QFileDialog.getOpenFileName(self, "Select File") self.LE_file_path.setText(fname[0]) def open_dir_dialog(self): file = QFileDialog.getExistingDirectory(self, "Select Directory") self.LE_dir_path.setText(file) def encrypt_file(self): cipher = Fernet(self.LE_key.text()) with open(self.LE_file_path.text(), 'rb') as f: data = f.read() with open( f"{self.LE_dir_path.text()}\\enc_{os.path.basename(self.LE_file_path.text())}", 'wb') as f: f.write(cipher.encrypt(data)) def decrypt_file(self): cipher = Fernet(self.LE_key.text()) with open(self.LE_file_path.text(), 'rb') as f: data = f.read() with open( f"{self.LE_dir_path.text()}\\dec_{os.path.basename(self.LE_file_path.text())}", 'wb') as f: f.write(cipher.decrypt(data))
class WidgetConfig(QWidget): def __init__(self): super(WidgetConfig, self).__init__() HEIGHT = 30 grid1 = QGridLayout() # 使用默认摄像头复选框 self.check_camera = QCheckBox('Use default camera') self.check_camera.setChecked(gb.get_config('use_camera', True)) self.check_camera.stateChanged.connect(self.slot_check_camera) grid1.addWidget(self.check_camera, 0, 0, 1, 4) # 选择视频文件 label_video = QLabel('Source') self.line_video = QLineEdit() self.line_video.setText(gb.get_config('video', '')) self.line_video.setFixedHeight(HEIGHT) self.line_video.setEnabled(False) self.line_video.editingFinished.connect( lambda: gb.record_config({'video': self.line_video.text()})) self.btn_video = QPushButton('...') self.btn_video.setFixedWidth(40) self.btn_video.setFixedHeight(HEIGHT) self.btn_video.setEnabled(False) self.btn_video.clicked.connect(self.choose_video_file) self.slot_check_camera() grid1.addWidget(label_video, 1, 0) grid1.addWidget(self.line_video, 1, 1, 1, 2) grid1.addWidget(self.btn_video, 1, 3) # 视频录制 self.check_record = QCheckBox('Record video') self.check_record.setChecked(gb.get_config('record', True)) self.check_record.stateChanged.connect(lambda: gb.record_config( {'record': self.check_record.isChecked()})) grid1.addWidget(self.check_record, 2, 0, 1, 4) # Settings self.btn_settings = QPushButton('Settings') grid1.addWidget(self.btn_settings, 3, 0, 1, 4) box = QGroupBox() box.setLayout(grid1) vbox = QVBoxLayout() vbox.setContentsMargins(0, 0, 0, 0) vbox.addWidget(box) self.setLayout(vbox) def slot_check_camera(self): check = self.check_camera.isChecked() gb.record_config({'use_camera': check}) # 保存配置 if check: self.line_video.setEnabled(False) self.btn_video.setEnabled(False) else: self.line_video.setEnabled(True) self.btn_video.setEnabled(True) def choose_video_file(self): """从系统中选择视频文件""" file = QFileDialog.getOpenFileName(self, "Video Files", "./", "Video Files (*)") if file[0] != '': self.line_video.setText(file[0]) gb.record_config({'video': file[0]})
class PyCalcUi(QMainWindow): """PyCalc's View (GUI).""" def __init__(self): """View initializer.""" super().__init__() # Set some main window's properties self.setWindowTitle('PyCalc') self.setFixedSize(235, 235) # Set the central widget and the general layout self.generalLayout = QVBoxLayout() self._centralWidget = QWidget(self) self.setCentralWidget(self._centralWidget) self._centralWidget.setLayout(self.generalLayout) # Create the display and the buttons self._createDisplay() self._createButtons() def _createDisplay(self): """Create the display.""" # Create the display widget self.display = QLineEdit() # Set some display's properties self.display.setFixedHeight(35) self.display.setAlignment(Qt.AlignRight) self.display.setReadOnly(True) # Add the display to the general layout self.generalLayout.addWidget(self.display) def _createButtons(self): """Create the buttons.""" self.buttons = {} buttonsLayout = QGridLayout() # Button text | position on the QGridLayout buttons = { '7': (0, 0), '8': (0, 1), '9': (0, 2), '/': (0, 3), 'C': (0, 4), '4': (1, 0), '5': (1, 1), '6': (1, 2), '*': (1, 3), '(': (1, 4), '1': (2, 0), '2': (2, 1), '3': (2, 2), '-': (2, 3), ')': (2, 4), '0': (3, 0), '00': (3, 1), '.': (3, 2), '+': (3, 3), '=': (3, 4), } # Create the buttons and add them to the grid layout for btnText, pos in buttons.items(): self.buttons[btnText] = QPushButton(btnText) self.buttons[btnText].setFixedSize(40, 40) buttonsLayout.addWidget(self.buttons[btnText], pos[0], pos[1]) # Add buttonsLayout to the general layout self.generalLayout.addLayout(buttonsLayout) def setDisplayText(self, text): """Set display's text.""" self.display.setText(text) self.display.setFocus() def displayText(self): """Get display's text.""" return self.display.text() def clearDisplay(self): """Clear the display.""" self.setDisplayText('')
class TrackEditor(Observation, QWidget, metaclass=FinalMeta): def __init__(self, subject, powermode=False, allowEditBackend=False, confirmUpdate=True): Observation.__init__(self, subject) QWidget.__init__(self) self._template = None self.deleted = False self.shouldSave = False self.powermode = powermode self.allowEditBackend = allowEditBackend self.confirmUpdate = confirmUpdate self.descriptionMaxLen = 1000 self._code = "" layout = QVBoxLayout() layout.setAlignment(Qt.AlignTop) layout.setSpacing(0) layout.setContentsMargins(0, 0, 0, 0) self.setLayout(layout) if self.allowEditBackend: self._initForm() self._initCodeEditor() self.setFixedSize(630, 600) self.setAttribute(Qt.WA_StyledBackground) self.setStyleSheet(Theme.templateEditor.style) self.setContextMenuPolicy(Qt.NoContextMenu) self.setWindowModality(Qt.ApplicationModal) self.setWindowFlags(Qt.Tool | Qt.WindowTitleHint | Qt.CustomizeWindowHint | Qt.WindowCloseButtonHint | Qt.WindowMaximizeButtonHint) self.setWindowFlag(Qt.WindowMinimizeButtonHint, False) self.codeView.closeShortcut.setEnabled(False) QShortcut(QKeySequence(self.tr("Ctrl+w")), self, self.close) def _initForm(self): layout = QFormLayout() self.runCommand = QLineEdit(self, maxLength=200) self.runCommand.setStyleSheet(Theme.templateEditor.inputStyle) self.runCommand.setFont(Theme.templateEditor.inputCodeFont) self.runCommand.setFixedHeight(Theme.templateEditor.inputHeight) if self.powermode: self.backendName = QLineEdit(self, maxLength=20) self.backendName.setStyleSheet(Theme.templateEditor.inputStyle) self.backendName.setFont(Theme.templateEditor.inputFont) self.backendName.setFixedHeight(Theme.templateEditor.inputHeight) self.editorMode = QComboBox() [self.editorMode.addItem(mode) for mode in self._availableModes()] self.editorMode.currentIndexChanged.connect( self.onEditorModeChanged) self.inputRegex = QLineEdit(self, maxLength=100) self.inputRegex.setToolTip("regex") self.inputRegex.setStyleSheet(Theme.templateEditor.inputStyle) self.inputRegex.setFont(Theme.templateEditor.inputCodeFont) self.inputRegex.setFixedHeight(Theme.templateEditor.inputHeight) self.inputReplace = QLineEdit(self, maxLength=100) self.inputReplace.setToolTip("substitution string") self.inputReplace.setStyleSheet(Theme.templateEditor.inputStyle) self.inputReplace.setFont(Theme.templateEditor.inputCodeFont) self.inputReplace.setFixedHeight(Theme.templateEditor.inputHeight) self.outputRegex = QLineEdit(self, maxLength=100) self.outputRegex.setToolTip("regex") self.outputRegex.setStyleSheet(Theme.templateEditor.inputStyle) self.outputRegex.setFont(Theme.templateEditor.inputCodeFont) self.outputRegex.setFixedHeight(Theme.templateEditor.inputHeight) self.outputReplace = QLineEdit(self, maxLength=100) self.outputReplace.setToolTip("substitution string") self.outputReplace.setStyleSheet(Theme.templateEditor.inputStyle) self.outputReplace.setFont(Theme.templateEditor.inputCodeFont) self.outputReplace.setFixedHeight(Theme.templateEditor.inputHeight) self.description = QPlainTextEdit(self, minimumHeight=80) self.description.setStyleSheet( Theme.templateEditor.descriptionStyle) self.description.setFont(Theme.templateEditor.descriptionFont) layout.addRow(self.tr("Run Command:"), self.runCommand) if self.powermode: layout.addRow(self.tr("Backend Name:"), self.backendName) layout.addRow(self.tr("Editor Mode:"), self.editorMode) inputMiddlewareLayout = QHBoxLayout() inputMiddlewareLayout.addWidget(self.inputRegex) inputMiddlewareLayout.addWidget(self.inputReplace) layout.addRow(self.tr("Input Middleware:"), inputMiddlewareLayout) outputMiddlewareLayout = QHBoxLayout() outputMiddlewareLayout.addWidget(self.outputRegex) outputMiddlewareLayout.addWidget(self.outputReplace) layout.addRow(self.tr("Output Middleware:"), outputMiddlewareLayout) layout.addRow(self.tr("Description:"), self.description) layout.setSpacing(10) layout.setContentsMargins(10, 10, 10, 10) self.layout().addLayout(layout) def _initCodeEditor(self): self.codeView = CodeView(self.subject, viewTip=False) self.layout().addWidget(QLabel("Setup Code:", margin=10)) self.layout().addWidget(self.codeView) self.codeView.setDelegate(self) def _availableModes(self): return acePropertyNames("mode-", ".js", False) def onEditorModeChanged(self, e): mode = self.editorMode.itemText(e) self.codeView.setMode(mode) if self._template is not None: self._template.editor_mode = mode def onSave(self): self.shouldSave = True if self.allowEditBackend: self._template.run_command = self.runCommand.text().strip() if self.powermode and self.allowEditBackend: self._template.backend_name = self.backendName.text().strip() self._template.editor_mode = self.editorMode.currentText() self._template.backend_middleware.input.regex = \ self.inputRegex.text() self._template.backend_middleware.input.substitution = \ self.inputReplace.text() self._template.backend_middleware.output.regex = \ self.outputRegex.text() self._template.backend_middleware.output.substitution = \ self.outputReplace.text() self._template.description = self.description.toPlainText( )[:self.descriptionMaxLen] self._template.setup_code = self._code def setTemplate(self, delegate): self._template = delegate self.codeView.setDelegate(self) self.deserialize() def setCode(self, code, notify): if self._template is None: return self._code = code if self.shouldSave: self._template.setup_code = code self.onTemplateUpdate() def onTemplateUpdate(self): pass def code(self): if self._template is None: return "" return self._template.setup_code def codeWindowTitle(self): return "Track Template Editor" def deserialize(self): if self._template is None: return if self.allowEditBackend: self.runCommand.setText(self._template.run_command.strip()) if self.powermode and self.allowEditBackend: self.backendName.setText(self._template.backend_name.strip()) self.editorMode.setCurrentText(self._template.editor_mode) self.inputRegex.setText( self._template.backend_middleware.input.regex) self.inputReplace.setText( self._template.backend_middleware.input.substitution) self.outputRegex.setText( self._template.backend_middleware.output.regex) self.outputReplace.setText( self._template.backend_middleware.output.substitution) self.description.document().setPlainText( self._template.description) else: self.codeView.setMode(self._template.editor_mode) self._code = self._template.setup_code self.setWindowTitle("Track Template Editor") def delete(self): self.deleted = True self.codeView.delete() self.unregister() self.setParent(None) self.deleteLater() def template(self): return self._template def showEvent(self, event): self.shouldSave = False self.codeView.show() super().showEvent(event) def closeEvent(self, event): if self._template is not None and not self.deleted: if self.confirmUpdate: question = "Do you want to save changes in " +\ f"{self._template.backend_name} template?" confirmation = ConfirmationDialog("Update Track Template", question) if confirmation.exec_() == ConfirmationDialog.Yes: self.onSave() else: self.onSave() self.codeView.close() super().closeEvent(event)
class SettingsDialog(QDialog): def __init__(self): super(SettingsDialog, self).__init__() self.setWindowTitle('Settings') self.setWindowIcon(QIcon('img/yologo.png')) self.setWindowFlags(Qt.WindowCloseButtonHint) self.setMinimumWidth(600) HEIGHT = 30 grid = QGridLayout() # 选择权重文件 label_weights = QLabel('Weights') self.line_weights = QLineEdit() self.line_weights.setFixedHeight(HEIGHT) self.btn_weights = QPushButton('...') self.btn_weights.setFixedWidth(40) self.btn_weights.setFixedHeight(HEIGHT) self.btn_weights.clicked.connect(self.choose_weights_file) grid.addWidget(label_weights, 2, 0) grid.addWidget(self.line_weights, 2, 1, 1, 2) grid.addWidget(self.btn_weights, 2, 3) # 是否使用GPU label_device = QLabel('CUDA device') self.line_device = QLineEdit('cpu') self.line_device.setToolTip('cuda device, i.e. 0 or 0,1,2,3 or cpu') self.line_device.setPlaceholderText('cpu or 0 or 0,1,2,3') self.line_device.setFixedHeight(HEIGHT) grid.addWidget(label_device, 3, 0) grid.addWidget(self.line_device, 3, 1, 1, 3) # 设置图像大小 label_size = QLabel('Img Size') self.combo_size = QComboBox() self.combo_size.setToolTip('inference size (pixels)') self.combo_size.setFixedHeight(HEIGHT) self.combo_size.setStyleSheet( 'QAbstractItemView::item {height: 40px;}') self.combo_size.setView(QListView()) self.combo_size.addItem('320', 320) self.combo_size.addItem('384', 384) self.combo_size.addItem('448', 448) self.combo_size.addItem('512', 512) self.combo_size.addItem('576', 576) self.combo_size.addItem('640', 640) grid.addWidget(label_size, 4, 0) grid.addWidget(self.combo_size, 4, 1, 1, 3) # 设置置信度阈值 label_conf = QLabel('Confidence') self.spin_conf = QDoubleSpinBox() self.spin_conf.setToolTip('confidence threshold') self.spin_conf.setFixedHeight(HEIGHT) self.spin_conf.setDecimals(1) self.spin_conf.setRange(0.1, 0.9) self.spin_conf.setSingleStep(0.1) grid.addWidget(label_conf, 5, 0) grid.addWidget(self.spin_conf, 5, 1, 1, 3) # 设置IOU阈值 label_iou = QLabel('IOU') self.spin_iou = QDoubleSpinBox() self.spin_iou.setToolTip('NMS IoU threshold') self.spin_iou.setFixedHeight(HEIGHT) self.spin_iou.setDecimals(1) self.spin_iou.setRange(0.1, 0.9) self.spin_iou.setSingleStep(0.1) grid.addWidget(label_iou, 6, 0) grid.addWidget(self.spin_iou, 6, 1, 1, 3) # maximum detections per image label_max_det = QLabel('maximum detections') self.spin_max_det = QDoubleSpinBox() self.spin_max_det.setToolTip('Maximum detections per image') self.spin_max_det.setFixedHeight(HEIGHT) self.spin_max_det.setDecimals(0) self.spin_max_det.setRange(10, 1000) self.spin_max_det.setSingleStep(10) grid.addWidget(label_max_det, 7, 0) grid.addWidget(self.spin_max_det, 7, 1, 1, 3) # class-agnostic NMS self.check_agnostic = QCheckBox('Agnostic') self.check_agnostic.setToolTip('class-agnostic NMS') # augmented inference self.check_augment = QCheckBox('Augment') self.check_augment.setToolTip('augmented inference') # half self.check_half = QCheckBox('Half') self.check_half.setToolTip('use FP16 half-precision inference') grid.addWidget(self.check_agnostic, 8, 0) grid.addWidget(self.check_augment, 8, 1) grid.addWidget(self.check_half, 8, 2) # use OpenCV DNN for ONNX inference self.check_dnn = QCheckBox('DNN') self.check_dnn.setToolTip('Use OpenCV DNN for ONNX inference') grid.addWidget(self.check_dnn, 9, 0) box = QGroupBox() box.setLayout(grid) hbox = QHBoxLayout() self.btn_cancel = QPushButton('Cancel') self.btn_cancel.clicked.connect(self.restore) self.btn_ok = QPushButton('Ok') self.btn_ok.clicked.connect(self.save_settings) hbox.addStretch() hbox.addWidget(self.btn_cancel) hbox.addWidget(self.btn_ok) vbox = QVBoxLayout() vbox.addWidget(box) vbox.addLayout(hbox) self.setLayout(vbox) self.load_settings() def choose_weights_file(self): """从系统中选择权重文件""" weights_path = '.' weights = gb.get_config('weights', '') if os.path.exists(weights): weights_path = os.path.dirname(weights) file = QFileDialog.getOpenFileName( self, "Pre-trained YOLOv5 Weights", weights_path, "Weights Files (*.pt);;All Files (*)") if file[0] != '': self.line_weights.setText(file[0]) def load_settings(self): self.line_weights.setText(gb.get_config('weights', '')) self.line_device.setText(gb.get_config('device', 'cpu')) self.combo_size.setCurrentText(gb.get_config('img_size', '640')) self.spin_conf.setValue(gb.get_config('conf_thresh', 0.5)) self.spin_iou.setValue(gb.get_config('iou_thresh', 0.5)) self.spin_max_det.setValue(gb.get_config('max_det', 50)) self.check_agnostic.setChecked(gb.get_config('agnostic', True)) self.check_augment.setChecked(gb.get_config('augment', True)) self.check_half.setChecked(gb.get_config('half', True)) self.check_dnn.setChecked(gb.get_config('dnn', False)) def save_settings(self): """更新配置""" config = { 'weights': self.line_weights.text(), 'device': self.line_device.text(), 'img_size': self.combo_size.currentText(), 'conf_thresh': round(self.spin_conf.value(), 1), 'iou_thresh': round(self.spin_iou.value(), 1), 'max_det': int(self.spin_max_det.value()), 'agnostic': self.check_agnostic.isChecked(), 'augment': self.check_augment.isChecked(), 'half': self.check_half.isChecked(), 'dnn': self.check_dnn.isChecked() } gb.record_config(config) self.accept() def restore(self): """恢复原配置""" self.load_settings() self.reject() def closeEvent(self, event): self.restore()
class SignUpForm(QDialog): def __init__(self, parent=None): super(SignUpForm, self).__init__(parent) self.checkedPass = 0 self.setWindowTitle("Backend Discord-GUI") self.changeStyle('fusion') palette = QPalette() palette.setColor(QPalette.Window, QColor(53, 53, 53)) palette.setColor(QPalette.WindowText, Qt.white) palette.setColor(QPalette.Text, Qt.white) palette.setColor(QPalette.Button, QColor(60, 60, 60)) palette.setColor(QPalette.ButtonText, Qt.white) palette.setColor(QPalette.Base, QColor(40, 40, 40)) palette.setColor(QPalette.ToolTipBase, QColor(60, 60, 60)) palette.setColor(QPalette.ToolTipText, Qt.white) palette.setColor(QPalette.PlaceholderText, QColor(100, 60, 60)) palette.setColor(QPalette.BrightText, Qt.white) palette.setColor(QPalette.Highlight, QColor(106, 13, 173)) palette.setColor(QPalette.HighlightedText, Qt.white) mainLayout = QVBoxLayout() hMainLayout = QHBoxLayout() passwordLayout = QHBoxLayout() entryBG = QPalette() gradient = QGradient() gradient.setColorAt(0.0, QColor(30, 30, 30)) gradient.setColorAt(0.4, QColor(30, 30, 30)) gradient.setColorAt(1.0, QColor(70, 70, 70)) gradient.setSpread(QGradient.RepeatSpread) entryBG.setBrush(QPalette.Button, QBrush(gradient)) self.name = QLineEdit(self) self.name.setFixedHeight(24) self.name.setToolTip("Max 64 Characters") self.name.setStyleSheet( "QToolTip { border: 0px; border-radius: 3px; }") self.name.setPalette(entryBG) self.QNameLabel = QLabel("Full Name") self.QNameLabel.setFont(QFont("Copperplate", 12)) self.name.setMaxLength(64) self.email = QLineEdit(self) self.email.setFixedHeight(24) self.email.setToolTip( "Max 128 Characters, Example - [email protected]") self.email.setStyleSheet( "QToolTip { border: 0px; border-radius: 3px }") self.email.setPalette(entryBG) self.QEmailLabel = QLabel("Email") self.QEmailLabel.setFont(QFont("Copperplate", 12)) self.email.setMaxLength(128) self.username = QLineEdit(self) self.username.setFixedHeight(24) self.username.setToolTip("Max 16 Characters") self.username.setStyleSheet( "QToolTip { border: 0px; border-radius: 3px }") self.username.setPalette(entryBG) self.QUserLabel = QLabel("Username") self.QUserLabel.setFont(QFont("Copperplate", 12)) self.username.setMaxLength(16) self.password = QLineEdit(self) self.password.setFixedHeight(24) self.password.setToolTip( "Max 32 Characters, Must Include = Uppercase Letter,\nNumber and Special Character" ) self.password.setStyleSheet( "QToolTip { border: 0px; border-radius: 3px }") self.password.setPalette(entryBG) self.QPasswordLabel = QLabel("Password ") self.password.setMaxLength(32) self.QPasswordLabel.setFont(QFont("Copperplate", 12)) self.showhideButton = QPushButton("Show") self.showhideButton.setCheckable(True) self.showhideButton.setChecked(False) self.showhideButton.clicked.connect(lambda: self.show_hide()) self.password.setEchoMode(QLineEdit.Password) passwordLayout.addWidget(self.QPasswordLabel) passwordLayout.addWidget(self.password) passwordLayout.addWidget(self.showhideButton) self.btn_SignUp = QPushButton("Sign Up") self.btn_SignUp.clicked.connect(lambda: self.signUpWindow()) shortcut = QShortcut(QKeySequence("Return"), self.btn_SignUp) shortcut.activated.connect(lambda: self.signUpWindow()) shortcut.setEnabled(True) self.btn_cancel = QPushButton("Cancel") self.btn_cancel.clicked.connect(lambda: self.cancel()) layout = QFormLayout() layout.addRow(self.QNameLabel, self.name) layout.addRow(self.QEmailLabel, self.email) layout.addRow(self.QUserLabel, self.username) layout.addRow(passwordLayout) layout.addRow(self.btn_SignUp) layout.addRow(self.btn_cancel) Label = QLabel("Sign Up To The\nBackend Discord-GUI Development") Label.setFont(QFont("Copperplate", 15, QFont.Bold)) Label.setAlignment(Qt.AlignCenter) mainLayout.addSpacing(40) mainLayout.addWidget(Label) mainLayout.addLayout(layout) mainLayout.addSpacing(60) hMainLayout.addSpacing(115) hMainLayout.addLayout(mainLayout) hMainLayout.addSpacing(115) self.setLayout(hMainLayout) QApplication.setPalette(palette) def keyPressEvent(self, e): if e.key() == Qt.Key_Escape: pass def check_passwordCheck(self): if self.checkedPass <= 0: msg = QMessageBox() msg.setIcon(QMessageBox.Information) msg.setText("Check Password?") msg.setInformativeText( "Are you sure you want to Sign Up, you haven't checked your password. Do you want to proceed?" ) msg.setWindowTitle("Check Password?") msg.setDetailedText( "We monitor basic actions you make, this is part of our policy. This MessageBox " + "was generated because we detected you did not check your password before clicking " + "the sign up button. We recommend this just incase you forget your password.\n\n" + "We believe in the best for our customers, so we try to minimise simple errors, " + "like this, to serve customers quicker when there is a higher priority support request." ) msg.setStandardButtons(QMessageBox.No | QMessageBox.Yes) msg.buttonClicked.connect(self.signUp) retval = msg.exec_() else: self.signUp(proceed=True) def signUpWindow(self): namePassed, emailPassed, usernamePassed, passwordPassed = False, False, False, False errors = [] if len(self.name.text()) <= 1: self.name.setStyleSheet( "QLineEdit { border: 1px solid red; border-radius: 3px; } QToolTip { border: 0px }" ) errors.append("Name: Too Short") else: self.name.setStyleSheet( "QLineEdit { border: 0px; border-radius: 3px; } QToolTip { border: 0px }" ) namePassed = True if re.match(r"(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$)", self.email.text()): self.email.setStyleSheet( "QLineEdit { border: 0px; border-radius: 3px; } QToolTip { border: 0px }" ) emailPassed = True else: self.email.setStyleSheet( "QLineEdit { border: 1px solid red; border-radius: 3px; } QToolTip { border: 0px }" ) errors.append("Email: This is not a valid Email") if len(self.username.text()) <= 2: self.username.setStyleSheet( "QLineEdit { border: 1px solid red; border-radius: 3px; } QToolTip { border: 0px }" ) errors.append("Username: Too Short") else: if re.match(r"([a-zA-Z0-9_]+$)", self.username.text()): self.username.setStyleSheet( "QLineEdit { border: 0px; border-radius: 3px; } QToolTip { border: 0px }" ) usernamePassed = True else: self.username.setStyleSheet( "QLineEdit { border: 1px solid red; border-radius: 3px; } QToolTip { border: 0px }" ) errors.append( "Username: Can only have, a-z (A-Z), 0-9 and '_'") if len(self.password.text()) <= 7: self.password.setStyleSheet( "QLineEdit { border: 1px solid red; border-radius: 3px; } QToolTip { border: 0px }" ) errors.append("Password: Too Short") else: if re.match( r'^.*(?=.{8,10})(?=.*[a-zA-Z])(?=.*?[A-Z])(?=.*\d)[a-zA-Z0-9!@£$%^&*()_+={}?:~\[\]]+$', self.password.text()): self.password.setStyleSheet( "QLineEdit { border: 0px; border-radius: 3px; } QToolTip { border: 0px }" ) passwordPassed = True else: self.password.setStyleSheet( "QLineEdit { border: 1px solid red; border-radius: 3px; } QToolTip { border: 0px }" ) errors.append( "Password: Needs to have, Capital Letter, Number, Special Character" ) if namePassed and emailPassed and usernamePassed and passwordPassed: self.check_passwordCheck() else: if len(errors) > 2: string = "; ".join(errors[:2]) overall_string = str("Errors: " + string + " +{} more".format(len(errors) - 2)) else: string = "; ".join(errors) overall_string = str("Errors: " + string) window.setStatusBar(overall_string, True) def signUp(self, i=None, proceed=False): if i != None: if i.text() == "&Yes": signUp = True QApplication.quit() else: pass signUp = proceed if signUp == True: print("Signed Up") QApplication.quit() def show_hide(self): if self.showhideButton.isChecked(): self.checkedPass += 1 self.password.setEchoMode(QLineEdit.Normal) self.showhideButton.setText("Hide") else: self.password.setEchoMode(QLineEdit.Password) self.showhideButton.setText("Show") def changeStyle(self, styleName): QApplication.setStyle(QStyleFactory.create(styleName)) def cancel(self): window.openLogIn()
class WidgetConfig(QGroupBox): def __init__(self): super(WidgetConfig, self).__init__() HEIGHT = 40 grid = QGridLayout() # 使用默认摄像头复选框 self.check_camera = QCheckBox('Use default camera') self.check_camera.setChecked(False) self.check_camera.stateChanged.connect(self.slot_check_camera) grid.addWidget(self.check_camera, 0, 0, 1, 3) # 一行三列 # 选择视频文件 label_video = QLabel('Detect File') self.line_video = QLineEdit() if 'video' in GLOBAL.config: self.line_video.setText(GLOBAL.config['video']) self.line_video.setFixedHeight(HEIGHT) self.line_video.setEnabled(False) self.line_video.editingFinished.connect( lambda: GLOBAL.record_config({'video': self.line_video.text()})) self.btn_video = QPushButton('Choose') self.btn_video.setFixedHeight(HEIGHT) self.btn_video.setEnabled(False) self.btn_video.clicked.connect(self.choose_video_file) self.slot_check_camera() grid.addWidget(label_video, 1, 0) grid.addWidget(self.line_video, 1, 1) grid.addWidget(self.btn_video, 1, 2) # 选择权重文件 label_weights = QLabel('Weights File') self.line_weights = QLineEdit() if 'weights' in GLOBAL.config: self.line_weights.setText(GLOBAL.config['weights']) self.line_weights.setFixedHeight(HEIGHT) self.line_weights.editingFinished.connect(lambda: GLOBAL.record_config( {'weights': self.line_weights.text()})) self.btn_weights = QPushButton('Choose') self.btn_weights.setFixedHeight(HEIGHT) self.btn_weights.clicked.connect(self.choose_weights_file) grid.addWidget(label_weights, 2, 0) grid.addWidget(self.line_weights, 2, 1) grid.addWidget(self.btn_weights, 2, 2) # 是否使用GPU label_device = QLabel('CUDA device') self.line_device = QLineEdit('gpu') if 'device' in GLOBAL.config: self.line_device.setText(GLOBAL.config['device']) else: self.line_device.setText('cpu') self.line_device.setPlaceholderText('cpu or 0 or 0,1,2,3') self.line_device.setFixedHeight(HEIGHT) self.line_device.editingFinished.connect( lambda: GLOBAL.record_config({'device': self.line_device.text()})) grid.addWidget(label_device, 3, 0) grid.addWidget(self.line_device, 3, 1, 1, 2) # 设置图像大小 label_size = QLabel('Img Size') self.combo_size = QComboBox() self.combo_size.setFixedHeight(HEIGHT) self.combo_size.setStyleSheet( 'QAbstractItemView::item {height: 40px;}') self.combo_size.setView(QListView()) self.combo_size.addItem('320', 320) self.combo_size.addItem('416', 416) self.combo_size.addItem('480', 480) self.combo_size.addItem('544', 544) self.combo_size.addItem('640', 640) self.combo_size.setCurrentIndex(2) self.combo_size.currentIndexChanged.connect( lambda: GLOBAL.record_config( {'img_size': self.combo_size.currentData()})) grid.addWidget(label_size, 4, 0) grid.addWidget(self.combo_size, 4, 1, 1, 2) #choose net camera label_stream = QLabel('NetVedioStream') self.combo_stream = QComboBox() self.combo_stream.setFixedHeight(HEIGHT) self.combo_stream.setStyleSheet( 'QAbstractItemView::item {height: 40px;}') self.combo_stream.setView(QListView()) self.combo_stream.addItem('rtsp://*****:*****@192.168.0.65/', 'rtsp://*****:*****@192.168.0.65/') self.combo_stream.addItem('rtsp://*****:*****@192.168.0.66/', 'rtsp://*****:*****@192.168.0.66/') self.combo_stream.addItem('rtsp://*****:*****@192.168.0.67/', 'rtsp://*****:*****@192.168.0.67/') self.combo_stream.addItem('rtsp://*****:*****@192.168.0.68/', 'rtsp://*****:*****@192.168.0.68/') self.combo_stream.addItem('rtsp://*****:*****@192.168.0.65/', 'rtsp://*****:*****@192.168.0.65/') self.combo_stream.setCurrentIndex(0) self.combo_stream.currentIndexChanged.connect( lambda: GLOBAL.record_config( {'netstreamvedio': self.combo_stream.currentData()})) grid.addWidget(label_stream, 5, 0) grid.addWidget(self.combo_stream, 5, 1, 1, 2) # 设置置信度阈值 label_conf = QLabel('Confidence') self.spin_conf = QDoubleSpinBox() self.spin_conf.setFixedHeight(HEIGHT) self.spin_conf.setDecimals(1) self.spin_conf.setRange(0.1, 0.9) self.spin_conf.setSingleStep(0.1) if 'conf_thresh' in GLOBAL.config: self.spin_conf.setValue(GLOBAL.config['conf_thresh']) else: self.spin_conf.setValue(0.4) # 默认值 GLOBAL.record_config({'conf_thresh': 0.4}) self.spin_conf.valueChanged.connect(lambda: GLOBAL.record_config( {'conf_thresh': round(self.spin_conf.value(), 1)})) grid.addWidget(label_conf, 6, 0) grid.addWidget(self.spin_conf, 6, 1, 1, 2) # 设置IOU阈值 label_iou = QLabel('IOU') self.spin_iou = QDoubleSpinBox() self.spin_iou.setFixedHeight(HEIGHT) self.spin_iou.setDecimals(1) self.spin_iou.setRange(0.1, 0.9) self.spin_iou.setSingleStep(0.1) if 'iou_thresh' in GLOBAL.config: self.spin_iou.setValue(GLOBAL.config['iou_thresh']) else: self.spin_iou.setValue(0.5) # 默认值 GLOBAL.record_config({'iou_thresh': 0.5}) self.spin_iou.valueChanged.connect(lambda: GLOBAL.record_config( {'iou_thresh': round(self.spin_iou.value(), 1)})) grid.addWidget(label_iou, 7, 0) grid.addWidget(self.spin_iou, 7, 1, 1, 2) # class-agnostic NMS self.check_agnostic = QCheckBox('Agnostic') if 'agnostic' in GLOBAL.config: self.check_agnostic.setChecked(GLOBAL.config['agnostic']) else: self.check_agnostic.setChecked(True) self.check_agnostic.stateChanged.connect(lambda: GLOBAL.record_config( {'agnostic': self.check_agnostic.isChecked()})) grid.addWidget(self.check_agnostic, 8, 0, 1, 3) # 一行三列 # augmented inference self.check_augment = QCheckBox('Augment') if 'augment' in GLOBAL.config: self.check_augment.setChecked(GLOBAL.config['augment']) else: self.check_augment.setChecked(True) self.check_augment.stateChanged.connect(lambda: GLOBAL.record_config( {'augment': self.check_augment.isChecked()})) grid.addWidget(self.check_augment, 9, 0, 1, 3) # 一行三列 self.setLayout(grid) # 设置布局 def slot_check_camera(self): check = self.check_camera.isChecked() GLOBAL.record_config({'use_camera': check}) # 保存配置 if check: self.line_video.setEnabled(False) self.btn_video.setEnabled(False) else: self.line_video.setEnabled(True) self.btn_video.setEnabled(True) def choose_weights_file(self): """从系统中选择权重文件""" file = QFileDialog.getOpenFileName( self, "Pre-trained YOLOv5 Weights", "./", "Weights Files (*.pt);;All Files (*)") if file[0] != '': self.line_weights.setText(file[0]) GLOBAL.record_config({'weights': file[0]}) def choose_video_file(self): """从系统中选择视频文件""" file = QFileDialog.getOpenFileName(self, "Video Files", "./", "Video Files (*)") if file[0] != '': self.line_video.setText(file[0]) GLOBAL.record_config({'video': file[0]}) def save_config(self): """保存当前的配置到配置文件""" config = { 'use_camera': self.check_camera.isChecked(), 'video': self.line_video.text(), 'weights': self.line_weights.text(), 'device': self.line_device.text(), 'img_size': self.combo_size.currentData(), 'conf_thresh': round(self.spin_conf.value(), 1), 'iou_thresh': round(self.spin_iou.value(), 1), 'agnostic': self.check_agnostic.isChecked(), 'augment': self.check_augment.isChecked(), 'netstreamvedio': self.combo_stream.currentData() } GLOBAL.record_config(config)
class MainWindow(QMainWindow): def __init__(self, application, *args, **kwargs): super(MainWindow, self).__init__(*args, **kwargs) self.printer_thread = WorkerThread() self.printer_thread.message.connect(self.standardOutputWritten) self.printer_thread.start() self.app = application self.app.setStyle("Fusion") self.__set_interface() self.__set_layouts() self.__set_stylesheet() self.__set_connections() self.__set_params() def closeEvent(self, event): self.printer_thread.stop() def __set_interface(self): self.button_width = 0.35 self.button_height = 0.05 self.setWindowTitle("GSI-RADS") self.__getScreenDimensions() self.setGeometry(self.left, self.top, self.width, self.height) self.setMaximumWidth(self.width) #self.setMaximumHeight(self.height) self.setMinimumWidth(self.width) self.setMinimumHeight(self.height) self.move(self.width / 2, self.height / 2) self.menu_bar = QMenuBar(self) self.menu_bar.setNativeMenuBar( False ) # https://stackoverflow.com/questions/25261760/menubar-not-showing-for-simple-qmainwindow-code-qt-creator-mac-os self.file_menu = self.menu_bar.addMenu('File') self.import_dicom_action = QAction( QIcon( os.path.join(os.path.dirname(os.path.realpath(__file__)), 'images/database-icon.png')), 'Import DICOM', self) self.import_dicom_action.setShortcut('Ctrl+D') self.file_menu.addAction(self.import_dicom_action) self.quit_action = QAction('Quit', self) self.quit_action.setShortcut("Ctrl+Q") self.file_menu.addAction(self.quit_action) self.settings_menu = self.menu_bar.addMenu('Settings') self.settings_seg_menu = self.settings_menu.addMenu("Segmentation...") self.settings_seg_preproc_menu = self.settings_seg_menu.addMenu( "Preprocessing...") self.settings_seg_preproc_menu_p1_action = QAction( "Brain-masking off (P1)", checkable=True) self.settings_seg_preproc_menu_p2_action = QAction( "Brain-masking on (P2)", checkable=True) self.settings_seg_preproc_menu_p2_action.setChecked(True) self.settings_seg_preproc_menu.addAction( self.settings_seg_preproc_menu_p1_action) self.settings_seg_preproc_menu.addAction( self.settings_seg_preproc_menu_p2_action) self.help_menu = self.menu_bar.addMenu('Help') self.readme_action = QAction( QIcon( os.path.join(os.path.dirname(os.path.realpath(__file__)), 'images/readme-icon.jpeg')), 'Tutorial', self) self.readme_action.setShortcut("Ctrl+R") self.help_menu.addAction(self.readme_action) self.about_action = QAction( QIcon( os.path.join(os.path.dirname(os.path.realpath(__file__)), 'images/about-icon.png')), 'About', self) self.about_action.setShortcut("Ctrl+A") self.help_menu.addAction(self.about_action) self.help_action = QAction( QIcon.fromTheme("help-faq"), "Help", self ) # Default icons can be found here: https://specifications.freedesktop.org/icon-naming-spec/icon-naming-spec-latest.html#guidelines self.help_action.setShortcut("Ctrl+J") self.help_menu.addAction(self.help_action) self.input_image_lineedit = QLineEdit() self.input_image_lineedit.setFixedWidth(self.width * (0.93 - self.button_width / 2)) self.input_image_lineedit.setFixedHeight(self.height * self.button_height) self.input_image_lineedit.setReadOnly(True) self.input_image_pushbutton = QPushButton('Input MRI') self.input_image_pushbutton.setFixedWidth(self.height * self.button_width) self.input_image_pushbutton.setFixedHeight(self.height * self.button_height) self.input_segmentation_lineedit = QLineEdit() self.input_segmentation_lineedit.setReadOnly(True) self.input_segmentation_lineedit.setFixedWidth( self.width * (0.93 - self.button_width / 2)) self.input_segmentation_lineedit.setFixedHeight(self.height * self.button_height) self.input_segmentation_pushbutton = QPushButton('Input segmentation') self.input_segmentation_pushbutton.setFixedWidth(self.height * self.button_width) self.input_segmentation_pushbutton.setFixedHeight(self.height * self.button_height) self.output_folder_lineedit = QLineEdit() self.output_folder_lineedit.setReadOnly(True) self.output_folder_lineedit.setFixedWidth( self.width * (0.93 - self.button_width / 2)) self.output_folder_lineedit.setFixedHeight(self.height * self.button_height) self.output_folder_pushbutton = QPushButton('Output destination') self.output_folder_pushbutton.setFixedWidth(self.height * self.button_width) self.output_folder_pushbutton.setFixedHeight(self.height * self.button_height) self.run_button = QPushButton('Run diagnosis') self.run_button.setFixedWidth(self.height * self.button_width) self.run_button.setFixedHeight(self.height * self.button_height) self.main_display_tabwidget = QTabWidget() self.tutorial_textedit = QPlainTextEdit() self.tutorial_textedit.setReadOnly(True) self.tutorial_textedit.setFixedWidth(self.width * 0.97) self.tutorial_textedit.setPlainText( "HOW TO USE THE SOFTWARE: \n" " 1) Click 'Input MRI...' to select from your file explorer the MRI scan to process (unique file).\n" " 1*) Alternatively, Click File > Import DICOM... if you wish to process an MRI scan as a DICOM sequence.\n" " 2) Click 'Output destination' to choose a directory where to save the results \n" " 3) (OPTIONAL) Click 'Input segmentation' to choose a tumor segmentation mask file, if nothing is provided the internal model with generate the segmentation automatically \n" " 4) Click 'Run diagnosis' to perform the analysis. The human-readable version will be displayed in the interface.\n" " \n" "NOTE: \n" "The output folder is populated automatically with the following: \n" " * The diagnosis results in human-readable text (report.txt) and Excel-ready format (report.csv).\n" " * The automatic segmentation masks of the brain and the tumor in the original patient space (input_brain_mask.nii.gz and input_tumor_mask.nii.gz).\n" " * The input volume and tumor segmentation mask in MNI space in the sub-directory named \'registration\'.\n" ) self.main_display_tabwidget.addTab(self.tutorial_textedit, 'Tutorial') self.prompt_lineedit = QPlainTextEdit() self.prompt_lineedit.setReadOnly(True) self.prompt_lineedit.setFixedWidth(self.width * 0.97) self.main_display_tabwidget.addTab(self.prompt_lineedit, 'Logging') self.results_textedit = QPlainTextEdit() self.results_textedit.setReadOnly(True) self.results_textedit.setFixedWidth(self.width * 0.97) self.main_display_tabwidget.addTab(self.results_textedit, 'Results') self.sintef_logo_label = QLabel() self.sintef_logo_label.setPixmap( QPixmap( os.path.join(os.path.dirname(os.path.realpath(__file__)), 'images/sintef-logo.png'))) self.sintef_logo_label.setFixedWidth(0.95 * (self.width / 3)) self.sintef_logo_label.setFixedHeight( 1 * (self.height * self.button_height)) self.sintef_logo_label.setScaledContents(True) self.stolavs_logo_label = QLabel() self.stolavs_logo_label.setPixmap( QPixmap( os.path.join(os.path.dirname(os.path.realpath(__file__)), 'images/stolavs-logo.png'))) self.stolavs_logo_label.setFixedWidth(0.95 * (self.width / 3)) self.stolavs_logo_label.setFixedHeight( 1 * (self.height * self.button_height)) self.stolavs_logo_label.setScaledContents(True) self.amsterdam_logo_label = QLabel() self.amsterdam_logo_label.setPixmap( QPixmap( os.path.join(os.path.dirname(os.path.realpath(__file__)), 'images/amsterdam-logo.png'))) self.amsterdam_logo_label.setFixedWidth(0.95 * (self.width / 3)) self.amsterdam_logo_label.setFixedHeight( 1 * (self.height * self.button_height)) self.amsterdam_logo_label.setScaledContents(True) def __set_layouts(self): self.input_volume_hbox = QHBoxLayout() self.input_volume_hbox.addStretch(1) self.input_volume_hbox.addWidget(self.input_image_lineedit) self.input_volume_hbox.addWidget(self.input_image_pushbutton) self.input_volume_hbox.addStretch(1) self.input_seg_hbox = QHBoxLayout() self.input_seg_hbox.addStretch(1) self.input_seg_hbox.addWidget(self.input_segmentation_lineedit) self.input_seg_hbox.addWidget(self.input_segmentation_pushbutton) self.input_seg_hbox.addStretch(1) self.output_dir_hbox = QHBoxLayout() self.output_dir_hbox.addStretch(1) self.output_dir_hbox.addWidget(self.output_folder_lineedit) self.output_dir_hbox.addWidget(self.output_folder_pushbutton) self.output_dir_hbox.addStretch(1) self.run_action_hbox = QHBoxLayout() self.run_action_hbox.addStretch(1) self.run_action_hbox.addWidget(self.run_button) self.run_action_hbox.addStretch(1) self.dump_area_hbox = QHBoxLayout() self.dump_area_hbox.addStretch(1) self.dump_area_hbox.addWidget(self.main_display_tabwidget) self.dump_area_hbox.addStretch(1) self.logos_hbox = QHBoxLayout() self.logos_hbox.addStretch(1) self.logos_hbox.addWidget(self.sintef_logo_label) self.logos_hbox.addWidget(self.stolavs_logo_label) self.logos_hbox.addWidget(self.amsterdam_logo_label) self.logos_hbox.addStretch(1) self.main_vbox = QVBoxLayout() self.main_vbox.addWidget(self.menu_bar) #self.main_vbox.addStretch(1) self.main_vbox.addLayout(self.input_volume_hbox) self.main_vbox.addLayout(self.output_dir_hbox) self.main_vbox.addLayout(self.input_seg_hbox) self.main_vbox.addLayout(self.run_action_hbox) #self.main_vbox.addStretch(1) self.main_vbox.addLayout(self.dump_area_hbox) self.main_vbox.addLayout(self.logos_hbox) #self.main_vbox.addStretch(1) self.central_label = QLabel() self.central_label.setLayout(self.main_vbox) self.setCentralWidget(self.central_label) def __set_stylesheet(self): self.central_label.setStyleSheet( 'QLabel{background-color: qlineargradient(spread:pad, x1:0.5, y1:1, x2:0.5, y2:0, stop:0 rgba(207, 209, 207, 255), stop:1 rgba(230, 229, 230, 255));}' ) self.menu_bar.setStyleSheet(get_stylesheet('QMenuBar')) self.input_image_lineedit.setStyleSheet(get_stylesheet('QLineEdit')) self.input_image_pushbutton.setStyleSheet( get_stylesheet('QPushButton')) self.input_segmentation_lineedit.setStyleSheet( get_stylesheet('QLineEdit')) self.input_segmentation_pushbutton.setStyleSheet( get_stylesheet('QPushButton')) self.output_folder_lineedit.setStyleSheet(get_stylesheet('QLineEdit')) self.output_folder_pushbutton.setStyleSheet( get_stylesheet('QPushButton')) self.results_textedit.setStyleSheet(get_stylesheet('QTextEdit')) self.prompt_lineedit.setStyleSheet(get_stylesheet('QTextEdit')) self.run_button.setStyleSheet(get_stylesheet('QPushButton')) def __set_connections(self): self.run_button.clicked.connect(self.diagnose_main_wrapper) self.input_image_pushbutton.clicked.connect( self.run_select_input_image) self.input_segmentation_pushbutton.clicked.connect( self.run_select_input_segmentation) self.output_folder_pushbutton.clicked.connect( self.run_select_output_folder) self.readme_action.triggered.connect(self.readme_action_triggered) self.about_action.triggered.connect(self.about_action_triggered) self.quit_action.triggered.connect(self.quit_action_triggered) self.import_dicom_action.triggered.connect( self.import_dicom_action_triggered) self.help_action.triggered.connect(self.help_action_triggered) self.settings_seg_preproc_menu_p1_action.triggered.connect( self.settings_seg_preproc_menu_p1_action_triggered) self.settings_seg_preproc_menu_p2_action.triggered.connect( self.settings_seg_preproc_menu_p2_action_triggered) def __set_params(self): self.input_image_filepath = '' self.input_annotation_filepath = '' self.output_folderpath = '' def __getScreenDimensions(self): screen = self.app.primaryScreen() size = screen.size() self.left = size.width() / 2 self.top = size.height() / 2 self.width = 0.4 * size.width() self.height = 0.4 * size.height() def readme_action_triggered(self): popup = QMessageBox() popup.setWindowTitle('Tutorial') popup.setText( "HOW TO USE THE SOFTWARE: \n" " 1) Click 'Input MRI...' to select from your file explorer the MRI scan to process (unique file).\n" " 1*) Alternatively, Click File > Import DICOM... if you wish to process an MRI scan as a DICOM sequence.\n" " 2) Click 'Output destination' to choose a directory where to save the results \n" " 3) (OPTIONAL) Click 'Input segmentation' to choose a tumor segmentation mask file, if nothing is provided the internal model with generate the segmentation automatically \n" " 4) Click 'Run diagnosis' to perform the analysis. The human-readable version will be displayed in the interface.\n" " \n" "NOTE: \n" "The output folder is populated automatically with the following: \n" " * The diagnosis results in human-readable text (report.txt) and Excel-ready format (report.csv).\n" " * The automatic segmentation masks of the brain and the tumor in the original patient space (input_brain_mask.nii.gz and input_tumor_mask.nii.gz).\n" " * The input volume and tumor segmentation mask in MNI space in the sub-directory named \'registration\'.\n" ) popup.exec_() def about_action_triggered(self): popup = QMessageBox() popup.setWindowTitle('About') popup.setText( 'Software developed as part of a collaboration between: \n' ' * Departement of Health Research, SINTEF\n' ' * St. Olavs hospital, Trondheim University Hospital\n' ' * Amsterdam University Medical Center\n\n' 'Contact: David Bouget, Andre Pedersen\n\n' 'For questions about the software, please visit:\n' 'https://github.com/SINTEFMedtek/GSI-RADS\n' 'For questions about the methodological aspect, please refer to the original publication:\n' 'https://www.mdpi.com/2072-6694/13/12/2854/review_report') popup.exec_() def quit_action_triggered(self): self.printer_thread.stop() sys.exit() def diagnose_main_wrapper(self): self.run_diagnosis_thread = threading.Thread(target=self.run_diagnosis) self.run_diagnosis_thread.daemon = True # using daemon thread the thread is killed gracefully if program is abruptly closed self.run_diagnosis_thread.start() def run_diagnosis(self): if not os.path.exists(self.input_image_filepath) or not os.path.exists( self.output_folderpath): self.standardOutputWritten( 'Process could not be started - The 1st and 2nd above-fields must be filled in.\n' ) return self.run_button.setEnabled(False) self.prompt_lineedit.clear() self.main_display_tabwidget.setCurrentIndex(1) QApplication.processEvents( ) # to immidiently update GUI after button is clicked self.seg_preprocessing_scheme = 'P1' if self.settings_seg_preproc_menu_p1_action.isChecked( ) else 'P2' try: start_time = time.time() print('Initialize - Begin (Step 0/6)') from diagnosis.main import diagnose_main print('Initialize - End (Step 0/6)') print('Step runtime: {} seconds.'.format( np.round(time.time() - start_time, 3)) + "\n") diagnose_main( input_volume_filename=self.input_image_filepath, input_segmentation_filename=self.input_annotation_filepath, output_folder=self.output_folderpath, preprocessing_scheme=self.seg_preprocessing_scheme) except Exception as e: print('{}'.format(traceback.format_exc())) self.run_button.setEnabled(True) self.standardOutputWritten( 'Process could not be completed - Issue arose.\n') QApplication.processEvents() return self.run_button.setEnabled(True) results_filepath = os.path.join( ResourcesConfiguration.getInstance().output_folder, 'report.txt') self.results_textedit.setPlainText(open(results_filepath, 'r').read()) self.main_display_tabwidget.setCurrentIndex(2) def run_select_input_image(self): input_image_filedialog = QFileDialog() self.input_image_filepath = input_image_filedialog.getOpenFileName( self, 'Select input T1 MRI', '~', "Image files (*.nii *.nii.gz *.nrrd *.mha *.mhd)")[0] self.input_image_lineedit.setText(self.input_image_filepath) def run_select_input_segmentation(self): filedialog = QFileDialog() self.input_annotation_filepath = filedialog.getOpenFileName( self, 'Select input segmentation file', '~', "Image files (*.nii *.nii.gz)")[0] self.input_segmentation_lineedit.setText( self.input_annotation_filepath) def import_dicom_action_triggered(self): filedialog = QFileDialog() filedialog.setFileMode(QFileDialog.DirectoryOnly) self.input_image_filepath = filedialog.getExistingDirectory( self, 'Select DICOM folder', '~') self.input_image_lineedit.setText(self.input_image_filepath) def run_select_output_folder(self): filedialog = QFileDialog() filedialog.setFileMode(QFileDialog.DirectoryOnly) self.output_folderpath = filedialog.getExistingDirectory( self, 'Select output folder', '~') self.output_folder_lineedit.setText(self.output_folderpath) def standardOutputWritten(self, text): self.prompt_lineedit.moveCursor(QTextCursor.End) self.prompt_lineedit.insertPlainText(text) QApplication.processEvents() def help_action_triggered(self): # opens browser with specified url, directs user to Issues section of GitHub repo QDesktopServices.openUrl( QUrl("https://github.com/SINTEFMedtek/GSI-RADS/issues")) def settings_seg_preproc_menu_p1_action_triggered(self, status): if status: self.settings_seg_preproc_menu_p2_action.setChecked(False) else: self.settings_seg_preproc_menu_p2_action.setChecked(True) def settings_seg_preproc_menu_p2_action_triggered(self, status): if status: self.settings_seg_preproc_menu_p1_action.setChecked(False) else: self.settings_seg_preproc_menu_p1_action.setChecked(True)
class PyCalcUi(QMainWindow): """PyCalc's View (GUI).""" def __init__(self): """View initializer.""" super().__init__() # Set some main window's properties self.setWindowTitle("PyCalc") self.setFixedSize(235, 235) # Set the central widget and the general layout self.generalLayout = QVBoxLayout() self._centralWidget = QWidget(self) self.setCentralWidget(self._centralWidget) self._centralWidget.setLayout(self.generalLayout) # Create the display and the buttons self._createDisplay() self._createButtons() self.show() def _createDisplay(self): """Create the display.""" # Create the display widget self.display = QLineEdit() # Set some display's properties self.display.setFixedHeight(35) self.display.setAlignment(Qt.AlignRight) self.display.setReadOnly(True) # Add the display to the general layout self.generalLayout.addWidget(self.display) def _createButtons(self): """Create the buttons.""" self.buttons = {} buttonsLayout = QGridLayout() # Button text | position on the QGridLayout buttons = { "7": (0, 0), "8": (0, 1), "9": (0, 2), "/": (0, 3), "C": (0, 4), "4": (1, 0), "5": (1, 1), "6": (1, 2), "*": (1, 3), "(": (1, 4), "1": (2, 0), "2": (2, 1), "3": (2, 2), "-": (2, 3), ")": (2, 4), "0": (3, 0), "00": (3, 1), ".": (3, 2), "+": (3, 3), "=": (3, 4), } # Create the buttons and add them to the grid layout for btnText, pos in buttons.items(): self.buttons[btnText] = QPushButton(btnText) self.buttons[btnText].setFixedSize(40, 40) buttonsLayout.addWidget(self.buttons[btnText], pos[0], pos[1]) # Add buttonsLayout to the general layout self.generalLayout.addLayout(buttonsLayout) def setDisplayText(self, text): """Set display's text.""" self.display.setText(text) self.display.setFocus() def displayText(self): """Get display's text.""" return self.display.text() def clearDisplay(self): """Clear the display.""" self.setDisplayText("")