class VideoWidget(QWidget): def __init__(self): super().__init__() self.image = QGraphicsView() color = QColor("black") self.image.setBackgroundBrush(QBrush(color)) self.setLayout(QVBoxLayout()) self.layout().addWidget(self.image) self.connected = False def connect(self, port, ip="localhost"): if self.connected: return self.socket = QDataSocket(tcp_ip=ip, tcp_port=port) self.socket_thread = QThread() self.socket.moveToThread(self.socket_thread) self.socket_thread.started.connect(self.socket.start) self.socket.new_data.connect(self.update_image) self.socket_thread.start() self.connected = True def update_image(self, data): image = data[0]['data'] assert (np.max(image) <= 255) image8 = image.astype(np.uint8, order='C', casting='unsafe') height, width, colors = image8.shape bytesPerLine = 3 * width image = QImage(image8.data, width, height, bytesPerLine, QImage.Format_RGB888) image = image.rgbSwapped() pixmap = QPixmap(image) scene = QGraphicsScene() scene.addPixmap(pixmap.scaled(self.image.width(), self.image.height(), Qt.KeepAspectRatio)) self.image.setScene(scene)
def initUI(self): self.scene = GraphicsScene(self) self.scene._image = QImage('1513411692.png') view = QGraphicsView(self.scene, self) self.scene.setSceneRect(0, 0, view.width(), view.height()) addLine = QPushButton('AddLine') addLine.clicked.connect(self.addLine) hbox = QHBoxLayout(self) hbox.addWidget(view) vbox = QVBoxLayout(self) vbox.addWidget(addLine) hbox.addLayout(vbox) self.setWindowTitle(self.title) self.setGeometry(self.top, self.left, self.width, self.height) self.setFixedSize(self.width, self.height) self.setLayout(hbox) self.show()
def run(): app = QApplication(sys.argv) scene = QGraphicsScene() # adding scene background scene.setBackgroundBrush(QBrush(QImage('./imgs/background.png'))) player = Player() # add the item to the scene scene.addItem(player) # make player focusable player.setFlag(QGraphicsItem.ItemIsFocusable) player.setFocus() # add a view, widget(invisible) view = QGraphicsView(scene) view.setFixedSize(800, 600) # horizontal and vertical scroll bar has benn disabled view.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) view.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) scene.setSceneRect(0, 0, 800, 600) player.setPos(view.width() / 2 - player.pixmap().width() / 2, view.height() - player.pixmap().height()) view.show() global score score = Score() scene.addItem(score) global health health = Health() scene.addItem(health) # spawn enemies timer = QTimer() def spawn(): enemy = Enemy() scene.addItem(enemy) timer.timeout.connect(spawn) timer.start(1000) # play background music url = QUrl.fromLocalFile("./sounds/intro.ogg") media = M.QMediaContent(url) playlist = M.QMediaPlaylist() playlist.addMedia(media) playlist.setPlaybackMode(M.QMediaPlaylist.Loop) music = M.QMediaPlayer() music.setPlaylist(playlist) music.setVolume(10) music.play() # media = M.QMediaContent(url) # music = M.QMediaPlayer() # music.setMedia(media) # music.setVolume(20) # music.play() sys.exit(app.exec_())
class BattleView(QObject): def __init__(self, battle_window, parent=None): super().__init__(parent) self.battleWindow = battle_window # MainBattleWindow container_widget if len(self.battleWindow.config.errors) != 0: # noinspection PyArgumentList QMessageBox.critical(battle_window, 'Configuration Error', self.battleWindow.config.get_error_str()) exit(-1) # main elements self.centralWidget = QWidget(self.battleWindow) self.gridLayout = QGridLayout(self.centralWidget) # misc side elements self.graphicsView_coatOfArm = CustomScene() self.graphicsView_currentUnit = CustomScene() self.graphicsView_targetedUnit = CustomScene() for button in self.graphicsView_coatOfArm, self.graphicsView_currentUnit, self.graphicsView_targetedUnit: button.enter_functions.append(self.set_label_hint) button.leave_functions.append(self.clear_label_hint) # buttons self.autoCombatButton = CustomButton(self.centralWidget) self.helpButton = CustomButton(self.centralWidget) self.retreatButton = CustomButton(self.centralWidget) self.endUnitTurnButton = CustomButton(self.centralWidget) self.nextTargetButton = CustomButton(self.centralWidget) for button in self.autoCombatButton, self.helpButton, self.retreatButton, self.nextTargetButton, self.endUnitTurnButton: button.enter_functions.append(self.set_label_hint) button.leave_functions.append(self.clear_label_hint) button.click_functions.append(self.click_button) # info containers self.dateLabel = QLabel( self.centralWidget) # display current turn in battle self.hintLabel = QLabel( self.centralWidget) # display hint when hovering over an elemend # the actual battle scene self.mainScene = MainQGraphicsScene() self.graphicsView_main = QGraphicsView(self.mainScene) self.gridLayout.addWidget(self.graphicsView_main, 1, 0, 12, 1) def setup_ui(self): self.battleWindow.setWindowTitle( self.battleWindow.config.get_text('battle.window.title') + ' v' + str(self.battleWindow.config.version)) background = self.battleWindow.config.theme_selected.get_background_pixmap( ) palette = QPalette() palette.setBrush(QPalette.Background, QBrush(background)) self.battleWindow.setMinimumSize(constants.get_min_resolution_qsize()) self.battleWindow.setAutoFillBackground(True) self.gridLayout.setVerticalSpacing(0) self.setup_hint_label() # Labels self.setup_turn_label() # Labels self.setup_space() # Space item self.setup_help_button() # Help Push Button self.setup_next_target_button() # Next Target Button self.setup_end_unit_button() # End Unit Button self.setup_retreat_button() # Retreat Button self.setup_auto_combat_button() # Automatic battle button self.setup_targeted_unit_view() # Targeted Unit view self.setup_current_unit_view() # Current Unit View self.setup_coat_of_arms_view() # Coat of Arm view self.setup_map() # Main view self.battleWindow.setPalette(palette) self.battleWindow.setCentralWidget(self.centralWidget) # noinspection PyArgumentList QMetaObject.connectSlotsByName(self.battleWindow) def setup_map(self): self.mainScene = MainQGraphicsScene() self.graphicsView_main.setScene(self.mainScene) self.mainScene.set_battle_view(self.battleView) width = 2 * self.graphicsView_main.height() / math.sqrt(3) height = self.graphicsView_main.height() if width > self.graphicsView_main.width(): width = self.graphicsView_main.width() height = self.graphicsView_main.width() * math.sqrt(3) / 2 item = self.mainScene.addRect(0, 0, width - 15, height - 15) item.hide() self.battleView.draw_battle_map(self.mainScene) def resize_event(self): self.setup_map() # misc elements def setup_hint_label(self): size_policy = constants.default_size_policy(self.hintLabel, QSizePolicy.Preferred, QSizePolicy.Fixed) self.hintLabel.setSizePolicy(size_policy) self.hintLabel.setFont(constants.default_font()) self.hintLabel.setAlignment(Qt.AlignRight | Qt.AlignTrailing | Qt.AlignVCenter) self.gridLayout.addWidget(self.hintLabel, 0, 0, 1, 1) def setup_turn_label(self): size_policy = constants.default_size_policy(self.dateLabel, QSizePolicy.Preferred, QSizePolicy.Fixed) self.dateLabel.setSizePolicy(size_policy) self.dateLabel.setFont(constants.default_font()) self.dateLabel.setText('Turn ' + str(self.battleView.turn)) self.dateLabel.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) self.gridLayout.addWidget(self.dateLabel, 0, 0, 1, 1) def setup_space(self): # Space between help Button and flag view spacer_item = QSpacerItem(20, 10, QSizePolicy.Minimum, QSizePolicy.MinimumExpanding) self.gridLayout.addItem(spacer_item, 2, 1, 1, 1) # Space between flag view and next target Button spacer_item1 = QSpacerItem(20, 10, QSizePolicy.Minimum, QSizePolicy.MinimumExpanding) self.gridLayout.addItem(spacer_item1, 4, 1, 1, 1) # Space between retreat Button and targetted unit view spacer_item2 = QSpacerItem(20, 10, QSizePolicy.Minimum, QSizePolicy.Fixed) self.gridLayout.addItem(spacer_item2, 8, 1, 1, 1) # Space between current unit view and auto Button spacer_item3 = QSpacerItem(20, 10, QSizePolicy.Minimum, QSizePolicy.MinimumExpanding) self.gridLayout.addItem(spacer_item3, 11, 1, 1, 1) def setup_coat_of_arms_view(self): size = QSize(90, 120) self.battleView.draw_coat_of_arms(self.graphicsView_coatOfArm.scene(), size) self.graphicsView_coatOfArm.setVerticalScrollBarPolicy( Qt.ScrollBarAlwaysOff) size_policy = constants.default_size_policy( self.graphicsView_coatOfArm, QSizePolicy.Fixed, QSizePolicy.Fixed) self.graphicsView_coatOfArm.setSizePolicy(size_policy) self.graphicsView_coatOfArm.setMinimumSize(size) self.graphicsView_coatOfArm.setMaximumSize(size) self.graphicsView_coatOfArm.setStyleSheet( "border-style: none;background: transparent") self.graphicsView_coatOfArm.setCacheMode(QGraphicsView.CacheBackground) self.gridLayout.addWidget(self.graphicsView_coatOfArm, 3, 1, 1, 1) # unit views def setup_targeted_unit_view(self): size = QSize(60, 60) army = self.get_computer_army() defending = (army == self.battleView.defender) self.battleView.draw_targetted_unit( defending, self.graphicsView_targetedUnit.scene(), size) size_policy = constants.default_size_policy( self.graphicsView_targetedUnit, QSizePolicy.Fixed, QSizePolicy.Fixed) self.graphicsView_targetedUnit.setSizePolicy(size_policy) self.graphicsView_targetedUnit.setMinimumSize(size) self.graphicsView_targetedUnit.setMaximumSize(size) self.gridLayout.addWidget(self.graphicsView_targetedUnit, 9, 1, 1, 1, Qt.AlignCenter) def setup_current_unit_view(self): size = QSize(60, 60) army = self.get_human_army() defending = (army == self.battleView.defender) self.battleView.draw_current_unit( defending, self.graphicsView_currentUnit.scene(), size) size_policy = constants.default_size_policy( self.graphicsView_currentUnit, QSizePolicy.Fixed, QSizePolicy.Fixed) self.graphicsView_currentUnit.setSizePolicy(size_policy) self.graphicsView_currentUnit.setMinimumSize(size) self.graphicsView_currentUnit.setMaximumSize(size) self.gridLayout.addWidget(self.graphicsView_currentUnit, 10, 1, 1, 1, Qt.AlignCenter) def get_human_army(self): if self.battleView.attacker.nation.computer: return self.battleView.defender return self.battleView.attacker def get_computer_army(self): if self.battleView.attacker.nation.computer: return self.battleView.attacker return self.battleView.defender # buttons def setup_next_target_button(self): size_policy = constants.default_size_policy(self.nextTargetButton, QSizePolicy.Fixed, QSizePolicy.Fixed) self.nextTargetButton.setSizePolicy(size_policy) self.nextTargetButton.setMinimumSize(QSize(45, 45)) self.nextTargetButton.setMaximumSize(QSize(45, 45)) self.nextTargetButton.setText("") icon = QIcon() icon.addPixmap( QPixmap(self.battleWindow.config.theme_selected. get_target_button_pixmap()), QIcon.Normal, QIcon.Off) self.nextTargetButton.setIcon(icon) self.nextTargetButton.setIconSize(QSize(40, 40)) self.gridLayout.addWidget(self.nextTargetButton, 5, 1, 1, 1, Qt.AlignCenter) def setup_end_unit_button(self): size_policy = constants.default_size_policy(self.endUnitTurnButton, QSizePolicy.Fixed, QSizePolicy.Fixed) self.endUnitTurnButton.setSizePolicy(size_policy) self.endUnitTurnButton.setMinimumSize(QSize(45, 45)) self.endUnitTurnButton.setMaximumSize(QSize(45, 45)) self.endUnitTurnButton.setText("") icon1 = QIcon() icon1.addPixmap( self.battleWindow.config.theme_selected.get_end_button_pixmap(), QIcon.Normal, QIcon.Off) self.endUnitTurnButton.setIcon(icon1) self.endUnitTurnButton.setIconSize(QSize(40, 40)) self.gridLayout.addWidget(self.endUnitTurnButton, 6, 1, 1, 1, Qt.AlignCenter) def setup_retreat_button(self): size_policy = constants.default_size_policy(self.retreatButton, QSizePolicy.Fixed, QSizePolicy.Fixed) self.retreatButton.setSizePolicy(size_policy) self.retreatButton.setMinimumSize(QSize(45, 45)) self.retreatButton.setMaximumSize(QSize(45, 45)) self.retreatButton.setToolTip("") self.retreatButton.setWhatsThis("") self.retreatButton.setText("") icon2 = QIcon() icon2.addPixmap( QPixmap(self.battleWindow.config.theme_selected. get_retreat_button_pixmap()), QIcon.Normal, QIcon.Off) self.retreatButton.setIcon(icon2) self.retreatButton.setIconSize(QSize(42, 40)) self.gridLayout.addWidget(self.retreatButton, 7, 1, 1, 1, Qt.AlignCenter) def setup_help_button(self): size_policy = constants.default_size_policy(self.helpButton, QSizePolicy.Fixed, QSizePolicy.Fixed) self.helpButton.setSizePolicy(size_policy) self.helpButton.setMinimumSize(QSize(80, 80)) self.helpButton.setMaximumSize(QSize(80, 80)) self.helpButton.setText("") icon3 = QIcon() icon3.addPixmap( QPixmap(self.battleWindow.config.theme_selected. get_help_button_pixmap()), QIcon.Normal, QIcon.Off) self.helpButton.setIcon(icon3) self.helpButton.setIconSize(QSize(75, 75)) self.gridLayout.addWidget(self.helpButton, 0, 1, 2, 1) def setup_auto_combat_button(self): size_policy = constants.default_size_policy(self.autoCombatButton, QSizePolicy.Fixed, QSizePolicy.Fixed) self.autoCombatButton.setSizePolicy(size_policy) self.autoCombatButton.setMinimumSize(QSize(90, 90)) self.autoCombatButton.setMaximumSize(QSize(90, 90)) self.autoCombatButton.setText("") icon4 = QIcon() icon4.addPixmap( QPixmap(self.battleWindow.config.theme_selected. get_autocombat_button_pixmap()), QIcon.Normal, QIcon.Off) self.autoCombatButton.setIcon(icon4) self.autoCombatButton.setIconSize(QSize(80, 80)) self.gridLayout.addWidget(self.autoCombatButton, 12, 1, 1, 1) # element interactions def clear_label_hint(self, generic_element): self.hintLabel.setText('') def set_label_hint(self, generic_element): text = '' if generic_element in self.battleView.map.fields: # TODO - not hooked up text = str(generic_element) elif generic_element == self.graphicsView_currentUnit: text = str(self.battleView.currentUnit) elif generic_element == self.graphicsView_targetedUnit: text = str(self.battleView.targettedUnit) elif generic_element == self.autoCombatButton: text = self.battleWindow.config.get_text('auto.play.label') elif generic_element == self.helpButton: text = self.battleWindow.config.get_text( 'help.tacticalbattle.label') elif generic_element == self.retreatButton: text = self.battleWindow.config.get_text('retreat.all.label') elif generic_element == self.endUnitTurnButton: text = self.battleWindow.config.get_text('end.unit.label') elif generic_element == self.nextTargetButton: text = self.battleWindow.config.get_text('next.target.label') if text != '': self.hintLabel.setText(text) def click_button(self, button_element): if button_element == self.autoCombatButton: self.battleView.autoCombat = True elif button_element == self.helpButton: print('click helpButton') elif button_element == self.retreatButton: self.get_human_army().retreat = True elif button_element == self.endUnitTurnButton: print('click endUnitTurnButton') elif button_element == self.nextTargetButton: print('click nextTargetButton')
class Ui_Form(object): def __init__(self, obj): super().__init__() self.setupUi(obj) self.retranslateUi(obj) self.graphicsView = QGraphicsView(obj) self.graphicsView.setGeometry(QtCore.QRect(10, 10, 791, 441)) self.graphicsView.setObjectName("graphicsView") self.scene = QtWidgets.QGraphicsScene() self.graphicsView.setScene(self.scene) pen = QtGui.QPen(QtCore.Qt.GlobalColor.gray) for i in range(-1 * self.graphicsView.height() // 2 + 10, self.graphicsView.height() // 2 - 10): r1 = QtCore.QRectF(QtCore.QPointF(0, i), QtCore.QSizeF(1, 1)) self.scene.addRect(r1, pen) for i in range(-1 * self.graphicsView.width() // 2 + 10, self.graphicsView.width() // 2 - 10): r2 = QtCore.QRectF(QtCore.QPointF(i, 0), QtCore.QSizeF(1, 1)) self.scene.addRect(r2, pen) self.coordsContainer = [] self.centersContainer = [] self.clastersContainer = [] self.distance = None def setupUi(self, Form): Form.setObjectName("Form") Form.resize(815, 678) self.startPushButton = QPushButton(Form) self.startPushButton.clicked.connect( self.startPushButton_button_clicked) self.startPushButton.setGeometry(QtCore.QRect(260, 620, 261, 41)) self.startPushButton.setObjectName("startPushButton") self.coordsTextBox = QtWidgets.QPlainTextEdit(Form) self.coordsTextBox.setGeometry(QtCore.QRect(260, 470, 261, 81)) self.coordsTextBox.setObjectName("coordsTextBox") self.CentersTextBox = QtWidgets.QPlainTextEdit(Form) self.CentersTextBox.setGeometry(QtCore.QRect(540, 470, 261, 81)) self.CentersTextBox.setObjectName("CentersTextBox") self.addCordsPushButton = QPushButton(Form) self.addCordsPushButton.clicked.connect( self.addCordsPushButton_button_clicked) self.addCordsPushButton.setGeometry(QtCore.QRect(260, 570, 541, 31)) self.addCordsPushButton.setObjectName("addCordsPushButton") self.groupBox = QtWidgets.QGroupBox(Form) self.groupBox.setGeometry(QtCore.QRect(10, 460, 241, 91)) self.groupBox.setObjectName("groupBox") self.euclidRadioButton = QRadioButton(self.groupBox) self.euclidRadioButton.toggled.connect(self.euclidRadioButton_clicked) self.euclidRadioButton.setGeometry(QtCore.QRect(10, 20, 221, 31)) self.euclidRadioButton.setObjectName("euclidRadioButton") self.chebishevRadioButton = QRadioButton(self.groupBox) self.chebishevRadioButton.toggled.connect( self.chebishevRadioButton_clicked) self.chebishevRadioButton.setGeometry(QtCore.QRect(10, 50, 221, 41)) self.chebishevRadioButton.setObjectName("chebishevRadioButton") self.stepPushButton = QPushButton(Form) self.stepPushButton.clicked.connect(self.stepPushButton_button_clicked) self.stepPushButton.setGeometry(QtCore.QRect(540, 620, 261, 41)) self.stepPushButton.setObjectName("stepPushButton") self.restartPushButton = QPushButton(Form) self.restartPushButton.clicked.connect( self.restartPushButton_button_clicked) self.restartPushButton.setGeometry(QtCore.QRect(10, 620, 241, 41)) self.restartPushButton.setObjectName("restartPushButton") self.testPushButton = QPushButton(Form) self.testPushButton.clicked.connect(self.testPushButton_button_clicked) self.testPushButton.setGeometry(QtCore.QRect(10, 570, 241, 31)) self.testPushButton.setObjectName("testPushButton") self.retranslateUi(Form) QtCore.QMetaObject.connectSlotsByName(Form) def retranslateUi(self, Form): _translate = QtCore.QCoreApplication.translate Form.setWindowTitle(_translate("Form", "Form")) self.startPushButton.setText(_translate("Form", "START")) self.addCordsPushButton.setText(_translate("Form", "ADD COORDINATES")) self.groupBox.setTitle(_translate("Form", "Distance")) self.euclidRadioButton.setText(_translate("Form", "Euclid")) self.chebishevRadioButton.setText(_translate("Form", "Chebishev")) self.stepPushButton.setText(_translate("Form", "STEP")) self.restartPushButton.setText(_translate("Form", "RESTART")) self.testPushButton.setText(_translate("Form", "Set Test Dataset")) def drawLineToDot(self): pen = QtGui.QPen(QtCore.Qt.GlobalColor.blue) brush = QtGui.QBrush(QtCore.Qt.GlobalColor.blue) pen.setWidth(2) pen.setColor(QtCore.Qt.GlobalColor.blue) for i in range(len(self.clastersContainer)): for j in self.clastersContainer[i]: self.scene.addLine( QtCore.QLineF(4 * j[0], -4 * j[1], 4 * self.centersContainer[i][0], -4 * self.centersContainer[i][1]), pen) def stringParser(self, coords, centers): coords_l = None centers_l = None try: coords_string_array = coords.split(';') centers_string_array = centers.split(';') coords_l = [] centers_l = [] for i in coords_string_array: l = [float(k) for k in i.strip('()').split(',')] coords_l.append(l) for i in centers_string_array: l = [float(k) for k in i.strip('()').split(',')] centers_l.append(l) except: self.CentersTextBox.clear() self.coordsTextBox.clear() msg = QtWidgets.QMessageBox() msg.setIcon(QtWidgets.QMessageBox.Critical) msg.setText("Format Error") msg.setInformativeText('Follow the format!') msg.setWindowTitle("Error") msg.setStyleSheet("QLabel{font-size: 20px;}") msg.exec_() pass return coords_l, centers_l def add_coordinates_to_GraphView(self): pen = QtGui.QPen(QtCore.Qt.GlobalColor.black) brush = QtGui.QBrush(QtCore.Qt.GlobalColor.black) side = 4 for i in self.coordsContainer: self.scene.addEllipse(i[0] * side - 3, -1 * i[1] * side - 3, 7, 7, pen, brush) pen = QtGui.QPen(QtCore.Qt.GlobalColor.red) brush = QtGui.QBrush(QtCore.Qt.GlobalColor.red) for i in self.centersContainer: self.scene.addEllipse(i[0] * side - 3, -1 * i[1] * side - 3, 7, 7, pen, brush) def addCordsPushButton_button_clicked(self): coordinates = self.coordsTextBox.toPlainText() centers = self.CentersTextBox.toPlainText() if coordinates == '' or centers == '': msg = QtWidgets.QMessageBox() msg.setIcon(QtWidgets.QMessageBox.Critical) msg.setText("Data Empty") msg.setInformativeText('Please, enter coords') msg.setWindowTitle("Error") msg.setStyleSheet("QLabel{font-size: 20px;}") msg.exec_() return coordinates_l, centers_l = self.stringParser(coordinates, centers) if coordinates_l is not None and centers_l is not None: co = self.coordsContainer.copy() ce = self.centersContainer.copy() co += coordinates_l.copy() ce += centers_l.copy() co.sort() ce.sort() co_new = list(num for num, _ in itertools.groupby(co)) ce_new = list(num for num, _ in itertools.groupby(ce)) self.centersContainer = ce_new.copy() self.coordsContainer = co_new.copy() print(self.centersContainer) print(self.coordsContainer) self.add_coordinates_to_GraphView() def startPushButton_button_clicked(self): if self.coordsContainer == [] or self.centersContainer == []: msg = QtWidgets.QMessageBox() msg.setIcon(QtWidgets.QMessageBox.Critical) msg.setText("Data Empty") msg.setInformativeText('Please, enter coords') msg.setWindowTitle("Error") msg.setStyleSheet("QLabel{font-size: 20px;}") msg.exec_() return self.chebishevRadioButton.setEnabled(False) self.euclidRadioButton.setEnabled(False) self.addCordsPushButton.setEnabled(False) self.coordsTextBox.setEnabled(False) self.CentersTextBox.setEnabled(False) self.startPushButton.setEnabled(False) self.testPushButton.setEnabled(False) if self.distance == 'E': for _ in range(len(self.centersContainer)): self.clastersContainer.append([]) for i in self.coordsContainer: range_l = [] for c in self.centersContainer: range_l.append( math.sqrt((i[0] - c[0])**2 + (i[1] - c[1])**2)) minindex = range_l.index(min(range_l)) self.clastersContainer[minindex].append(i) self.drawLineToDot() elif self.distance == 'H': for _ in range(len(self.centersContainer)): self.clastersContainer.append([]) for i in self.coordsContainer: range_l = [] for c in self.centersContainer: range_l.append(max(abs(i[0] - c[0]), abs(i[1] - c[1]))) minindex = range_l.index(min(range_l)) self.clastersContainer[minindex].append(i) self.drawLineToDot() def stepPushButton_button_clicked(self): if self.centersContainer is None or self.coordsContainer is None: msg = QtWidgets.QMessageBox() msg.setIcon(QtWidgets.QMessageBox.Critical) msg.setText("Empty Error") msg.setInformativeText('Not enough dots!') msg.setWindowTitle("Error") msg.setStyleSheet("QLabel{font-size: 20px;}") msg.exec_() return claster_backup = self.clastersContainer.copy() new_centers = [] for i in self.clastersContainer: new_x, new_y = 0, 0 for k in i: new_x += k[0] new_y += k[1] new_x /= len(i) new_y /= len(i) new_centers.append([new_x, new_y]) self.centersContainer = new_centers.copy() self.redrow(False) self.add_coordinates_to_GraphView() self.clastersContainer.clear() for _ in range(len(self.centersContainer)): self.clastersContainer.append([]) for i in self.coordsContainer: range_l = [] for c in new_centers: range_l.append(math.sqrt((i[0] - c[0])**2 + (i[1] - c[1])**2)) minindex = range_l.index(min(range_l)) self.clastersContainer[minindex].append(i) self.drawLineToDot() new_back_clasters = self.clastersContainer.copy() if claster_backup == new_back_clasters: self.stepPushButton.setEnabled(False) def redrow(self, full): self.scene.clear() pen = QtGui.QPen(QtCore.Qt.GlobalColor.gray) for i in range(-1 * self.graphicsView.height() // 2 + 10, self.graphicsView.height() // 2 - 10): r1 = QtCore.QRectF(QtCore.QPointF(0, i), QtCore.QSizeF(1, 1)) self.scene.addRect(r1, pen) for i in range(-1 * self.graphicsView.width() // 2 + 10, self.graphicsView.width() // 2 - 10): r2 = QtCore.QRectF(QtCore.QPointF(i, 0), QtCore.QSizeF(1, 1)) self.scene.addRect(r2, pen) if not full: pen2 = QtGui.QPen(QtCore.Qt.GlobalColor.black) brush2 = QtGui.QBrush(QtCore.Qt.GlobalColor.black) side = 4 for i in self.coordsContainer: self.scene.addEllipse(i[0] * side - 3, -1 * i[1] * side - 3, 7, 7, pen2, brush2) def restartPushButton_button_clicked(self): self.chebishevRadioButton.setEnabled(True) self.euclidRadioButton.setEnabled(True) self.addCordsPushButton.setEnabled(True) self.coordsTextBox.setEnabled(True) self.CentersTextBox.setEnabled(True) self.testPushButton.setEnabled(True) self.startPushButton.setEnabled(True) self.stepPushButton.setEnabled(True) self.redrow(True) self.coordsContainer.clear() self.centersContainer.clear() self.clastersContainer.clear() def testPushButton_button_clicked(self): self.coordsTextBox.setPlainText(TEST_COORDS) if self.distance == 'E': self.CentersTextBox.setPlainText(EUCLID_TEST_CENTERS) elif self.distance == 'H': self.CentersTextBox.setPlainText(CHEBISHEV_TEST_CENTERS) else: self.coordsTextBox.clear() msg = QtWidgets.QMessageBox() msg.setIcon(QtWidgets.QMessageBox.Critical) msg.setText("Distance not set") msg.setInformativeText('Please, pick the distance') msg.setWindowTitle("Error") msg.setStyleSheet("QLabel{font-size: 20px;}") msg.exec_() pass def euclidRadioButton_clicked(self): if self.euclidRadioButton.isChecked(): self.distance = 'E' def chebishevRadioButton_clicked(self): if self.chebishevRadioButton.isChecked(): self.distance = 'H'
class MainWindow(QMainWindow): class MainScene(QGraphicsScene): def __init__(self, parent=None): super().__init__(parent) self.parent = parent self.prev_active_rect = None self.active_elements = [] def mouseMoveEvent(self, event: 'QGraphicsSceneMouseEvent') -> None: try: good = False for _event, event_object in self.parent.events: if _event.x1 <= event.scenePos().x() <= _event.x2 \ and _event.y1 <= event.scenePos().y() <= _event.y2: if self.prev_active_rect is not None: self.prev_active_rect.setBrush( QBrush(QColor.fromRgb(250, 240, 240))) self.prev_active_rect = None event_object.setBrush(QBrush(Qt.green)) self.prev_active_rect = event_object good = True if not good and self.prev_active_rect is not None: self.prev_active_rect.setBrush( QBrush(QColor.fromRgb(250, 240, 240))) self.prev_active_rect = None except Exception as e: print(e) def mousePressEvent(self, event: 'QGraphicsSceneMouseEvent') -> None: try: for element in self.active_elements: element.setBrush(QBrush(QColor.fromRgb(240, 240, 250))) except Exception as exception: print('error with a brush in mousePressEvent in MainScene:', exception) try: if event.button() == 2: current_x, current_y = event.scenePos().x( ), event.scenePos().y() for rect, object_rect in self.parent.rectangles: try: if rect.x1 <= current_x <= rect.x2 and \ rect.y1 <= current_y <= rect.y2: try: context_menu = QMenu() history = context_menu.addAction('history') action = context_menu.exec(QCursor().pos()) if action == history: rect.widget = QWidget() rect.widget.setWindowTitle( 'Biography of {}'.format( rect.name)) layout = QHBoxLayout() label = QLabel() label.setText(rect.description) layout.addWidget(label) rect.widget.setLayout(layout) rect.widget.setGeometry( QCursor().pos().x(), QCursor().pos().y(), 500, 200) rect.widget.show() except Exception as exception: print(exception) except Exception as exception: print(exception) elif event.button() == 1: current_x, current_y = event.scenePos().x( ), event.scenePos().y() for _event, event_object in self.parent.events: if _event.x1 <= current_x <= _event.x2 and _event.y1 <= current_y <= _event.y2: for _rect, object_rect in self.parent.rectangles: year_from = int(_rect.years.split()[0]) year_to = int(_rect.years.split()[2]) if year_from <= int(_event.years) <= year_to: object_rect.setBrush( QBrush(QColor.fromRgb(200, 200, 240))) self.active_elements.append(object_rect) pass except Exception as e: print(e) print('finished') def closeEvent(self, a0: QtGui.QCloseEvent) -> None: import sys sys.exit(0) def __init__(self): super().__init__() self.setWindowTitle('Genealogy tree') self.setGeometry(500, 50, 1000, 900) self.view = QTableView() layout = QHBoxLayout() w = QWidget(self) w.setLayout(layout) self.scene = self.MainScene(self) self.graphics_view = QGraphicsView(self.scene) self.graphics_view.setMouseTracking(True) self.graphics_view.setFixedSize(900, 900) self.setMouseTracking(True) self.events = [] layout.addWidget(self.graphics_view) database_layout = QVBoxLayout() layout.addLayout(database_layout) font = QFont('Times') font.setPixelSize(20) change_tree_structure_button = QPushButton( 'change structure of the tree') change_tree_structure_button.setFixedSize(300, 150) change_tree_structure_button.setFont(font) change_events_structure_button = QPushButton( 'change structure of events') change_events_structure_button.setFixedSize(300, 150) change_events_structure_button.setFont(font) rebuild_tree_button = QPushButton('rebuild tree') rebuild_tree_button.setFixedSize(300, 150) rebuild_tree_button.setFont(font) database_layout.addWidget(change_tree_structure_button) database_layout.addWidget(change_events_structure_button) database_layout.addWidget(rebuild_tree_button) change_events_structure_button.clicked.connect( self.change_events_structure) change_tree_structure_button.clicked.connect( self.change_tree_structure) rebuild_tree_button.clicked.connect(self.rebuild_tree) self.setCentralWidget(w) self.scale = 1 self.db_widget = None self.add_element_widget = None self.remove_element_widget = None self.add_connection_widget = None self.remove_connection_widget = None self.db_widget_events = None self.add_event_widget = None self.remove_event_widget = None def change_tree_structure(self): self.db_widget = QWidget() self.db_widget.setGeometry(1000, 200, 400, 100) self.db_widget.setWindowTitle('Change structure of the tree') layout = QVBoxLayout() add_element_in_data_base = QPushButton('add note') remove_element_from_data_base = QPushButton('del note') add_connection_in_data_base = QPushButton('add connection') remove_connection_in_data_base = QPushButton('del connection') layout.addWidget(add_element_in_data_base) layout.addWidget(remove_element_from_data_base) layout.addWidget(add_connection_in_data_base) layout.addWidget(remove_connection_in_data_base) add_element_in_data_base.clicked.connect(self.add_element_in_data_base) remove_element_from_data_base.clicked.connect( self.remove_element_from_data_base) add_connection_in_data_base.clicked.connect( self.add_connection_in_data_base) remove_connection_in_data_base.clicked.connect( self.remove_connection_in_data_base) self.db_widget.setLayout(layout) self.db_widget.show() def change_events_structure(self): self.db_widget_events = QWidget() self.db_widget_events.setGeometry(1000, 200, 400, 100) self.db_widget_events.setWindowTitle('Change structure of events') layout = QVBoxLayout() add_element_in_data_base = QPushButton('add note') remove_element_from_data_base = QPushButton('del note') layout.addWidget(add_element_in_data_base) layout.addWidget(remove_element_from_data_base) add_element_in_data_base.clicked.connect(self.add_event_in_data_base) remove_element_from_data_base.clicked.connect( self.remove_event_from_data_base) self.db_widget_events.setLayout(layout) self.db_widget_events.show() def add_event_in_data_base(self): add_event_widget = QWidget() add_event_widget.setGeometry(1100, 250, 700, 200) add_event_widget.setWindowTitle('Add new event') layout = QVBoxLayout() first_layout = QHBoxLayout() second_layout = QHBoxLayout() layout.addLayout(first_layout) layout.addLayout(second_layout) apply_button = QPushButton('apply') apply_button.clicked.connect(self.apply_button_operation_add_event) layout.addWidget(apply_button) for title in ['title', 'description', 'year']: first_layout.addWidget(QLabel(title)) second_layout.addWidget(QTextEdit()) add_event_widget.setLayout(layout) add_event_widget.show() self.add_event_widget = add_event_widget def apply_button_operation_add_event(self): title = self.add_event_widget.layout().itemAt(1).layout().itemAt( 0).widget().toPlainText() description = self.add_event_widget.layout().itemAt(1).layout().itemAt( 1).widget().toPlainText() year = self.add_event_widget.layout().itemAt(1).layout().itemAt( 2).widget().toPlainText() if title and description and year: human_and_time_database.TimeEvent.create(title=title, description=description, date=year) self.add_event_widget.close() else: message = QErrorMessage(self) message.setWindowTitle('Input data error') message.showMessage('All fields must be filled') def remove_event_from_data_base(self): try: remove_event_widget = QWidget() remove_event_widget.setGeometry(1100, 250, 700, 200) remove_event_widget.setWindowTitle('Del event') layout = QVBoxLayout() first_layout = QHBoxLayout() second_layout = QHBoxLayout() layout.addLayout(first_layout) layout.addLayout(second_layout) apply_button = QPushButton('apply') print('here') apply_button.clicked.connect(self.apply_button_operation_del_event) print('here') layout.addWidget(apply_button) print('here') for title in ['title']: first_layout.addWidget(QLabel(title)) second_layout.addWidget(QTextEdit()) print('here') remove_event_widget.setLayout(layout) remove_event_widget.show() print('here') self.remove_event_widget = remove_event_widget print('here') except Exception as e: print('here', e) def apply_button_operation_del_event(self): try: title = self.remove_event_widget.layout().itemAt( 1).layout().itemAt(0).widget().toPlainText() if title: query = human_and_time_database.TimeEvent.select().where( human_and_time_database.TimeEvent.title == title).limit(1) if len(list(query)) == 1: human_and_time_database.TimeEvent.delete().where( (human_and_time_database.TimeEvent.title == query[0].title)).execute() self.remove_event_widget.close() else: message = QErrorMessage(self) message.setWindowTitle('Input data error') message.showMessage('No such node in the tree') else: message = QErrorMessage(self) message.setWindowTitle('Input data error') message.showMessage('All fields must be filled') except Exception as e: print('apply_button_operation_del_element: ', e) def add_element_in_data_base(self): add_element_widget = QWidget() add_element_widget.setGeometry(1100, 250, 700, 200) add_element_widget.setWindowTitle('Add element') layout = QVBoxLayout() first_layout = QHBoxLayout() second_layout = QHBoxLayout() layout.addLayout(first_layout) layout.addLayout(second_layout) apply_button = QPushButton('apply') apply_button.clicked.connect(self.apply_button_operation_add_element) layout.addWidget(apply_button) for title in ['name', 'biography', 'year of born', 'year of death']: first_layout.addWidget(QLabel(title)) second_layout.addWidget(QTextEdit()) add_element_widget.setLayout(layout) add_element_widget.show() self.add_element_widget = add_element_widget def apply_button_operation_add_element(self): name = self.add_element_widget.layout().itemAt(1).layout().itemAt( 0).widget().toPlainText() biography = self.add_element_widget.layout().itemAt(1).layout().itemAt( 1).widget().toPlainText() year_of_born = self.add_element_widget.layout().itemAt( 1).layout().itemAt(2).widget().toPlainText() year_of_death = self.add_element_widget.layout().itemAt( 1).layout().itemAt(3).widget().toPlainText() if name and biography and year_of_death and year_of_death: human_and_time_database.HumanModel.create( name=name, biography=biography, year_of_born=year_of_born, year_of_death=year_of_death) self.add_element_widget.close() else: message = QErrorMessage(self) message.setWindowTitle('Input data error') message.showMessage('All fields must be filled') def remove_element_from_data_base(self): try: remove_element_widget = QWidget() remove_element_widget.setGeometry(1100, 250, 700, 200) remove_element_widget.setWindowTitle('Del element') layout = QVBoxLayout() first_layout = QHBoxLayout() second_layout = QHBoxLayout() layout.addLayout(first_layout) layout.addLayout(second_layout) apply_button = QPushButton('apply') apply_button.clicked.connect( self.apply_button_operation_del_element) layout.addWidget(apply_button) for title in ['name']: first_layout.addWidget(QLabel(title)) second_layout.addWidget(QTextEdit()) remove_element_widget.setLayout(layout) remove_element_widget.show() self.remove_element_widget = remove_element_widget except Exception as e: print(e) def apply_button_operation_del_element(self): try: name = self.remove_element_widget.layout().itemAt( 1).layout().itemAt(0).widget().toPlainText() if name: query = human_and_time_database.HumanModel.select().where( human_and_time_database.HumanModel.name == name).limit(1) if len(list(query)) == 1: human = query[0] new_rows = [] for row in human_and_time_database.RelationTable.select(): if human.id in [row.spouse, row.parent1, row.parent2]: current_human = row.human current_spouse = None if row.spouse == human.id else row.spouse current_parent1 = None if row.parent1 == human.id else row.parent1 current_parent2 = None if row.parent2 == human.id else row.parent2 new_rows.append((current_human, current_spouse, current_parent1, current_parent2)) human_and_time_database.RelationTable.delete().where( (human_and_time_database.RelationTable.human == human.id) | (human_and_time_database.RelationTable.spouse == human.id) | (human_and_time_database.RelationTable.parent1 == human.id) | (human_and_time_database.RelationTable.parent2 == human.id)).execute() for h, s, p1, p2 in new_rows: human_and_time_database.RelationTable.create( human=h, spouse=s, parent1=p1, parent2=p2) human_and_time_database.HumanModel.delete().where( human_and_time_database.HumanModel.name == name).execute() self.remove_element_widget.close() else: message = QErrorMessage(self) message.setWindowTitle('Input data error') message.showMessage('No such node in the tree') else: message = QErrorMessage(self) message.setWindowTitle('Input data error') message.showMessage('All fields must be filled') except Exception as e: print('apply_button_operation_del_element: ', e) def add_connection_in_data_base(self): add_connection_widget = QWidget() add_connection_widget.setGeometry(1100, 250, 700, 200) add_connection_widget.setWindowTitle('Add connection') layout = QVBoxLayout() first_layout = QHBoxLayout() second_layout = QHBoxLayout() layout.addLayout(first_layout) layout.addLayout(second_layout) apply_button = QPushButton('apply') apply_button.clicked.connect( self.apply_button_operation_add_connection) layout.addWidget(apply_button) for title in ['name 1', 'name 2']: first_layout.addWidget(QLabel(title)) second_layout.addWidget(QTextEdit()) third_layout = QVBoxLayout() second_layout.addLayout(third_layout) first_layout.addWidget(QLabel('')) first_layout.addWidget(QLabel('Type of connection')) first_button = QRadioButton('spouse - spouse connection') first_button.setChecked(True) second_button = QRadioButton('parent - child connection') third_layout.addWidget(first_button) third_layout.addWidget(second_button) add_connection_widget.setLayout(layout) add_connection_widget.show() self.add_connection_widget = add_connection_widget def apply_button_operation_add_connection(self): name1 = self.add_connection_widget.layout().itemAt(1).layout().itemAt( 0).widget().toPlainText() name2 = self.add_connection_widget.layout().itemAt(1).layout().itemAt( 1).widget().toPlainText() spouse_connection = self.add_connection_widget.layout().itemAt( 1).layout().itemAt(2).layout().itemAt(0).widget().isChecked() try: if name1 and name2: human_1 = human_and_time_database.HumanModel.select().where( human_and_time_database.HumanModel.name == name1) human_2 = human_and_time_database.HumanModel.select().where( human_and_time_database.HumanModel.name == name2) if len(human_1) != 1 or len(human_2) != 1: message = QErrorMessage(self) message.setWindowTitle('Input data error') message.showMessage('No human with set name in the tree') return human_1 = human_1[0] human_2 = human_2[0] human_id1 = human_1.id human_id2 = human_2.id if human_id1 == human_id2: message = QErrorMessage(self) message.setWindowTitle('Input data error') message.showMessage( 'Cant create a connection between human and himself') return if spouse_connection: all_connections = human_and_time_database.RelationTable.select( ) graph = dict() for connection in all_connections: human = connection.human spouse = connection.spouse parent1 = connection.parent1 parent2 = connection.parent2 graph[human] = (spouse, parent1, parent2) if human_id1 not in graph: graph[human_id1] = (None, None, None) if human_id2 not in graph: graph[human_id2] = (None, None, None) if graph[human_id1][0] == human_id2: message = QErrorMessage(self) message.setWindowTitle('Input data error') message.showMessage('Connection already exists') return if graph[human_id1][0] is not None or graph[human_id2][ 0] is not None: message = QErrorMessage(self) message.setWindowTitle('Input data error') message.showMessage( 'Another connection already exists with at least one of humans' ) return queue = [human_id1] i = 0 used = set() while i < len(queue): v = queue[i] if v is None or v in used: i += 1 continue used.add(v) if v == human_id2: message = QErrorMessage(self) message.setWindowTitle('Input data error') message.showMessage( 'Cyclic dependence! The connection cannot be built' ) return queue.append(graph[v][0]) queue.append(graph[v][1]) queue.append(graph[v][2]) queue = [human_id2] i = 0 used = set() while i < len(queue): v = queue[i] if v is None or v in used: i += 1 continue used.add(v) if v == human_id1: message = QErrorMessage(self) message.setWindowTitle('Input data error') message.showMessage( 'Cyclic dependence! The connection cannot be built' ) return queue.append(graph[v][0]) queue.append(graph[v][1]) queue.append(graph[v][2]) human_1 = human_id1 human_1_spouse = human_id2 human_1_parent1 = graph[human_id1][1] human_1_parent2 = graph[human_id1][2] human_2 = human_id2 human_2_spouse = human_id1 human_2_parent1 = graph[human_id2][1] human_2_parent2 = graph[human_id2][2] human_and_time_database.RelationTable.delete().where(( human_and_time_database.RelationTable.human == human_1 ) | (human_and_time_database.RelationTable.human == human_2 )).execute() human_and_time_database.RelationTable.create( human=human_1, spouse=human_1_spouse, parent1=human_1_parent1, parent2=human_1_parent2) human_and_time_database.RelationTable.create( human=human_2, spouse=human_2_spouse, parent1=human_2_parent1, parent2=human_2_parent2) self.add_connection_widget.close() else: all_connections = human_and_time_database.RelationTable.select( ) graph = dict() for connection in all_connections: human = connection.human spouse = connection.spouse parent1 = connection.parent1 parent2 = connection.parent2 graph[human] = (spouse, parent1, parent2) if human_id1 not in graph: graph[human_id1] = (None, None, None) if human_id2 not in graph: graph[human_id2] = (None, None, None) if graph[human_id2][1] == human_id1 or graph[human_id2][ 2] == human_id1: message = QErrorMessage(self) message.setWindowTitle('Input data error') message.showMessage('Connection already exists') return if graph[human_id2][1] is not None and graph[human_id2][ 2] is not None: message = QErrorMessage(self) message.setWindowTitle('Input data error') message.showMessage( 'The child already has two parents') return queue = [human_id1] i = 0 used = set() while i < len(queue): v = queue[i] if v is None or v in used: i += 1 continue used.add(v) if v == human_id2: message = QErrorMessage(self) message.setWindowTitle('Input data error') message.showMessage( 'Cyclic dependence! The connection cannot be built' ) return queue.append(graph[v][0]) queue.append(graph[v][1]) queue.append(graph[v][2]) queue = [human_id2] i = 0 used = set() while i < len(queue): v = queue[i] if v is None or v in used: i += 1 continue used.add(v) if v == human_id1: message = QErrorMessage(self) message.setWindowTitle('Input data error') message.showMessage( 'Cyclic dependence! The connection cannot be built' ) return queue.append(graph[v][0]) queue.append(graph[v][1]) queue.append(graph[v][2]) human_1 = human_id1 human_1_spouse = graph[human_id1][0] human_1_parent1 = graph[human_id1][1] human_1_parent2 = graph[human_id1][2] human_2 = human_id2 human_2_spouse = graph[human_id2][0] human_2_parent1 = graph[human_id2][1] human_2_parent2 = graph[human_id2][2] if human_2_parent1 is None: human_2_parent1 = human_1 else: human_2_parent2 = human_1 human_and_time_database.RelationTable.delete().where(( human_and_time_database.RelationTable.human == human_1 ) | (human_and_time_database.RelationTable.human == human_2 )).execute() human_and_time_database.RelationTable.create( human=human_1, spouse=human_1_spouse, parent1=human_1_parent1, parent2=human_1_parent2) human_and_time_database.RelationTable.create( human=human_2, spouse=human_2_spouse, parent1=human_2_parent1, parent2=human_2_parent2) self.add_connection_widget.close() else: message = QErrorMessage(self) message.setWindowTitle('Input data error') message.showMessage('All fields must be filled') except Exception as e: print(e) def remove_connection_in_data_base(self): remove_connection_widget = QWidget() remove_connection_widget.setGeometry(1100, 250, 700, 200) remove_connection_widget.setWindowTitle('Add connection') layout = QVBoxLayout() first_layout = QHBoxLayout() second_layout = QHBoxLayout() layout.addLayout(first_layout) layout.addLayout(second_layout) apply_button = QPushButton('apply') apply_button.clicked.connect( self.apply_button_operation_remove_connection) layout.addWidget(apply_button) for title in ['name 1', 'name 2']: first_layout.addWidget(QLabel(title)) second_layout.addWidget(QTextEdit()) third_layout = QVBoxLayout() second_layout.addLayout(third_layout) first_layout.addWidget(QLabel('')) first_layout.addWidget(QLabel('Type of connection')) first_button = QRadioButton('spouse - spouse connection') first_button.setChecked(True) second_button = QRadioButton('parent - child connection') third_layout.addWidget(first_button) third_layout.addWidget(second_button) remove_connection_widget.setLayout(layout) remove_connection_widget.show() self.remove_connection_widget = remove_connection_widget def apply_button_operation_remove_connection(self): name1 = self.remove_connection_widget.layout().itemAt( 1).layout().itemAt(0).widget().toPlainText() name2 = self.remove_connection_widget.layout().itemAt( 1).layout().itemAt(1).widget().toPlainText() spouse_connection = self.remove_connection_widget.layout().itemAt( 1).layout().itemAt(2).layout().itemAt(0).widget().isChecked() try: if name1 and name2: human_1 = human_and_time_database.HumanModel.select().where( human_and_time_database.HumanModel.name == name1) human_2 = human_and_time_database.HumanModel.select().where( human_and_time_database.HumanModel.name == name2) if len(human_1) != 1 or len(human_2) != 1: message = QErrorMessage(self) message.setWindowTitle('Input data error') message.showMessage('No human with set name in the tree') return human_1 = human_1[0] human_2 = human_2[0] human_id1 = human_1.id human_id2 = human_2.id if human_id1 == human_id2: message = QErrorMessage(self) message.setWindowTitle('Input data error') message.showMessage( 'No connection between human and himself') return if spouse_connection: all_connections = human_and_time_database.RelationTable.select( ) graph = dict() for connection in all_connections: human = connection.human spouse = connection.spouse parent1 = connection.parent1 parent2 = connection.parent2 graph[human] = (spouse, parent1, parent2) if human_id1 not in graph: graph[human_id1] = (None, None, None) if human_id2 not in graph: graph[human_id2] = (None, None, None) if graph[human_id1][0] != human_id2: message = QErrorMessage(self) message.setWindowTitle('Input data error') message.showMessage('No connection') return human_1 = human_id1 human_1_spouse = None human_1_parent1 = graph[human_id1][1] human_1_parent2 = graph[human_id1][2] human_2 = human_id2 human_2_spouse = None human_2_parent1 = graph[human_id2][1] human_2_parent2 = graph[human_id2][2] human_and_time_database.RelationTable.delete().where(( human_and_time_database.RelationTable.human == human_1 ) | (human_and_time_database.RelationTable.human == human_2 )).execute() human_and_time_database.RelationTable.create( human=human_1, spouse=human_1_spouse, parent1=human_1_parent1, parent2=human_1_parent2) human_and_time_database.RelationTable.create( human=human_2, spouse=human_2_spouse, parent1=human_2_parent1, parent2=human_2_parent2) self.remove_connection_widget.close() else: all_connections = human_and_time_database.RelationTable.select( ) graph = dict() for connection in all_connections: human = connection.human spouse = connection.spouse parent1 = connection.parent1 parent2 = connection.parent2 graph[human] = (spouse, parent1, parent2) if human_id1 not in graph: graph[human_id1] = (None, None, None) if human_id2 not in graph: graph[human_id2] = (None, None, None) if graph[human_id2][1] != human_id1 and graph[human_id2][ 2] != human_id1: message = QErrorMessage(self) message.setWindowTitle('Input data error') message.showMessage('No connection') return human_1 = human_id1 human_1_spouse = graph[human_id1][0] human_1_parent1 = graph[human_id1][1] human_1_parent2 = graph[human_id1][2] human_2 = human_id2 human_2_spouse = graph[human_id2][0] human_2_parent1 = graph[human_id2][1] human_2_parent2 = graph[human_id2][2] if human_2_parent1 == human_1: human_2_parent1 = None else: human_2_parent2 = None human_and_time_database.RelationTable.delete().where(( human_and_time_database.RelationTable.human == human_1 ) | (human_and_time_database.RelationTable.human == human_2 )).execute() human_and_time_database.RelationTable.create( human=human_1, spouse=human_1_spouse, parent1=human_1_parent1, parent2=human_1_parent2) human_and_time_database.RelationTable.create( human=human_2, spouse=human_2_spouse, parent1=human_2_parent1, parent2=human_2_parent2) self.remove_connection_widget.close() else: message = QErrorMessage(self) message.setWindowTitle('Input data error') message.showMessage('All fields must be filled') except Exception as e: print(e) def rebuild_tree(self): try: human_and_time_database.build_tree_from_database(self) except Exception as e: print(e) def keyPressEvent(self, a0: QtGui.QKeyEvent) -> None: if a0.key() == 43: # plus -> zoom in self.graphics_view.scale(6 / 5, 6 / 5) self.scale *= 6 / 5 elif a0.key() == 45: # minus -> zoom out self.graphics_view.scale(5 / 6, 5 / 6) self.scale *= 5 / 6 elif a0.key() == 61: # equal -> reset zoom self.graphics_view.scale(1 / self.scale, 1 / self.scale) self.scale = 1 def draw_rectangle(self, rect, pen=QPen(Qt.black, 8, Qt.SolidLine), brush=QBrush(QColor.fromRgb(240, 240, 255))): object_rect = self.scene.addRect(rect.x1, rect.y1, rect.x2 - rect.x1, rect.y2 - rect.y1, pen, brush) self.rectangles.append((rect, object_rect)) text_name = QGraphicsTextItem(rect.name) text_years = QGraphicsTextItem(rect.years) text_name.setPos(rect.x1 + 15, rect.y1 + 15) text_years.setPos(rect.x1 + 15, rect.y1 + 70) font = QFont() font.setBold(False) font.setPixelSize(35) text_name.setFont(font) text_years.setFont(font) self.scene.addItem(text_name) self.scene.addItem(text_years) def relax(self): kx = self.graphics_view.size().width() / max( 1, self.graphics_view.sceneRect().width()) ky = self.graphics_view.height() / max( 1, self.graphics_view.sceneRect().height()) k = min(kx, ky) * 2 self.graphics_view.scale(k, k) def draw_line(self, line): color = Qt.black pen = QPen(color, 8, Qt.SolidLine) self.lines.append(line) self.scene.addPath(line, pen) def draw_event(self, event, min_x, max_x, min_y, max_y, pen=QPen(Qt.black, 3, Qt.SolidLine), brush=QBrush(QColor.fromRgb(250, 240, 240))): object_event = self.scene.addRect(event.x1, event.y1, event.x2 - event.x1, event.y2 - event.y1, pen, brush) text = event.description.split() pre = 0 result_text = event.name + '\n\n' for word in text: if pre + len(word) > 50: pre = 0 result_text += '\n' pre += len(word) + 1 result_text += word + ' ' object_event.setToolTip(result_text) self.events.append((event, object_event)) text_event = QGraphicsTextItem(str(event.years)) text_event.setPos(event.x1 + 5, event.y1 + 5) font = QFont() font.setBold(False) font.setPixelSize(25) text_event.setFont(font) text_event.setFont(font) self.scene.addItem(text_event)
class IdpRecording(QWidget): def __init__(self): super().__init__() # -------------------- First class -------------------- self.main_page = QHBoxLayout(self) self.setLayout(self.main_page) # -------------------- Second class -------------------- # 1. input block (vertical) # 2. instruction block (horizontal) self.input_block = init_container(parent=self.main_page, vertical=True, style=None) self.instruction_block = init_container(parent=self.main_page, vertical=False, style="background-color: white;", size=config.instruction_block_size) # -------------------- third class -------------------- # 1. Input block # 1-1. Interval last # 1-2. Repeats # 1-3. Classes # 1-4. Subject name # 1-5. Training data directory # 1-6. Buttons + help self.interval_last_block, self.interval_slider_view = init_slider_bar_box(self.input_block, label=config.operation_interval_label, max_value=config.recording_interval) self.repeats_block, self.repeat_slider_view = init_slider_bar_box(self.input_block, label=config.operation_repeats_label, max_value=config.repeat_times) self.classes_block, self.classes_textbox = init_inputBox(self.input_block, label=config.operation_classes_label, label_bold=False, default_input=config.indexPen_classes_default) self.subject_name_block, self.subject_names_textbox = init_inputBox(self.input_block, label=config.operation_subject_name_label, label_bold=False, default_input= config.indexPen_subjectName_default) self.training_dir_block, self.training_dir_textbox = init_inputBox(self.input_block, label=config.trainingDataPath_label, label_bold=False, default_input= config.indexPen_trainingDataDir_default) # -------------------- fourth class -------------------- # 1-6. Buttons + help (horizontally distributed) # 1-6-1. Buttons # 1-6-2. Help (message box) self.buttons_block = init_container(self.input_block, vertical=False) self.help_block = init_container(self.input_block) # -------------------- fifth class -------------------- # 1-6-1. Buttons # 1-6-1-1. Interrupt # 1-6-1-2. Start/end test # 1-6-1-3. Start Recording self.interrupt_btn = init_button(parent=self.buttons_block, label=config.interrupt_btn_label, function=self.interrupt_btn_action) self.test_btn = init_button(parent=self.buttons_block, label=config.test_btn_start_label, function=self.test_btn_action) self.recording_btn = init_button(parent=self.buttons_block, label=config.record_btn_start_label, function=self.recording_btn_action) self.help_btn = init_button(parent=self.buttons_block, label=config.help_btn_label, function=help_btn_action) # -------------------- third class -------------------- # 1. Instruction block (horizontal) # 1-1. circles block (vertical) # 1-2. text block (vertical) self.counter_block = init_container(parent=self.instruction_block, vertical=True, size=config.counter_block_size) self.ist_text_block = init_container(parent=self.instruction_block, vertical=True, size=config.ist_text_block_size) # -------------------- fourth class -------------------- # 1-1. circles block (vertical) # 1-1-1. circles_view # 1-1-1-1. circles_scene # 1-1-1-1. 4 circles drawn to the scene self.metronome_scene = QGraphicsScene() self.metronome_view = QGraphicsView(self.metronome_scene) # positions of the four circles # stored for redraw self.x1, self.x2, self.x3, self.x4, self.y1, self.y2, self.y3, self.y4, self.circle_scene_width, \ self.circle_scene_height = self.setup_canvas() # show the circles self.paint(first_circle_colored=False) # -------------------- fourth class -------------------- # 1-2. text block (vertical) # ------- preparation ------- # 1-1-1. "You will be writing: " # char_set ::= A sequence of text the user will write # "Press Enter To Continue" # # ------- forecast ------ # 1-1-1. Label1: Forecast # # ------- record ------ # 1-1-1. Label1: "Write" # character to write # "...next" + next character to write # will be initialized when the user presses enter/return after preparation self.countdown_block, self.countdown_label = None, None # will be initialized when the forecast animation is over self.lb_char_to_write, self.lb_char_next = None, None self.show() # ============================= others ========================== # get input values self.interval = self.interval_slider_view.slider.value() self.repeat_times = self.repeat_slider_view.slider.value() # stored in a list self.classes = self.get_classes() self.subject_name = self.get_subject_name() self.training_dir = self.get_training_data_dir() self.char_set = generate_char_set(self.classes, self.repeat_times) # ======================= indicators, counters ========================== self.state = ['idle'] # see the docstring of self.update_state for details # tracking if the user pressed the return key to start recording self.is_dir_valid = False self.cur_countdown, self.tempo_counter = 0, 0 self.reset_instruction() # =========================== timers ============================= self.timer = QtCore.QTimer() self.timer.setTimerType(QtCore.Qt.PreciseTimer) self.timer.setInterval(self.interval * 1000) self.timer.timeout.connect(self.ticks) self.timer.start() # self.count = 0 # self.start_time = time.time() def update_state(self, action): """ update the current state based on action The working states, as oppose to 'idle' include that of 'pending', 'testing', 'countingDown', 'writing' @param action: str: issued with the following functions with the corresponding value: * self.keyPressEvent(): 'enter_pressed' * self.countdown_tick(): 'countdown_over' * self.test_btn_action(): 'start_test' * self.update_state: 'countdown_over' @@for restarting writing when in test mode @note: you will see that there's a slight pause at the start of writing and the instruction says writing '...', this is an expected behavior as we are not updating the states in a clock, but rather posting to the state changes in function class. It's not a bug, it's a feature! """ if action == 'test_pressed': if 'idle' in self.state: # start the test mode self.idle_to_pending() self.state = ['testing', 'pending'] else: # back to idle self.update_state('interrupt') # this is equivalent to issuing an interrupt action # break pending state and start count down elif action == 'enter_pressed': if 'pending' in self.state: self.state.remove('pending') self.state.append('countingDown') self.pending_to_countdown() elif action == 'countdown_over': if 'countingDown' in self.state: # countingDown may not be in the states if looping in test mode self.state.remove('countingDown') self.state.append('writing') self.countdown_to_writing() elif action == 'writing_over': self.state.remove('writing') if 'testing' in self.state: # restart writing if in test mode self.update_state('countdown_over') elif '': pass # TODO implement writing over when in recording mode else: raise Exception('Unknown State change') elif action == 'interrupt': self.working_to_idle() # working includes that self.state = ['idle'] else: raise Exception('Unknown State change') self.resolve_state() def resolve_state(self): if 'testing' in self.state: self.test_btn.setText(config.test_btn_end_label) self.recording_btn.setDisabled(True) else: self.test_btn.setText(config.test_btn_start_label) self.recording_btn.setDisabled(False) def idle_to_pending(self): self.get_experiment_config() self.char_set = generate_char_set(self.classes, self.repeat_times) init_preparation_block(parent=self.ist_text_block, text=self.char_set) def working_to_idle(self): self.reset_instruction() def pending_to_countdown(self): # clear the preparation text block self.reset_instruction() # create the forecast block self.countdown_block, self.countdown_label = init_countdown_block(self.ist_text_block, label=" ", font=36, bold=True) def countdown_to_writing(self): clear_layout(self.ist_text_block) self.reset_instruction() self.lb_char_to_write, self.lb_char_next = init_instruction_text_block(self.ist_text_block) def keyPressEvent(self, key_event): print(key_event) if is_enter_key_event(key_event): self.update_state('enter_pressed') @pg.QtCore.pyqtSlot() def ticks(self): """ check the current state ticks every 'refresh' milliseconds """ # duration = time.time() - self.start_time # self.count += 1 if 'pending' in self.state: pass elif 'countingDown' in self.state: self.countdown_tick() elif 'writing' in self.state: self.metronome_tick() pass @pg.QtCore.pyqtSlot() def countdown_tick(self): # after the text block shows all countdown texts, stop updating, do nothing and return if self.cur_countdown == len(config.countdown_animation_text): self.cur_countdown += 1 return # wait for a given interval and start the input timer elif self.cur_countdown > len(config.countdown_animation_text): # end of counting down self.update_state('countdown_over') else: self.countdown_label.setText(config.countdown_animation_text[self.cur_countdown]) self.cur_countdown += 1 def metronome_tick(self): # tempo: dah, dih, dih,dih self.repaint(circle=self.tempo_counter % 4 + 1) if not self.tempo_counter % 4: dah() char_count = int(self.tempo_counter / 4) if char_count < len(self.char_set): # draw a new one cur_char = self.char_set[char_count] next_char = 'no Next' if (char_count + 1) == len(self.char_set) else self.char_set[char_count + 1] self.lb_char_to_write.setText(cur_char) self.lb_char_next.setText(config.instruction_next_text + next_char) # finish a recording loop else: self.update_state('writing_over') # must return here to avoid further incrementing the tempo counter, it is reset within update_state() return else: dih() self.tempo_counter += 1 def setup_canvas(self): self.counter_block.addWidget(self.metronome_view) self.metronome_view.resize(config.unit_size, config.WINDOW_HEIGHT / 3) position = self.metronome_view.pos() self.metronome_scene.setSceneRect(position.x(), position.y(), self.metronome_view.width(), self.metronome_view.height()) # size of the scene width = self.metronome_scene.width() height = self.metronome_scene.height() # positions of circles x1, y1 = position.x() + width / 3, position.y() x2, y2 = position.x() + width / 3, position.y() + 3 * (height / 10) x3, y3 = position.x() + width / 3, position.y() + 6 * (height / 10) x4, y4 = position.x() + width / 3, position.y() + 9 * (height / 10) return x1, x2, x3, x4, y1, y2, y3, y4, width, height def repaint(self, circle=1): x = self.x1 y = self.y1 if circle == 1: # remove all current circles for item in self.metronome_scene.items(): self.metronome_scene.removeItem(item) # paint them light gray self.paint() else: if circle == 2: x = self.x2 y = self.y2 elif circle == 3: x = self.x3 y = self.y3 elif circle == 4: x = self.x4 y = self.y4 # locate the circle circle = self.metronome_scene.itemAt(x, y, QTransform()) # remove the original circle if circle: self.metronome_scene.removeItem(circle) # repaint a blue one pen = QPen(Qt.black, 5, Qt.SolidLine) brush = QBrush(Qt.blue, Qt.SolidPattern) self.metronome_scene.addEllipse(x, y, self.circle_scene_width / 3, self.circle_scene_width / 3, pen, brush) def paint(self, first_circle_colored=False): pen = QPen(Qt.black, 5, Qt.SolidLine) brush = QBrush(Qt.lightGray, Qt.SolidPattern) self.metronome_scene.addEllipse(self.x2, self.y2, self.circle_scene_width / 3, self.circle_scene_width / 3, pen, brush) self.metronome_scene.addEllipse(self.x3, self.y3, self.circle_scene_width / 3, self.circle_scene_width / 3, pen, brush) self.metronome_scene.addEllipse(self.x4, self.y4, self.circle_scene_width / 3, self.circle_scene_width / 3, pen, brush) if first_circle_colored: brush = QBrush(Qt.blue, Qt.SolidPattern) self.metronome_scene.addEllipse(self.x1, self.y1, self.circle_scene_width / 3, self.circle_scene_width / 3, pen, brush) def get_experiment_config(self): self.interval = self.interval_slider_view.slider.value() self.repeat_times = self.repeat_slider_view.slider.value() self.classes = self.get_classes() self.subject_name = self.get_subject_name() self.training_dir = self.get_training_data_dir() def get_training_data_dir(self): _user_input = self.training_dir_textbox.text() if not _user_input: _user_input = config.indexPen_trainingDataDir_default return _user_input def get_subject_name(self): _user_input = self.subject_names_textbox.text() if not _user_input: _user_input = config.indexPen_subjectName_default return _user_input def get_classes(self): _user_input = self.classes_textbox.text() if not _user_input: _user_input = config.indexPen_classes_default # change to a list classes = _user_input.split(" ") return classes def interrupt_btn_action(self): self.update_state('interrupt') def test_btn_action(self): self.update_state('test_pressed') def recording_btn_action(self): # TODO implement this action pass # if self.is_recording: # self.reset() # # # if not recording yet # elif not self.is_recording: # # self.get_experiment_config() # # try starting recording # # check the data path first # self.is_dir_valid = self.check_dir_valid() # # if self.is_dir_valid: # # if valid data path, show preparation page # # start recording # self.is_recording = True # self.prepare() # self.recording_btn.setText(config.record_btn_end_label) # self.countdown_timer.start() # # msg = QMessageBox() # msg.setIcon(QMessageBox.Information) # msg.setText("Recording") # msg.exec() def check_dir_valid(self): print(self.training_dir) if os.path.exists(self.training_dir): return True else: msg = QMessageBox() msg.setIcon(QMessageBox.Information) msg.setText(config.datapath_invalid_message) msg.exec() return False def reset_instruction(self): clear_layout(self.ist_text_block) for item in self.metronome_scene.items(): self.metronome_scene.removeItem(item) self.paint() self.lb_char_next, self.lb_char_to_write = None, None self.cur_countdown, self.tempo_counter = 0, 0
class Example(QWidget): def paintEvent(self, e): self.qp.begin(self) self.draw() self.qp.end() def __init__(self): super().__init__() self.elements = [] """ self.elements: QGraphicsObject[] """ self.scene = QGraphicsScene() self.graphicsView = QGraphicsView(self.scene) hbox = QHBoxLayout() hbox.addWidget(self.graphicsView) # hbox.addWidget(self.wid) vbox = QVBoxLayout() vbox.addStretch(1) vbox.addLayout(hbox) self.setLayout(vbox) self.setGeometry(300, 300, 500, 500) self.setWindowTitle('My first app') font = QFont('Ubuntu', 20, QFont.Normal) self.scene.setFont(font) self.qp = QPainter(self.graphicsView) self.lcd = QLCDNumber(self.graphicsView) self.slider = QSlider(self.graphicsView) self.slider.setOrientation(Qt.Horizontal) self.slider.setGeometry(0, self.graphicsView.height() - 30, self.graphicsView.width(), 30) self.slider.valueChanged.connect(self.changer) self.elements.append(self.scene.addText('@!#')) self.show() def changer(self, e: int): self.lcd.display(e) # self.wid.testDraw(e) # self.graphicsView. font = QFont('Ubuntu', e * 2 + 16, QFont.Bold) self.elements[0].setFont(font) # dynamic change def keyPressEvent(self, event): if event.key() == Qt.Key_Q: exit(0) # print(event.key()) def draw(self): self.graphicsView.setGeometry(0, 0, self.width(), self.height()) self.lcd.move(self.graphicsView.width() - self.lcd.width() - 4, 3) # self.qp.qp.drawLine(0, 0, 100, 200) # self.qp.drawText(80, 80, "@!#") # self.qp.qp.drawArc(50, 50, 20, 20, 100, 4000) # self.qp.qp.drawPie(50, 50, 20, 20, 100, 4000) # self.qp.qp.drawRect(1,2, self.graphicsView.width() - 4, self.graphicsView.height() - 3) self.slider.setGeometry(0, self.graphicsView.height() - 30, self.graphicsView.width(), 30)
# Show the scene # First the view widget gets the event, which sends it to the scene # The scene sends the event to the item in focus view = QGraphicsView(scene) view.setBackgroundBrush(QBrush(QImage("./res/images/background.png"))) view.setAttribute(Qt.WA_DeleteOnClose) view.setViewport(QGLWidget()) view.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) view.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) view.setFixedSize(800, 600) scene.setSceneRect(0, 0, 800, 600) # set the end condition health.dead.connect(functools.partial(gameOver, app, view, scene)) # set the player position player.setPos(view.width() / 2, view.height() - player.pixmap().height()) # play the background music url = QUrl.fromLocalFile("./res/sounds/background.wav") media = M.QMediaContent(url) playlist = M.QMediaPlaylist() playlist.addMedia(media) playlist.setPlaybackMode(M.QMediaPlaylist.Loop) music = M.QMediaPlayer() music.setPlaylist(playlist) music.setVolume(10) music.play() view.show() sys.exit(app.exec_())
class BattleView(QObject): def __init__(self, battle_window, parent=None): super().__init__(parent) self.battleWindow = battle_window # MainBattleWindow container_widget if len(self.battleWindow.config.errors) != 0: # noinspection PyArgumentList QMessageBox.critical(battle_window, 'Configuration Error', self.battleWindow.config.get_error_str()) exit(-1) # main elements self.centralWidget = QWidget(self.battleWindow) self.gridLayout = QGridLayout(self.centralWidget) # misc side elements self.graphicsView_coatOfArm = CustomScene() self.graphicsView_currentUnit = CustomScene() self.graphicsView_targetedUnit = CustomScene() for button in self.graphicsView_coatOfArm, self.graphicsView_currentUnit, self.graphicsView_targetedUnit: button.enter_functions.append(self.set_label_hint) button.leave_functions.append(self.clear_label_hint) # buttons self.autoCombatButton = CustomButton(self.centralWidget) self.helpButton = CustomButton(self.centralWidget) self.retreatButton = CustomButton(self.centralWidget) self.endUnitTurnButton = CustomButton(self.centralWidget) self.nextTargetButton = CustomButton(self.centralWidget) for button in self.autoCombatButton, self.helpButton, self.retreatButton, self.nextTargetButton, self.endUnitTurnButton: button.enter_functions.append(self.set_label_hint) button.leave_functions.append(self.clear_label_hint) button.click_functions.append(self.click_button) # info containers self.dateLabel = QLabel(self.centralWidget) # display current turn in battle self.hintLabel = QLabel(self.centralWidget) # display hint when hovering over an elemend # the actual battle scene self.mainScene = MainQGraphicsScene() self.graphicsView_main = QGraphicsView(self.mainScene) self.gridLayout.addWidget(self.graphicsView_main, 1, 0, 12, 1) def setup_ui(self): self.battleWindow.setWindowTitle(self.battleWindow.config.get_text('battle.window.title') + ' v' + str(self.battleWindow.config.version)) background = self.battleWindow.config.theme_selected.get_background_pixmap() palette = QPalette() palette.setBrush(QPalette.Background, QBrush(background)) self.battleWindow.setMinimumSize(constants.get_min_resolution_qsize()) self.battleWindow.setAutoFillBackground(True) self.gridLayout.setVerticalSpacing(0) self.setup_hint_label() # Labels self.setup_turn_label() # Labels self.setup_space() # Space item self.setup_help_button() # Help Push Button self.setup_next_target_button() # Next Target Button self.setup_end_unit_button() # End Unit Button self.setup_retreat_button() # Retreat Button self.setup_auto_combat_button() # Automatic battle button self.setup_targeted_unit_view() # Targeted Unit view self.setup_current_unit_view() # Current Unit View self.setup_coat_of_arms_view() # Coat of Arm view self.setup_map() # Main view self.battleWindow.setPalette(palette) self.battleWindow.setCentralWidget(self.centralWidget) # noinspection PyArgumentList QMetaObject.connectSlotsByName(self.battleWindow) def setup_map(self): self.mainScene = MainQGraphicsScene() self.graphicsView_main.setScene(self.mainScene) self.mainScene.set_battle_view(self.battleView) width = 2 * self.graphicsView_main.height() / math.sqrt(3) height = self.graphicsView_main.height() if width > self.graphicsView_main.width(): width = self.graphicsView_main.width() height = self.graphicsView_main.width() * math.sqrt(3) / 2 item = self.mainScene.addRect(0, 0, width - 15, height - 15) item.hide() self.battleView.draw_battle_map(self.mainScene) def resize_event(self): self.setup_map() # misc elements def setup_hint_label(self): size_policy = constants.default_size_policy(self.hintLabel, QSizePolicy.Preferred, QSizePolicy.Fixed) self.hintLabel.setSizePolicy(size_policy) self.hintLabel.setFont(constants.default_font()) self.hintLabel.setAlignment(Qt.AlignRight | Qt.AlignTrailing | Qt.AlignVCenter) self.gridLayout.addWidget(self.hintLabel, 0, 0, 1, 1) def setup_turn_label(self): size_policy = constants.default_size_policy(self.dateLabel, QSizePolicy.Preferred, QSizePolicy.Fixed) self.dateLabel.setSizePolicy(size_policy) self.dateLabel.setFont(constants.default_font()) self.dateLabel.setText('Turn ' + str(self.battleView.turn)) self.dateLabel.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) self.gridLayout.addWidget(self.dateLabel, 0, 0, 1, 1) def setup_space(self): # Space between help Button and flag view spacer_item = QSpacerItem(20, 10, QSizePolicy.Minimum, QSizePolicy.MinimumExpanding) self.gridLayout.addItem(spacer_item, 2, 1, 1, 1) # Space between flag view and next target Button spacer_item1 = QSpacerItem(20, 10, QSizePolicy.Minimum, QSizePolicy.MinimumExpanding) self.gridLayout.addItem(spacer_item1, 4, 1, 1, 1) # Space between retreat Button and targetted unit view spacer_item2 = QSpacerItem(20, 10, QSizePolicy.Minimum, QSizePolicy.Fixed) self.gridLayout.addItem(spacer_item2, 8, 1, 1, 1) # Space between current unit view and auto Button spacer_item3 = QSpacerItem(20, 10, QSizePolicy.Minimum, QSizePolicy.MinimumExpanding) self.gridLayout.addItem(spacer_item3, 11, 1, 1, 1) def setup_coat_of_arms_view(self): size = QSize(90, 120) self.battleView.draw_coat_of_arms(self.graphicsView_coatOfArm.scene(), size) self.graphicsView_coatOfArm.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) size_policy = constants.default_size_policy(self.graphicsView_coatOfArm, QSizePolicy.Fixed, QSizePolicy.Fixed) self.graphicsView_coatOfArm.setSizePolicy(size_policy) self.graphicsView_coatOfArm.setMinimumSize(size) self.graphicsView_coatOfArm.setMaximumSize(size) self.graphicsView_coatOfArm.setStyleSheet("border-style: none;background: transparent") self.graphicsView_coatOfArm.setCacheMode(QGraphicsView.CacheBackground) self.gridLayout.addWidget(self.graphicsView_coatOfArm, 3, 1, 1, 1) # unit views def setup_targeted_unit_view(self): size = QSize(60, 60) army = self.get_computer_army() defending = (army == self.battleView.defender) self.battleView.draw_targetted_unit(defending, self.graphicsView_targetedUnit.scene(), size) size_policy = constants.default_size_policy(self.graphicsView_targetedUnit, QSizePolicy.Fixed, QSizePolicy.Fixed) self.graphicsView_targetedUnit.setSizePolicy(size_policy) self.graphicsView_targetedUnit.setMinimumSize(size) self.graphicsView_targetedUnit.setMaximumSize(size) self.gridLayout.addWidget(self.graphicsView_targetedUnit, 9, 1, 1, 1, Qt.AlignCenter) def setup_current_unit_view(self): size = QSize(60, 60) army = self.get_human_army() defending = (army == self.battleView.defender) self.battleView.draw_current_unit(defending, self.graphicsView_currentUnit.scene(), size) size_policy = constants.default_size_policy(self.graphicsView_currentUnit, QSizePolicy.Fixed, QSizePolicy.Fixed) self.graphicsView_currentUnit.setSizePolicy(size_policy) self.graphicsView_currentUnit.setMinimumSize(size) self.graphicsView_currentUnit.setMaximumSize(size) self.gridLayout.addWidget(self.graphicsView_currentUnit, 10, 1, 1, 1, Qt.AlignCenter) def get_human_army(self): if self.battleView.attacker.nation.computer: return self.battleView.defender return self.battleView.attacker def get_computer_army(self): if self.battleView.attacker.nation.computer: return self.battleView.attacker return self.battleView.defender # buttons def setup_next_target_button(self): size_policy = constants.default_size_policy(self.nextTargetButton, QSizePolicy.Fixed, QSizePolicy.Fixed) self.nextTargetButton.setSizePolicy(size_policy) self.nextTargetButton.setMinimumSize(QSize(45, 45)) self.nextTargetButton.setMaximumSize(QSize(45, 45)) self.nextTargetButton.setText("") icon = QIcon() icon.addPixmap(QPixmap(self.battleWindow.config.theme_selected.get_target_button_pixmap()), QIcon.Normal, QIcon.Off) self.nextTargetButton.setIcon(icon) self.nextTargetButton.setIconSize(QSize(40, 40)) self.gridLayout.addWidget(self.nextTargetButton, 5, 1, 1, 1, Qt.AlignCenter) def setup_end_unit_button(self): size_policy = constants.default_size_policy(self.endUnitTurnButton, QSizePolicy.Fixed, QSizePolicy.Fixed) self.endUnitTurnButton.setSizePolicy(size_policy) self.endUnitTurnButton.setMinimumSize(QSize(45, 45)) self.endUnitTurnButton.setMaximumSize(QSize(45, 45)) self.endUnitTurnButton.setText("") icon1 = QIcon() icon1.addPixmap(self.battleWindow.config.theme_selected.get_end_button_pixmap(), QIcon.Normal, QIcon.Off) self.endUnitTurnButton.setIcon(icon1) self.endUnitTurnButton.setIconSize(QSize(40, 40)) self.gridLayout.addWidget(self.endUnitTurnButton, 6, 1, 1, 1, Qt.AlignCenter) def setup_retreat_button(self): size_policy = constants.default_size_policy(self.retreatButton, QSizePolicy.Fixed, QSizePolicy.Fixed) self.retreatButton.setSizePolicy(size_policy) self.retreatButton.setMinimumSize(QSize(45, 45)) self.retreatButton.setMaximumSize(QSize(45, 45)) self.retreatButton.setToolTip("") self.retreatButton.setWhatsThis("") self.retreatButton.setText("") icon2 = QIcon() icon2.addPixmap(QPixmap(self.battleWindow.config.theme_selected.get_retreat_button_pixmap()), QIcon.Normal, QIcon.Off) self.retreatButton.setIcon(icon2) self.retreatButton.setIconSize(QSize(42, 40)) self.gridLayout.addWidget(self.retreatButton, 7, 1, 1, 1, Qt.AlignCenter) def setup_help_button(self): size_policy = constants.default_size_policy(self.helpButton, QSizePolicy.Fixed, QSizePolicy.Fixed) self.helpButton.setSizePolicy(size_policy) self.helpButton.setMinimumSize(QSize(80, 80)) self.helpButton.setMaximumSize(QSize(80, 80)) self.helpButton.setText("") icon3 = QIcon() icon3.addPixmap(QPixmap(self.battleWindow.config.theme_selected.get_help_button_pixmap()), QIcon.Normal, QIcon.Off) self.helpButton.setIcon(icon3) self.helpButton.setIconSize(QSize(75, 75)) self.gridLayout.addWidget(self.helpButton, 0, 1, 2, 1) def setup_auto_combat_button(self): size_policy = constants.default_size_policy(self.autoCombatButton, QSizePolicy.Fixed, QSizePolicy.Fixed) self.autoCombatButton.setSizePolicy(size_policy) self.autoCombatButton.setMinimumSize(QSize(90, 90)) self.autoCombatButton.setMaximumSize(QSize(90, 90)) self.autoCombatButton.setText("") icon4 = QIcon() icon4.addPixmap(QPixmap(self.battleWindow.config.theme_selected.get_autocombat_button_pixmap()), QIcon.Normal, QIcon.Off) self.autoCombatButton.setIcon(icon4) self.autoCombatButton.setIconSize(QSize(80, 80)) self.gridLayout.addWidget(self.autoCombatButton, 12, 1, 1, 1) # element interactions def clear_label_hint(self, generic_element): self.hintLabel.setText('') def set_label_hint(self, generic_element): text = '' if generic_element in self.battleView.map.fields: # TODO - not hooked up text = str(generic_element) elif generic_element == self.graphicsView_currentUnit: text = str(self.battleView.currentUnit) elif generic_element == self.graphicsView_targetedUnit: text = str(self.battleView.targettedUnit) elif generic_element == self.autoCombatButton: text = self.battleWindow.config.get_text('auto.play.label') elif generic_element == self.helpButton: text = self.battleWindow.config.get_text('help.tacticalbattle.label') elif generic_element == self.retreatButton: text = self.battleWindow.config.get_text('retreat.all.label') elif generic_element == self.endUnitTurnButton: text = self.battleWindow.config.get_text('end.unit.label') elif generic_element == self.nextTargetButton: text = self.battleWindow.config.get_text('next.target.label') if text != '': self.hintLabel.setText(text) def click_button(self, button_element): if button_element == self.autoCombatButton: self.battleView.autoCombat = True elif button_element == self.helpButton: print('click helpButton') elif button_element == self.retreatButton: self.get_human_army().retreat = True elif button_element == self.endUnitTurnButton: print('click endUnitTurnButton') elif button_element == self.nextTargetButton: print('click nextTargetButton')
class QCliWidget(QWidget): interpreter = Interpreter() display_widget = None vkbd = None beamer = None result_from_queue = False set_tab_text = pyqtSignal(str) def __init__(self): super().__init__() self.unicode_fonts = UnicodeFonts() self.grid = QGridLayout() self.grid.setContentsMargins(0, 0, 0, 6) self.setLayout(self.grid) self.display_widget = QTextEditEnhanced() self.display_widget.setText( "type in the command 'man' down in the command line for getting started ..." ) self.display_widget.setReadOnly(True) self.addDisplayWidget() line = QInputLine() line.setPlaceholderText( "This is the command line. See 'man commandline' for details.") line.return_pressed.connect(self.commandEntered) self.grid.addWidget(line, 1, 0) vkbdButton = QPushButton(self) vkbdButton.clicked.connect(partial(self.vkbdButtonClicked, line)) vkbdButton.setIcon(QIcon.fromTheme('input-keyboard')) self.grid.addWidget(vkbdButton, 1, 1) zoomOutButton = QPushButton(self) zoomOutButton.setIcon(QIcon.fromTheme('zoom-out')) zoomOutButton.clicked.connect(self.onZoomOutClicked) self.grid.addWidget(zoomOutButton, 1, 2) zoomResetButton = QPushButton(self) zoomResetButton.setIcon(QIcon.fromTheme('zoom-original')) zoomResetButton.clicked.connect(self.onZoomResetClicked) self.grid.addWidget(zoomResetButton, 1, 3) zoomInButton = QPushButton(self) zoomInButton.setIcon(QIcon.fromTheme('zoom-in')) zoomInButton.clicked.connect(self.onZoomInClicked) self.grid.addWidget(zoomInButton, 1, 4) self.applyStylesheet() def applyStylesheet(self): config = ConfigFile(None, None) path = config.readVar('global', 'stylesheet') stylesheet = '' try: with open(path) as css: for line in css: stylesheet += line self.display_widget.setStyleSheet(stylesheet) except FileNotFoundError: pass def addDisplayWidget(self): self.view = QGraphicsView() self.scene = QGraphicsScene() self.scene.addWidget(self.display_widget) self.view.setScene(self.scene) self.view.setStyleSheet("QGraphicsView { border-style: none; }") self.grid.addWidget(self.view, 0, 0, 1, 0) self.resizeDisplayWidget() self.applyStylesheet() def resizeDisplayWidget(self): # the magick numbers are for keeping the size of the view allways small enough not to spawn an outer set of scrollbars: x = self.view.width() - 2.1 y = self.view.height() - 2.1 self.x, self.y = x, y mapped_rect = self.view.mapToScene(QRect(0, 0, x, y)).boundingRect() self.display_widget.setFixedSize(mapped_rect.width(), mapped_rect.height()) self.scene.setSceneRect(0, 0, mapped_rect.width(), mapped_rect.height()) def resizeEvent(self, event): self.resizeDisplayWidget() def vkbdButtonClicked(self, lineEdit): self.vkbd = QVirtualKeyboardWindow() self.vkbd.setLineEdit(lineEdit) def commandEntered(self, command): # to keep the display_widget in the correct size self.resize(self.x, self.y) print("command:", command) if '|' in command: command, pipe = command.split('|') self.handleCommand(command) pipe = pipe.strip() if pipe == 'beamer': if self.beamer: self.beamer.destroy() print('destroyed!!!') self.beamer = QBeamerWindow() from PyQt5.QtWidgets import QLabel, QPushButton widget = QLabel('blaaaa') self.beamer.setWidget(self.display_widget) #self.beamer.setText('test') self.beamer.routeToScreen() self.beamer.showFullScreen() else: #self.handleCommand(command) self.set_tab_text.emit(command) #self.activityIndicator() q = queue.Queue() self.interpreter_thread = HandleCommandThread(command, q) self.interpreter_thread.processResult.connect(self.processResult) self.interpreter_thread.clearDisplayWidget.connect( self.clearDisplayWidget) self.interpreter_thread.makeSnapshot.connect(self.makeSnapshot) self.interpreter_thread.stopQueueListener.connect( self.stopQueueListener) self.interpreter_thread.start() self.queue_thread = GetQueueItemsThread(q) self.queue_thread.processQueueItem.connect(self.processQueueItem) self.queue_thread.start() def stopQueueListener(self): self.queue_thread.stop() def processQueueItem(self, item): self.result_from_queue = True item = item.getItem() json_dict = json.loads(item) if json_dict['category'] == 'progressbar': last_type = type(self.display_widget) if not last_type == QProgressBar: self.display_widget.deleteLater() self.display_widget = QProgressBar() self.display_widget.setMinimum(json_dict['minimum']) self.display_widget.setMaximum(json_dict['maximum']) self.display_widget.setValue(json_dict['value']) if not last_type == QProgressBar: self.addDisplayWidget() else: result_object = Result() result_object.payload = item.getItem() self.resultInTextEdit(result_object) def processResult(self, result): if self.result_from_queue: self.result_from_queue = False else: #if result is None: #self.showErrorMessage('no result found') if hasattr(result, 'payload') and result.payload: if hasattr(result, 'category') and result.category == "table": try: result.payload[0] except IndexError: pass # datastructure does not fit to display type 'table' else: self.resultInTable(result) elif hasattr( result, 'category') and result.category == "multimedia_table": self.resultInMultimediaTable(result) elif hasattr(result, 'category') and result.category == "list": self.resultInTextEdit(result) elif hasattr(result, 'category') and result.category == "text": self.resultInTextEdit(result) elif hasattr(result, 'category') and result.category == "string": self.resultInTextEdit(result) elif hasattr(result, 'category') and result.category == "itemized": self.resultInItemizedWidget(result) elif hasattr(result, 'category') and result.category == "image": self.resultInImageWidget(result) elif hasattr(result, 'category') and result.category == "html": #self.resultInHTMLWidget(result) self.resultInTextEdit(result) elif hasattr(result, 'category') and result.category == 'diagram': self.resultInDiagram(result) elif hasattr(result, 'category') and result.category == 'bloodline': self.resultInBloodlineDiagram(result) elif hasattr(result, 'category') and result.category == 'command': self.showMapWidget() elif hasattr(result, 'error') and result.error: self.showErrorMessage(result.error) else: result = Result() result.payload = 'empty result set' self.resultInTextEdit(result) def activityIndicator(self): self.display_widget.deleteLater() label = QLabel() movie = QMovie('./assets/images/activity_indicator.gif') movie.start() label.setMovie(movie) self.display_widget = QWidget() layout = QVBoxLayout() self.display_widget.setLayout(layout) layout.addWidget(label, Qt.AlignCenter) self.addDisplayWidget() def clearDisplayWidget(self): self.display_widget.deleteLater() self.display_widget = QTextEditEnhanced() self.display_widget.setReadOnly(True) self.addDisplayWidget() def makeSnapshot(self): image = QImage(self.display_widget.size(), QImage.Format_ARGB32) painter = QPainter(image) if painter.isActive(): self.render(painter) painter.end() default_dir = path.join(path.expanduser('~')) filename = QFileDialog.getSaveFileName(self, 'Save Snapshot', default_dir) image.save(filename[0]) def resultInTable(self, result): self.display_widget.deleteLater() self.display_widget = QTableWidget() self.display_widget.setRowCount(len(result.payload)) self.display_widget.setColumnCount(len(result.payload[0])) try: self.display_widget.setHorizontalHeaderLabels(result.header) except TypeError: pass try: self.display_widget.setVerticalHeaderLabels(result.header_left) except TypeError: pass for row, line in enumerate(result.payload): for column, item in enumerate(line): table_item = QTableWidgetItem(str(item)) table_item.setFlags(Qt.ItemIsEnabled) self.unicode_fonts.applyFontToQWidget(str(item), table_item) self.display_widget.setItem(row, column, table_item) self.display_widget.resizeColumnsToContents() self.addDisplayWidget() def resultInMultimediaTable(self, result): self.display_widget.deleteLater() max_length = 0 for line in result.payload: if len(line) > max_length: max_length = len(line) self.display_widget = QTableWidget() self.display_widget.setRowCount(len(result.payload)) self.display_widget.setColumnCount(max_length) audio_count = 0 config = ConfigFile(None, None) deckpath = config.readPath("vocable", "deckpath") for row, line in enumerate(result.payload): deckname = line[0] for column, item in enumerate(line): if self.isImage(str(item)): pixmap = QPixmap() pixmap.load(path.join(deckpath, deckname, str(item))) pixmap = pixmap.scaled(QSize(60, 30), Qt.KeepAspectRatio) image_widget = QLabel() image_widget.setPixmap(pixmap) self.display_widget.setCellWidget(row, column, image_widget) elif self.isAudio(str(item)): splitted = item.split(',') if audio_count < len(splitted): audio_count = len(splitted) audio_widget = QAudioItems(path.join(deckpath, deckname), self.display_widget, 7, max_length) audio_widget.appendPlayButtonsList(splitted, row) else: table_item = QTableWidgetItem(str(item)) table_item.setFlags(Qt.ItemIsEnabled) #self.unicode_fonts.applyFontToQWidget(str(item), table_item) self.display_widget.setItem(row, column, table_item) self.display_widget.setColumnCount(max_length + audio_count) self.display_widget.resizeColumnsToContents() self.addDisplayWidget() def resultInTextEdit(self, result): self.display_widget.deleteLater() self.display_widget = QTextEditEnhanced() self.unicode_fonts.applyFontAndSizeToQWidget(result.toString(), self.display_widget) self.display_widget.setAcceptRichText(True) self.display_widget.setText(result.toString()) self.display_widget.setReadOnly(True) self.display_widget.setTextInteractionFlags( self.display_widget.textInteractionFlags() | Qt.TextSelectableByKeyboard) self.addDisplayWidget() def resultInHTMLWidget(self, result): self.display_widget.deleteLater() self.display_widget = QWebView() self.display_widget.setHtml(result.payload) self.addDisplayWidget() def resultInItemizedWidget(self, result): self.display_widget.deleteLater() self.display_widget = QItemizedWidget(result.payload) self.addDisplayWidget() def resultInImageWidget(self, result): self.display_widget.deleteLater() self.display_widget = QCustomizedGraphicsView() import PIL if type(result.payload) == PIL.Image.Image: from PIL.ImageQt import ImageQt qimage = ImageQt(result.payload) pixmap = QPixmap.fromImage(qimage) #pixmap = QPixmap("/tmp/tmprp3q0gi9.PNG") #pixmap.fromImage(image) item = self.display_widget.scene().addPixmap(pixmap) item.setPos(0, 0) self.addDisplayWidget() def resultInDiagram(self, result): self.display_widget.deleteLater() curve = QLineSeries() pen = curve.pen() pen.setColor(Qt.red) pen.setWidthF(2) curve.setPen(pen) for data in result.payload: if type(data['y']) == str: data['y'] = 0 curve.append(data['x'], data['y'], 10) chart = QChart() chart.setTitle(result.name) chart.legend().hide() chart.addSeries(curve) chart.createDefaultAxes() view = QChartViewEnhanced(chart) view.setRenderHint(QPainter.Antialiasing) self.display_widget = view self.addDisplayWidget() def resultInBloodlineDiagram(self, result): self.display_widget.deleteLater() self.display_widget = QBloodlineWidget(result.payload) self.addDisplayWidget() def showMapWidget(self): self.display_widget.deleteLater() self.display_widget = QMapWidget() self.display_widget.showPosition() self.addDisplayWidget() def showErrorMessage(self, message): self.display_widget.deleteLater() self.display_widget = QTextEditEnhanced() self.display_widget.setText(message) self.display_widget.setReadOnly(True) self.addDisplayWidget() def onZoomInClicked(self): if type(self.display_widget) == QTextEditEnhanced: self.display_widget.zoomIn() elif type(self.display_widget) == QChartViewEnhanced: self.display_widget.chart().zoomIn() else: self.view.scale(SCALE_FACTOR, SCALE_FACTOR) self.resizeDisplayWidget() def onZoomOutClicked(self): if type(self.display_widget) == QTextEditEnhanced: self.display_widget.zoomOut() elif type(self.display_widget) == QChartViewEnhanced: self.display_widget.chart().zoomOut() else: self.view.scale(1 / SCALE_FACTOR, 1 / SCALE_FACTOR) self.resizeDisplayWidget() def onZoomResetClicked(self): if type(self.display_widget) == QTextEditEnhanced: self.display_widget.zoomReset() elif type(self.display_widget) == QChartViewEnhanced: self.display_widget.chart().zoomReset() else: self.view.resetTransform() self.resizeDisplayWidget() def keyPressEvent(self, event): if (event.modifiers() & Qt.ControlModifier): if event.key() == Qt.Key_Plus: self.onZoomInClicked() elif event.key() == Qt.Key_Minus: self.onZoomOutClicked() def isImage(self, data): suffixes = ['.png', '.jpg', '.jpe', '.jpeg', '.svg', '.bmp'] for suffix in suffixes: if data.lower().endswith(suffix): return True return False def isAudio(self, data): suffixes = ['.ogg', '.wav', '.mp3', '.aiff', '.wma'] for suffix in suffixes: if data.lower().endswith(suffix): return True return False
class ViewWindow(QMainWindow): # QWidget): def __init__(self): super().__init__() self.pilorig = None self.savedImg = None self.controlPanel = None self.dirName, self.fileName = '', '' self.dirFileNames = [] self.fileIdx = -1 self.ctrl = None # transformation control widget self.locator = None # locator rectangle widget self.locator1 = None # locator 1st point self.locator2 = None # locator 2nd point self.scale = (1, 1) self.show_histogram = False # usage of QGraphicsScene and QGraphicsView is taken from # https://stackoverflow.com/questions/50851587/undo-functionality-for-qpainter-drawellipse-function self.gv = None self.scene = None self.scaledPixmap = None self.histogram = [] self.initUI() def initUI(self): self.setWindowTitle("PyQT Tuts!") transforms.editWindow = self bar = self.menuBar() makeMenu(bar, FILE_MENU, self) menu = bar.actions()[2].menu() menu.addSeparator() addAction(menu, self, 'Show &Histogram', self.toggleHistogram, 'Ctrl+H', 'Show/hide histogram') menu = bar.actions()[1].menu() menu.addSeparator() for item in transforms.getTransforms(): addAction(menu, self, item[0], item[2], item[3], item[4]) # item[1] (Icon is ignored, todo: add support) menu = bar.actions()[0].menu() menu.addSeparator() addAction(menu, self, '&Next', self.onNextBtn, 'Ctrl+N', 'Next image') addAction(menu, self, '&Prev', self.onPrevBtn, 'Ctrl+P', 'Prev image') addAction(menu, self, '&Save', self.onSaveImg, 'Ctrl+S', 'Save image') layout1 = QVBoxLayout() self.gv = QGraphicsView() self.scene = QGraphicsScene() self.gv.setScene(self.scene) self.gv.installEventFilter(self) layout1.addWidget(self.gv) panel = QWidget(self) self.controlPanel = QHBoxLayout() panel.setLayout(self.controlPanel) layout1.addWidget(panel) center = QWidget() center.setLayout(layout1) self.setCentralWidget(center) def toggleHistogram(self): self.show_histogram = not self.show_histogram self.make_histogram() def eventFilter(self, obj, event): if obj == self.gv and event.type() == QEvent.MouseButtonPress: p = self.gv.mapToScene(event.pos()) self.setLocation(p) return QWidget.eventFilter(self, obj, event) def setLocation(self, pos): if self.locator2 is not None: self.locator1 = None self.locator2 = None if self.locator1: self.locator2 = (pos.x(), pos.y()) self.drawLocator() else: self.locator1 = (pos.x(), pos.y()) def drawLocator(self): if self.locator: self.scene.removeItem(self.locator) self.locator = None pen = QPen(Qt.red, 3) self.locator = self.scene.addRect(self.locator1[0], self.locator1[1], self.locator2[0] - self.locator1[0], self.locator2[1] - self.locator1[1], pen) print('locator', self.locator1, self.locator2) self.gv.update() # self.label.update() #QApplication.processEvents() def resizeEvent(self, event): QWidget.resizeEvent(self, event) self.sizeImage() def openImage(self, fileName): self.setWindowTitle(fileName) self.dirName = os.path.dirname(fileName) self.fileName = os.path.basename(fileName) self.dirFileNames = list(imgFiles(self.dirName)) self.fileIdx = self.dirFileNames.index(self.fileName) if fileName: self.pilorig = PIL.Image.open(fileName) self.sizeImage() def fullFileName(self): if self.fileName: return os.path.join(self.dirName, self.fileName) else: return None def showImage(self, fileName): self.openImage(fileName) self.show() def updateImage(self, pilImage): self.pilorig = pilImage self.sizeImage() def sizeImage(self): orig = pil2pixmap(self.pilorig) if self.pilorig: if self.scaledPixmap: self.scene.removeItem(self.scaledPixmap) self.scaledPixmap = None if self.locator: self.scene.removeItem(self.locator) self.locator = None pixmap = orig.scaled(self.gv.width(), self.gv.height(), Qt.KeepAspectRatio, transformMode=Qt.SmoothTransformation) self.scaledPixmap = self.scene.addPixmap(pixmap) self.scale = (orig.size().width() / pixmap.size().width(), orig.size().height() / pixmap.size().height()) self.make_histogram() def absLocatorRect(self): return [ self.locator1[0] * self.scale[0], self.locator1[1] * self.scale[1], self.locator2[0] * self.scale[0], self.locator2[1] * self.scale[1] ] def nextFileName(self): if self.fileIdx < len(self.dirFileNames) - 1: return os.path.join(self.dirName, self.dirFileNames[self.fileIdx + 1]) else: return None def prevFileName(self): if self.fileIdx > 0: return os.path.join(self.dirName, self.dirFileNames[self.fileIdx - 1]) else: return None def onNextBtn(self): fn = self.nextFileName() if fn: self.openImage(os.path.join(self.dirName, fn)) #@staticmethod def onPrevBtn(self): fn = self.prevFileName() if fn: self.openImage(os.path.join(self.dirName, fn)) def onSaveImg(self): options = QFileDialog.Options() options |= QFileDialog.DontUseNativeDialog fileName, _ = QFileDialog.getSaveFileName( self, "Save as ...", os.path.join(self.dirName, self.fileName), "All Files (*);;Jpeg Files(*.jpg)", options=options) if fileName: print(fileName) self.pilorig.save(fileName) def make_histogram(self): # should it be a ShowWin class method? #self.canvas.delete('histogram') for it in self.histogram: self.scene.removeItem(it) del self.histogram[:] if not self.show_histogram: return img = self.pilorig if not img: return h = img.convert("L").histogram() maxVal = 1 for i in range(0, len(h)): if h[i] > maxVal: maxVal = h[i] _X = float(img.size[1]) x = 100 if _X > 100 else _X penGray = QPen(Qt.gray, 3) penRed = QPen(Qt.red, 3) for i in range(0, len(h)): if h[i] == maxVal: pen = penRed else: pen = penGray self.histogram.append( self.scene.addLine(i, x, i, x - x * h[i] / maxVal, pen)) self.histogram.append(self.scene.addRect(0, 0, len(h), x, penGray)) self.gv.update() # support transformation plugins def controlImg(self, checkCtrl=True): if checkCtrl and not self.ctrl: return None else: return self.savedImg def setCtrl(self, ctrl): if ctrl and self.ctrl: return # do not allow two control panels if self.ctrl and not ctrl: self.ctrl.setParent(None) self.ctrl = ctrl if ctrl: self.controlPanel.addWidget(ctrl) self.savedImg = self.pilorig def unsetCtrl(self): if self.ctrl: self.ctrl.setParent(None) self.ctrl = None
class WindowTime(QMainWindow): '''This class handles the main window.''' def __init__(self): super().__init__() self.menubar = self.menuBar() self.status = self.statusBar() exitAction = QAction('Exit', self) exitAction.setShortcut('Ctrl+Q') exitAction.setStatusTip('Exit application') exitAction.triggered.connect(self.close) fileMenu = self.menubar.addMenu('&File') fileMenu.addAction(exitAction) self.zoomlevel = 2 # self.pixmaps = {2: QPixmap('yeg-2.png'), 3: QPixmap('yeg-3.png'), # 4: QPixmap('yeg-4.png'), 5: QPixmap('yeg-5.png'), 6: QPixmap('yeg-6.png')} # # self.sizes = {1: 512, 2: 1024, 3: 2048, 4: 4096, 5: 8192, 6: 16384} self.pixmaps = { 2: QPixmap(os.path.join(__location__, 'yeg-2.png')), 3: QPixmap(os.path.join(__location__, 'yeg-3.png')), 4: QPixmap(os.path.join(__location__, 'yeg-4.png')), 5: QPixmap(os.path.join(__location__, 'yeg-5.png')) } self.sizes = {1: 512, 2: 1024, 3: 2048, 4: 4096, 5: 8192} self.pressed = False self.start = 0 self.dest = 0 self.center = (0, 0) self.howmanycars = 0 self.customer_id = 0 self.initUI() self.show() def initUI(self): #The QToolTip class provides tool tips (balloon help) for any widget. QToolTip.setFont(QFont('SansSerif', 10)) w = QWidget() #The QGridLayout class lays out widgets in a grid. grid = QGridLayout() #setLayout(self, Qlayout) Sets the layout manager for this widget to layout. #The QLayout argument has it's ownership transferred to Qt. w.setLayout(grid) #The QLabel widget provides a text or image display. labelZoom = QLabel('Zoom here pls') labelPassengers = QLabel('How many Passengers') #The QPushButton widget provides a command button. Takes in arguments #For text label btnZoomIn = QPushButton('+') btnZoomIn.setToolTip('Zoom In') btnZoomIn.clicked.connect(self.zoomIn) btnZoomOut = QPushButton('-') btnZoomOut.setToolTip('Zoom Out') btnZoomOut.clicked.connect(self.zoomOut) spinBox = QSpinBox() spinBox.setMaximum(5) spinBox.setMinimum(1) self.mapScene = GraphicsScene() self.mapScene.setSceneRect(0, 0, self.sizes[self.zoomlevel], self.sizes[self.zoomlevel]) self.mapScene.addPixmap(self.pixmaps[self.zoomlevel]) #ellipse = mapScene.addEllipse(50,100,50,50) self.mapView = QGraphicsView() self.mapView.setScene(self.mapScene) #Set it so user can drag map via cursor self.mapView.setDragMode(QGraphicsView.ScrollHandDrag) #Hide the scroll bar self.mapView.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.mapView.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) grid.addWidget(labelZoom, 0, 4) grid.addWidget(self.mapView, 0, 0, 4, 4) grid.addWidget(btnZoomIn, 1, 4) grid.addWidget(btnZoomOut, 2, 4) grid.addWidget(labelPassengers, 3, 4) grid.addWidget(spinBox, 4, 4) #How everything will look on the screen self.setGeometry(300, 300, 800, 600) self.setWindowTitle('Uber Pool') self.setCentralWidget(w) #CHANGED: This def setCenter(self): center = self.mapView.mapToScene(self.mapView.width() // 2, self.mapView.height() // 2) self.center = (ConversionFunctions.x_to_longitude( self.zoomlevel, center.x()), ConversionFunctions.y_to_latitude( self.zoomlevel, center.y())) def zoomIn(self): if self.zoomlevel < 5: self.pressed = False self.setCenter() self.zoomlevel += 1 self.updateSceneZoom() def zoomOut(self): if self.zoomlevel > 2: self.pressed = False self.setCenter() self.zoomlevel -= 1 self.updateSceneZoom() #updates the scence once the zoom button has been pressed. The scene is #updated on the center of the last scene def updateSceneZoom(self): self.mapScene.clear() self.mapScene.addPixmap(self.pixmaps[self.zoomlevel]) self.mapScene.setSceneRect(0, 0, self.sizes[self.zoomlevel], self.sizes[self.zoomlevel]) (x, y) = (ConversionFunctions.longitude_to_x(self.zoomlevel, self.center[0]), ConversionFunctions.latitude_to_y(self.zoomlevel, self.center[1])) self.mapView.centerOn(x, y) #returns the x,y position of the cursor on the map def handleClick(self, pos): return (pos.x(), pos.y()) # #Grab the x,y coords # (x, y) = (pos.x(), pos.y()) # #Convert them into lat,lon # lon = x_to_longitude(self.zoomlevel, x) # lat = y_to_latitude(self.zoomlevel, y) # # #Determine whether start location has already been decided # if self.pressed == False: # self.start = Vertex(lat, lon) # self.pressed = True # self.drawBubble(self.start) # else: # #Once dest has been decided, find shortest path and draw it # self.dest = Vertex(lat, lon) # self.pressed = False # self.drawBubble(self.dest) # self.controller.passRequest(self.start, self.dest, 1) def drawCar(self): #Draws the map in place self.setCenter() self.mapScene.clear() self.mapScene.addPixmap(self.pixmaps[self.zoomlevel]) self.mapScene.setSceneRect(0, 0, self.sizes[self.zoomlevel], self.sizes[self.zoomlevel]) (lat, lon) = self.center x = ConversionFunctions.longitude_to_x(self.zoomlevel, lon) y = ConversionFunctions.latitude_to_y(self.zoomlevel, lat) self.mapView.centerOn(x, y) #advance_taxi UberTaxi.advance_taxi(taxi_directory, cust_directory, g) for taxi in taxi_directory.values(): #gets coords from vertex lon = server.coordinates[taxi.loc][1] lat = server.coordinates[taxi.loc][0] #stored in lat, lon, and then converted newx = ConversionFunctions.longitude_to_x(self.zoomlevel, lon) newy = ConversionFunctions.latitude_to_y(self.zoomlevel, lat) #draws path and car self.mapScene.addRect(newx, newy, 15, 10) self.mapScene.addEllipse(newx - 2, newy + 10, 6, 6) self.mapScene.addEllipse(newx + 11, newy + 10, 6, 6) self.drawPath(taxi.path) def drawPath(self, path): linePen = QPen() linePen.setWidth(3) #Set the width of the line to be noticeable for i in range(len(path) - 1): lon1 = server.coordinates[path[i]][1] lat1 = server.coordinates[path[i]][0] lon2 = server.coordinates[path[i + 1]][1] lat2 = server.coordinates[path[i + 1]][0] self.mapScene.addLine( ConversionFunctions.longitude_to_x(self.zoomlevel, lon1), ConversionFunctions.latitude_to_y(self.zoomlevel, lat1), ConversionFunctions.longitude_to_x(self.zoomlevel, lon2), ConversionFunctions.latitude_to_y(self.zoomlevel, lat2), linePen)
class MainWindow(QMainWindow): def __init__(self): super(MainWindow, self).__init__() self.lastyear = int(time.strftime('%Y', time.localtime(time.time()))) - 1 self.in_parameters = {u'datetime': str(self.lastyear) + u'年', u'target_area': u'绍兴市', u'density_cell': u'10', u'density_class': 10, u'day_cell': u'15', u'day_class': 10, u'out_type': u'tiff'} self.setupUi() def setupUi(self): self.setObjectName("MainWindow") self.setFixedSize(1040, 915) sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.sizePolicy().hasHeightForWidth()) self.setSizePolicy(sizePolicy) icon = QIcon() icon.addPixmap(QPixmap('./resource/weather-thunder.png'),QIcon.Normal, QIcon.Off) self.setWindowIcon(icon) self.centralwidget = QWidget(self) sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.centralwidget.sizePolicy().hasHeightForWidth()) self.centralwidget.setSizePolicy(sizePolicy) self.centralwidget.setObjectName("centralwidget") self.layoutWidget = QWidget(self.centralwidget) self.layoutWidget.setGeometry(QRect(32, 10, 979, 851)) self.layoutWidget.setObjectName("layoutWidget") self.verticalLayout_5 =QVBoxLayout(self.layoutWidget) self.verticalLayout_5.setContentsMargins(0, 0, 0, 0) self.verticalLayout_5.setObjectName("verticalLayout_5") self.horizontalLayout = QHBoxLayout() self.horizontalLayout.setObjectName("horizontalLayout") spacerItem = QSpacerItem(300, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.horizontalLayout.addItem(spacerItem) self.datetime_label = QLabel(self.layoutWidget) self.datetime_label.setObjectName("datetime_label") self.horizontalLayout.addWidget(self.datetime_label) self.datetime = QDateEdit(self.layoutWidget) self.datetime.setDateTime(QDateTime(QDate(self.lastyear, 1, 1), QTime(0, 0, 0))) self.datetime.setObjectName("datetime") self.horizontalLayout.addWidget(self.datetime) spacerItem1 = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.horizontalLayout.addItem(spacerItem1) self.target_area_label = QLabel(self.layoutWidget) self.target_area_label.setObjectName("target_area_label") self.horizontalLayout.addWidget(self.target_area_label) self.target_area = QComboBox(self.layoutWidget) self.target_area.setObjectName("target_area") self.target_area.addItem("") self.target_area.addItem("") self.target_area.addItem("") self.target_area.addItem("") self.target_area.addItem("") self.target_area.addItem("") self.horizontalLayout.addWidget(self.target_area) spacerItem2 = QSpacerItem(300, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.horizontalLayout.addItem(spacerItem2) self.verticalLayout_5.addLayout(self.horizontalLayout) self.tabWidget = QTabWidget(self.layoutWidget) sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.tabWidget.sizePolicy().hasHeightForWidth()) self.tabWidget.setSizePolicy(sizePolicy) self.tabWidget.setObjectName("tabWidget") self.density_tab = QWidget() self.density_tab.setObjectName("density_tab") self.verticalLayout_3 =QVBoxLayout(self.density_tab) self.verticalLayout_3.setObjectName("verticalLayout_3") self.verticalLayout_2 =QVBoxLayout() self.verticalLayout_2.setObjectName("verticalLayout_2") self.horizontalLayout_2 = QHBoxLayout() self.horizontalLayout_2.setObjectName("horizontalLayout_2") self.density_cell_label = QLabel(self.density_tab) self.density_cell_label.setObjectName("density_cell_label") self.horizontalLayout_2.addWidget(self.density_cell_label) self.density_cell = QSpinBox(self.density_tab) self.density_cell.setProperty("value", 10) self.density_cell.setObjectName("density_cell") self.horizontalLayout_2.addWidget(self.density_cell) spacerItem3 = QSpacerItem(40, 0, QSizePolicy.Expanding, QSizePolicy.Minimum) self.horizontalLayout_2.addItem(spacerItem3) self.density_class_label = QLabel(self.density_tab) self.density_class_label.setObjectName("density_class_label") self.horizontalLayout_2.addWidget(self.density_class_label) self.density_class = QSpinBox(self.density_tab) self.density_class.setProperty("value", 10) self.density_class.setObjectName("density_class") self.horizontalLayout_2.addWidget(self.density_class) spacerItem4 = QSpacerItem(478, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.horizontalLayout_2.addItem(spacerItem4) self.density_mxd = QPushButton(self.density_tab) self.density_mxd.setObjectName("density_mxd") self.horizontalLayout_2.addWidget(self.density_mxd) self.verticalLayout_2.addLayout(self.horizontalLayout_2) self.density_view = QGraphicsView(self.density_tab) self.density_view.setObjectName("density_view") self.verticalLayout_2.addWidget(self.density_view) self.verticalLayout_3.addLayout(self.verticalLayout_2) self.tabWidget.addTab(self.density_tab, "") self.day_tab = QWidget() self.day_tab.setObjectName("day_tab") self.verticalLayout_4 =QVBoxLayout(self.day_tab) self.verticalLayout_4.setObjectName("verticalLayout_4") self.verticalLayout =QVBoxLayout() self.verticalLayout.setObjectName("verticalLayout") self.horizontalLayout_3 =QHBoxLayout() self.horizontalLayout_3.setObjectName("horizontalLayout_3") self.day_cell_label = QLabel(self.day_tab) sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.day_cell_label.sizePolicy().hasHeightForWidth()) self.day_cell_label.setSizePolicy(sizePolicy) self.day_cell_label.setObjectName("day_cell_label") self.horizontalLayout_3.addWidget(self.day_cell_label) self.day_cell = QSpinBox(self.day_tab) self.day_cell.setProperty("value", 15) self.day_cell.setObjectName("day_cell") self.horizontalLayout_3.addWidget(self.day_cell) spacerItem5 = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.horizontalLayout_3.addItem(spacerItem5) self.day_class_label = QLabel(self.day_tab) self.day_class_label.setObjectName("day_class_label") self.horizontalLayout_3.addWidget(self.day_class_label) self.day_class = QSpinBox(self.day_tab) self.day_class.setProperty("value", 10) self.day_class.setObjectName("day_class") self.horizontalLayout_3.addWidget(self.day_class) spacerItem6 = QSpacerItem(478, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.horizontalLayout_3.addItem(spacerItem6) self.day_mxd = QPushButton(self.day_tab) self.day_mxd.setObjectName("day_mxd") self.horizontalLayout_3.addWidget(self.day_mxd) self.verticalLayout.addLayout(self.horizontalLayout_3) self.day_view = QGraphicsView(self.day_tab) self.day_view.setObjectName("day_view") self.verticalLayout.addWidget(self.day_view) self.verticalLayout_4.addLayout(self.verticalLayout) self.tabWidget.addTab(self.day_tab, "") self.verticalLayout_5.addWidget(self.tabWidget) self.horizontalLayout_4 =QHBoxLayout() self.horizontalLayout_4.setObjectName("horizontalLayout_4") self.progressBar = QProgressBar(self.layoutWidget) sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.progressBar.sizePolicy().hasHeightForWidth()) self.progressBar.setSizePolicy(sizePolicy) self.progressBar.setProperty("value", 0) self.progressBar.setObjectName("progressBar") self.horizontalLayout_4.addWidget(self.progressBar) self.execute_button = QPushButton(self.layoutWidget) sizePolicy = QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.execute_button.sizePolicy().hasHeightForWidth()) self.execute_button.setSizePolicy(sizePolicy) self.execute_button.setObjectName("execute_button") self.horizontalLayout_4.addWidget(self.execute_button) self.verticalLayout_5.addLayout(self.horizontalLayout_4) self.setCentralWidget(self.centralwidget) self.menubar = QMenuBar(self) self.menubar.setGeometry(QRect(0, 0, 1040, 26)) self.menubar.setObjectName("menubar") self.file_menu = QMenu(self.menubar) self.file_menu.setObjectName("file_menu") self.help_menu = QMenu(self.menubar) self.help_menu.setObjectName("help_menu") self.setMenuBar(self.menubar) self.statusbar = QStatusBar(self) self.statusbar.setObjectName("statusbar") self.setStatusBar(self.statusbar) self.action_add_data = QAction(self) self.action_add_data.setObjectName("action_add_data") self.action_help = QAction(self) self.action_help.setObjectName("action_help") self.action_about = QAction(self) self.action_about.setObjectName("action_about") self.action_save_pic = QAction(self) self.action_save_pic.setObjectName("action_save_pic") self.file_menu.addAction(self.action_add_data) self.file_menu.addAction(self.action_save_pic) self.help_menu.addAction(self.action_help) self.help_menu.addAction(self.action_about) self.menubar.addAction(self.file_menu.menuAction()) self.menubar.addAction(self.help_menu.menuAction()) self.retranslateUi() self.tabWidget.setCurrentIndex(0) QMetaObject.connectSlotsByName(self) self.center() self.show() self.target_area.activated[str].connect(self.updateTargetArea) self.datetime.dateChanged.connect(self.updateDatetime) self.density_cell.valueChanged.connect(self.updateDensityCell) self.density_class.valueChanged.connect(self.updateDensityClass) self.day_cell.valueChanged.connect(self.updateDayCell) self.day_class.valueChanged.connect(self.updateDayClass) self.action_add_data.triggered.connect(self.addData) self.action_save_pic.triggered.connect(self.savePic) self.action_about.triggered.connect(self.showAbout) self.action_help.triggered.connect(self.showHelp) self.execute_button.clicked.connect(self.execute) self.density_mxd.clicked.connect(self.openMxdDensity) self.day_mxd.clicked.connect(self.openMxdDay) self.density_mxd.setDisabled(True) self.day_mxd.setDisabled(True) self.action_save_pic.setDisabled(True) def execute(self): dir = u"E:/Documents/工作/雷电公报/闪电定位原始文本数据/" + self.in_parameters[u'datetime'] if os.path.exists(dir): datafiles = os.listdir(dir) datafiles = map(lambda x:os.path.join(dir,x),datafiles) self.in_parameters[u'origin_data_path'] = datafiles if not self.in_parameters.has_key(u'origin_data_path'): message = u"请加载%s的数据" % self.in_parameters[u'datetime'] msgBox = QMessageBox() msgBox.setText(message) msgBox.setIcon(QMessageBox.Information) icon = QIcon() icon.addPixmap(QPixmap('./resource/weather-thunder.png'), QIcon.Normal, QIcon.Off) msgBox.setWindowIcon(icon) msgBox.setWindowTitle(" ") msgBox.exec_() return self.execute_button.setDisabled(True) self.execute_button.setText(u'正在制图中……') self.progressBar.setMaximum(0) self.progressBar.setMinimum(0) self.action_add_data.setDisabled(True) self.target_area.setDisabled(True) self.datetime.setDisabled(True) self.density_cell.setDisabled(True) self.density_class.setDisabled(True) self.day_cell.setDisabled(True) self.day_class.setDisabled(True) # for outfile in self.in_parameters[u'origin_data_path']: # infile = # try: # with open(infile, 'w+') as in_f: # for line in in_f: # line = line.replace(u":",":") # in_f.write(line) # except Exception,inst: # print infile self.process_thread = WorkThread() self.process_thread.trigger.connect(self.finished) self.process_thread.beginRun(self.in_parameters) def finished(self): #绘制闪电密度图 ##清除上一次的QGraphicsView对象,防止其记录上一次图片结果,影响显示效果 self.density_view.setAttribute(Qt.WA_DeleteOnClose) self.verticalLayout_2.removeWidget(self.density_view) size = self.density_view.size() self.density_view.close() self.density_view = QGraphicsView(self.density_tab) self.density_view.setObjectName("density_view") self.density_view.resize(size) self.verticalLayout_2.addWidget(self.density_view) densityPic = ''.join([cwd,u'/bulletinTemp/', self.in_parameters[u'datetime'],u'/',self.in_parameters[u'datetime'], self.in_parameters[u'target_area'],u'闪电密度空间分布.tif']) scene = QGraphicsScene() pixmap_density = QPixmap(densityPic) scene.addPixmap(pixmap_density) self.density_view.setScene(scene) scale = float(self.density_view.width()) / pixmap_density.width() self.density_view.scale(scale, scale) #绘制雷暴日图 self.day_view.setAttribute(Qt.WA_DeleteOnClose) self.verticalLayout.removeWidget(self.day_view) size = self.day_view.size() self.day_view.close() self.day_view = QGraphicsView(self.day_tab) self.day_view.setObjectName("day_view") self.day_view.resize(size) self.verticalLayout.addWidget(self.day_view) dayPic = ''.join([cwd,u'/bulletinTemp/', self.in_parameters[u'datetime'],u'/',self.in_parameters[u'datetime'], self.in_parameters[u'target_area'],u'地闪雷暴日空间分布.tif']) pixmap_day = QPixmap(dayPic) scene = QGraphicsScene() scene.addPixmap(pixmap_day) self.day_view.resize(self.density_view.width(),self.density_view.height()) self.day_view.setScene(scene) scale = float(self.day_view.width()) / pixmap_day.width() self.day_view.scale(scale, scale) #处理进度条和执行按钮状态 self.progressBar.setMinimum(0) self.progressBar.setMaximum(100) self.progressBar.setValue(100) self.progressBar.setFormat(u'完成!') self.execute_button.setDisabled(False) self.execute_button.setText(u'执行') #改变一些控件的状态 self.action_add_data.setDisabled(False) self.target_area.setDisabled(False) self.datetime.setDisabled(False) self.density_cell.setDisabled(False) self.density_class.setDisabled(False) self.day_cell.setDisabled(False) self.day_class.setDisabled(False) self.density_mxd.setDisabled(False) self.day_mxd.setDisabled(False) self.action_save_pic.setDisabled(False) def addData(self): fnames = QFileDialog.getOpenFileNames(self, u'请选择原始的电闪数据', u'E:/Documents/工作/雷电公报/闪电定位原始文本数据', 'Text files (*.txt);;All(*.*)') self.in_parameters[u'origin_data_path'] = fnames[0] def savePic(self): densityPic = ''.join([cwd,u'/bulletinTemp/',self.in_parameters[u'datetime'],u'/', self.in_parameters[u'target_area'],'.gdb',u'/',self.in_parameters[u'datetime'], self.in_parameters[u'target_area'],u'闪电密度空间分布.tif']) dayPic = ''.join([cwd,u'/bulletinTemp/',self.in_parameters[u'datetime'],u'/', self.in_parameters[u'target_area'],'.gdb',u'/',self.in_parameters[u'datetime'], self.in_parameters[u'target_area'],u'地闪雷暴日空间分布.tif']) directory = QFileDialog.getExistingDirectory(self,u'请选择图片保存位置', u'E:/Documents/工作/雷电公报', QFileDialog.ShowDirsOnly|QFileDialog.DontResolveSymlinks) dest_density = os.path.join(directory,os.path.basename(densityPic)) dest_day = os.path.join(directory,os.path.basename(dayPic)) if os.path.isfile(dest_day) or os.path.isfile(dest_density): message = u"文件已经存在!" msgBox = QMessageBox() msgBox.setText(message) msgBox.setIcon(QMessageBox.Information) icon = QIcon() icon.addPixmap(QPixmap("./resource/weather-thunder.png"), QIcon.Normal, QIcon.Off) msgBox.setWindowIcon(icon) msgBox.setWindowTitle(" ") msgBox.exec_() return move(dayPic,directory) move(densityPic,directory) def openMxdDay(self): program = u'C:/Program Files (x86)/ArcGIS/Desktop10.3/bin/ArcMap.exe' src_dir = ''.join([cwd,u'/data/LightningBulletin.gdb']) dest_dir = ''.join([cwd,u"/bulletinTemp/",self.in_parameters[u'datetime'], u"/" , self.in_parameters[u'target_area']]) src_file = ''.join([self.in_parameters[u'target_area'] , u"地闪雷暴日空间分布模板.mxd"]) copy(os.path.join(src_dir,src_file),dest_dir) arguments = [os.path.join(dest_dir,src_file)] self.process = QProcess(self) self.process.start(program,arguments) def openMxdDensity(self): program = u'C:/Program Files (x86)/ArcGIS/Desktop10.3/bin/ArcMap.exe' src_dir = ''.join([cwd,u'/data/LightningBulletin.gdb']) dest_dir = ''.join([cwd,u"/bulletinTemp/",self.in_parameters[u'datetime'], u"/" , self.in_parameters[u'target_area']]) src_file = ''.join([self.in_parameters[u'target_area'] ,u"闪电密度空间分布模板.mxd"]) copy(os.path.join(src_dir,src_file),dest_dir) arguments = [os.path.join(dest_dir,src_file)] self.process = QProcess(self) self.process.start(program,arguments) def showAbout(self): self.about = About_Dialog() def showHelp(self): program = u'C:/Windows/hh.exe' arguments = [''.join([cwd,'/help/help.CHM'])] self.process = QProcess(self) self.process.start(program,arguments) def updateTargetArea(self, area): self.in_parameters[u'target_area'] = area def updateDatetime(self, date): self.in_parameters[u'datetime'] = str(date.year()) + u'年' if self.in_parameters.has_key(u'origin_data_path'): self.in_parameters.__delitem__(u'origin_data_path') def updateDensityCell(self, cell): self.in_parameters[u'density_cell'] = str(cell) def updateDensityClass(self, nclass): self.in_parameters[u'density_class'] = nclass def updateDayCell(self, cell): self.in_parameters[u'day_cell'] = str(cell) def updateDayClass(self, nclass): self.in_parameters[u'day_class'] = nclass def center(self): qr = self.frameGeometry() cp = QDesktopWidget().availableGeometry().center() qr.moveCenter(cp) self.move(qr.topLeft()) def retranslateUi(self): _translate = QCoreApplication.translate self.setWindowTitle(_translate("MainWindow", "绍兴防雷中心 雷电公报制图")) self.datetime_label.setText(_translate("MainWindow", "年份")) self.datetime.setDisplayFormat(_translate("MainWindow", "yyyy")) self.target_area_label.setText(_translate("MainWindow", "地区")) self.target_area.setItemText(0, _translate("MainWindow", "绍兴市")) self.target_area.setItemText(1, _translate("MainWindow", "柯桥区")) self.target_area.setItemText(2, _translate("MainWindow", "上虞区")) self.target_area.setItemText(3, _translate("MainWindow", "诸暨市")) self.target_area.setItemText(4, _translate("MainWindow", "嵊州市")) self.target_area.setItemText(5, _translate("MainWindow", "新昌县")) self.density_cell_label.setText(_translate("MainWindow", "插值网格大小")) self.density_class_label.setText(_translate("MainWindow", "制图分类数目")) self.density_mxd.setText(_translate("MainWindow", "ArcGIS文档")) self.tabWidget.setTabText(self.tabWidget.indexOf(self.density_tab), _translate("MainWindow", "电闪密度")) self.day_cell_label.setText(_translate("MainWindow", "插值网格大小")) self.day_class_label.setText(_translate("MainWindow", "制图分类数目")) self.day_mxd.setText(_translate("MainWindow", "ArcGIS文档")) self.tabWidget.setTabText(self.tabWidget.indexOf(self.day_tab), _translate("MainWindow", "雷暴日")) self.execute_button.setText(_translate("MainWindow", "执行")) self.file_menu.setTitle(_translate("MainWindow", "文件")) self.help_menu.setTitle(_translate("MainWindow", "帮助")) self.action_add_data.setText(_translate("MainWindow", "加载数据")) self.action_help.setText(_translate("MainWindow", "使用说明")) self.action_about.setText(_translate("MainWindow", "关于")) self.action_save_pic.setText(_translate("MainWindow", "图片另存为"))