def addMovementAnimation(self, animGroup): # print(">>MoveAnim") for phIdx in self.photoIdxsToMove: item = self.photosInGrid[phIdx] anim = QPropertyAnimation(item.pixmap, "pos") anim.setDuration(self.moveDuration - item.gridCol * self.moveModifier) anim.setEasingCurve(QEasingCurve.Linear) startCoords = self.getCellTLCoords(item.gridRow, item.gridCol) endCoords = self.getCellTLCoords(item.gridRow, item.gridCol + self.columnMovementDist) anim.setStartValue(startCoords) anim.setEndValue(endCoords) animGroup.addAnimation(anim)
class MoveSymbol(QUndoCommand): ''' Undo/Redo command for moving symbols ''' def __init__(self, symbol_id, old_pos, new_pos, animate=False): super(MoveSymbol, self).__init__() self.setText('Move symbol') self.symbol = symbol_id self.old_pos = old_pos self.new_pos = new_pos if animate: self.animation = QPropertyAnimation(self.symbol, "position") self.animation.setDuration(500) self.animation.setStartValue(self.old_pos) self.animation.setEndValue(self.new_pos) self.animation.setEasingCurve(QEasingCurve.OutCirc) def undo(self): ''' Undo a symbol move ''' self.symbol.position = self.old_pos try: self.symbol.decisionParent.updateConnectionPointPosition() except AttributeError: pass def redo(self): ''' Apply a symbol move ''' try: self.animation.start() except AttributeError: self.symbol.position = self.new_pos try: self.symbol.decisionParent.updateConnectionPointPosition() except AttributeError: pass
def createPositionAnimation(self, item, duration): ani = QPropertyAnimation(item, b'pos', self) ani.setDuration(duration) ani.setStartValue(item.pos()) width = self.squareWidth * 7 ani.setEndValue(QPointF(width - item.x(), width - item.y())) return ani
def createAnimation(self, target, index): '''创建动画''' # 暂停动画一 PauseAnimation1 = QPauseAnimation(target) PauseAnimation1.setDuration(150 * index) # 并行动画组一 # #透明度动画一 OpacityAnimation1 = QPropertyAnimation(target, b"opacity") OpacityAnimation1.setDuration(400) OpacityAnimation1.setStartValue(0) OpacityAnimation1.setEndValue(1) # #移动动画一 MoveAnimation1 = _MoveAnimation(target, self.parent, self.easing) MoveAnimation1.setMoveType(_MoveAnimation.MOVE1) MoveAnimation1.setDuration(400) MoveAnimation1.setStartValue(QPoint(0, 0)) MoveAnimation1.setEndValue(QPoint(self.parent.width() / 4.0, 0)) # 添加到并行动画里面 ParallelAnimation1 = QParallelAnimationGroup() ParallelAnimation1.addAnimation(OpacityAnimation1) ParallelAnimation1.addAnimation(MoveAnimation1) # 移动动画二 MoveAnimation2 = _MoveAnimation(target, self.parent, self.easing) MoveAnimation2.setMoveType(_MoveAnimation.MOVE2) MoveAnimation2.setDuration(2000) MoveAnimation2.setEndValue(QPoint((self.parent.width() / 4.0) * 3.0, 0)) # 并行动画组二 # #透明度动画二 OpacityAnimation2 = QPropertyAnimation(target, b"opacity") OpacityAnimation2.setDuration(400) OpacityAnimation2.setStartValue(1) OpacityAnimation2.setEndValue(0) # #移动动画三 MoveAnimation3 = _MoveAnimation(target, self.parent, self.easing) MoveAnimation3.setMoveType(_MoveAnimation.MOVE3) MoveAnimation3.setDuration(400) MoveAnimation3.setEndValue(QPoint(self.parent.width(), 0)) # 添加到并行动画里面 ParallelAnimation2 = QParallelAnimationGroup() ParallelAnimation2.addAnimation(OpacityAnimation2) ParallelAnimation2.addAnimation(MoveAnimation3) # 暂停动画二 PauseAnimation2 = QPauseAnimation(target) PauseAnimation2.setDuration(150 * (5 - index - 1)) # 串行动画组 self.setLoopCount(-1) # 无限循环 self.addAnimation(PauseAnimation1) self.addAnimation(ParallelAnimation1) self.addAnimation(MoveAnimation2) self.addAnimation(ParallelAnimation2) self.addAnimation(PauseAnimation2)
def __init__(self): super(Robot, self).__init__() self.setFlag(self.ItemHasNoContents) self.torsoItem = RobotTorso(self) self.headItem = RobotHead(self.torsoItem) self.upperLeftArmItem = RobotLimb(self.torsoItem) self.lowerLeftArmItem = RobotLimb(self.upperLeftArmItem) self.upperRightArmItem = RobotLimb(self.torsoItem) self.lowerRightArmItem = RobotLimb(self.upperRightArmItem) self.upperRightLegItem = RobotLimb(self.torsoItem) self.lowerRightLegItem = RobotLimb(self.upperRightLegItem) self.upperLeftLegItem = RobotLimb(self.torsoItem) self.lowerLeftLegItem = RobotLimb(self.upperLeftLegItem) settings = ( # Item Position Rotation Scale # x y start end (self.headItem, 0, -18, 20, -20, 1.1), (self.upperLeftArmItem, -15, -10, 190, 180, 0), (self.lowerLeftArmItem, 30, 0, 50, 10, 0), (self.upperRightArmItem, 15, -10, 300, 310, 0), (self.lowerRightArmItem, 30, 0, 0, -70, 0), (self.upperRightLegItem, 10, 32, 40, 120, 0), (self.lowerRightLegItem, 30, 0, 10, 50, 0), (self.upperLeftLegItem, -10, 32, 150, 80, 0), (self.lowerLeftLegItem, 30, 0, 70, 10, 0), (self.torsoItem, 0, 0, 5, -20, 0), ) animation = QParallelAnimationGroup(self) for item, pos_x, pos_y, start_rot, end_rot, scale in settings: item.setPos(pos_x, pos_y) rot_animation = QPropertyAnimation(item, b"rotation") rot_animation.setStartValue(start_rot) rot_animation.setEndValue(end_rot) rot_animation.setEasingCurve(QEasingCurve.SineCurve) rot_animation.setDuration(2000) animation.addAnimation(rot_animation) if scale > 0: scale_animation = QPropertyAnimation(item, b"scale") scale_animation.setEndValue(scale) scale_animation.setEasingCurve(QEasingCurve.SineCurve) scale_animation.setDuration(2000) animation.addAnimation(scale_animation) animation.setLoopCount(-1) animation.start()
class CircleObstruction(QColorThemedGraphicsObject): """ Useful for notifications, I...guess? """ def get_thickness(self): return self._thickness def set_thickness(self,c): self._thickness = c self.update() thickness = pyqtProperty(float, get_thickness, set_thickness) def __init__(self, sz, thickness, parent=None): super(CircleObstruction, self).__init__(parent) self._sz = sz self._thickness = thickness self._color = Qt.blue def boundingRect(self): return QRectF(-self._thickness, -self._thickness, self._sz + 2*self._thickness, self._sz + 2*self._thickness) def paint(self, painter, option, widget): # painter.setPen(QPen(self._color, # self._thickness)) painter.setBrush(self._color) painter.setPen(Qt.NoPen) painter.drawEllipse(QRectF( self._sz/2.0 - self._thickness, self._sz/2.0 - self._thickness, 2*self._thickness, 2*self._thickness, )) def show_anim(self): self.anim = QPropertyAnimation(self, "thickness") self.anim.setDuration(2000) self.anim.setStartValue(self.get_thickness()) self.anim.setEndValue(50.0) self.anim.setEasingCurve(QEasingCurve.OutElastic) self.anim.start() def hide_anim(self): self.anim = QPropertyAnimation(self, "thickness") self.anim.setDuration(500) self.anim.setStartValue(self.get_thickness()) self.anim.setEndValue(0.0) self.anim.setEasingCurve(QEasingCurve.InBack) self.anim.start()
class NotifyWidget(QWidget): def __init__(self): super().__init__() self.layout = QVBoxLayout(self) self.sub_widget = _NotifySubWidget(self) self.layout.addWidget(self.sub_widget) self.layout.setContentsMargins(0, 0, 0, 0) self._exit_shortcut = QShortcut(QKeySequence(Qt.Key_Escape), self) self._exit_shortcut.activated.connect(self.close) self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint | Qt.Tool) self.setAttribute(Qt.WA_TranslucentBackground) self.setAttribute(Qt.WA_MacAlwaysShowToolWindow) self.resize(width, height) self.move(QApplication.desktop().width() - self.width() - 20, 40) self.setLayout(self.layout) self._animation = QPropertyAnimation(self, b'windowOpacity') self._animation.setStartValue(0.8) self._animation.setKeyValueAt(0.4, 1) self._animation.setEndValue(0) self._animation.setDuration(5000) self._animation.finished.connect(self.close) def show(self): super().show() self._animation.start() def show_message(self, title, content, pixmap=None): if not self.isVisible(): self.show() self._animation.stop() self._animation.setCurrentTime(0) self._animation.start() self.sub_widget.set_title(title) self.sub_widget.set_content(content) pixmap = pixmap if pixmap else QPixmap(WINDOW_ICON) self.sub_widget.set_pixmap(pixmap) def enterEvent(self, event): self._animation.setCurrentTime(0)
def animate(self, item, property_name, duration, start_value, end_value): """Summary Args: item (TYPE): Description property_name (TYPE): Description duration (TYPE): Description start_value (TYPE): Description end_value (TYPE): Description """ if item is not None: b_name = property_name.encode('ascii') anim = QPropertyAnimation(item.adapter, b_name) anim.setDuration(duration) anim.setStartValue(start_value) anim.setEndValue(end_value) anim.start() item.adapter.saveRef(property_name, anim)
def addRemovalAnimation(self, animGroup): # print(">>RemoveAnim") for phIdx in self.photoIdxsToRemove: item = self.photosInGrid[phIdx] anim = QPropertyAnimation(item.pixmap, "scale") anim.setDuration(self.shrinkDuration) anim.setEasingCurve(QEasingCurve.Linear) anim.setStartValue(1.0) anim.setEndValue(0.0) animGroup.addAnimation(anim) anim = QPropertyAnimation(item.pixmap, "pos") anim.setDuration(self.shrinkDuration) anim.setEasingCurve(QEasingCurve.Linear) startCoords = self.getCellTLCoords(item.gridRow, item.gridCol) endCoords = QPointF(startCoords.x()+self.cellSize.width()*item.xFactor, startCoords.y() + item.pixmap.pixmapSize.height() / 2) anim.setStartValue(startCoords) anim.setEndValue(endCoords) animGroup.addAnimation(anim)
def addInsertionAnimation(self, animGroup): # Animation for added # print(">>>InsAnim") for ph in self.picItemsToAdd: # Set pixmap start location newPixmap = ph[0].pixmap row = ph[1] col = ph[2] xFact = ph[0].xFactor endCoords = self.getCellTLCoords(row, col) startCoords = QPointF(endCoords.x()-self.cellSize.width()*xFact, endCoords.y()) newPixmap.pixmap_item.setPos(startCoords) newPixmap.pixmap_item.setVisible(True) # Animate in anim = QPropertyAnimation(newPixmap, "pos") anim.setDuration(self.insertDuration) anim.setStartValue(startCoords) anim.setEasingCurve(QEasingCurve.Linear) anim.setEndValue(endCoords) animGroup.addAnimation(anim)
def animate(self, item: QGraphicsItem, property_name: str, duration: int, start_value, end_value): """ Args: item: Description property_name: Description duration: Description start_value (QVariant): Description end_value (QVariant): Description """ b_name = property_name.encode('ascii') anim = item.adapter.getRef(property_name) if anim is None: anim = QPropertyAnimation(item.adapter, b_name) item.adapter.saveRef(property_name, anim) anim.setDuration(duration) anim.setStartValue(start_value) anim.setEndValue(end_value) anim.start()
class ChannelListItem(QWidget): """ This class is responsible for managing the item in the list of channels. The list item supports a fade-in effect, which can be enabled with the should_fade parameter in the constructor. """ def __init__(self, parent, channel, fade_delay=0, should_fade=False): super(QWidget, self).__init__(parent) uic.loadUi('qt_resources/channel_list_item.ui', self) self.channel_name.setText(channel["name"]) self.channel_description_label.setText("Active 6 days ago • %d items" % channel["torrents"]) self.channel_num_subs_label.setText(str(channel["votes"])) if channel["sub"]: self.channel_subscribe_button.setText("✓ subscribed") else: self.channel_subscribe_button.setText("subscribe") if should_fade: self.opacity_effect = QGraphicsOpacityEffect(self) self.opacity_effect.setOpacity(0) self.setGraphicsEffect(self.opacity_effect) self.timer = QTimer() self.timer.setInterval(fade_delay) self.timer.timeout.connect(self.fadeIn) self.timer.start() def fadeIn(self): self.anim = QPropertyAnimation(self.opacity_effect, 'opacity') self.anim.setDuration(800) self.anim.setStartValue(0) self.anim.setEndValue(1) self.anim.start() self.timer.stop()
class FlipWidget(QWidget): Left = 0 # 从右往左 Right = 1 # 从左往右 Scale = 3 # 图片缩放比例 finished = pyqtSignal() def __init__(self, *args, **kwargs): super(FlipWidget, self).__init__(*args, **kwargs) # 无边框无任务栏 self.setWindowFlags(self.windowFlags() | Qt.FramelessWindowHint | Qt.SubWindow) # 背景透明 self.setAttribute(Qt.WA_TranslucentBackground, True) # 翻转角度 self._angle = 0 # 属性动画针对自定义属性`angle` self._animation = QPropertyAnimation(self, b'angle', self) self._animation.setDuration(550) self._animation.setEasingCurve(QEasingCurve.OutInQuad) self._animation.finished.connect(self.finished.emit) @pyqtProperty(int) def angle(self): return self._angle @angle.setter def angle(self, angle): self._angle = angle self.update() def updateImages(self, direction, image1, image2): """设置两张切换图 :param direction: 方向 :param image1: 图片1 :param image2: 图片2 """ self.image1 = image1 self.image2 = image2 self.show() self._angle = 0 # 根据方向设置动画的初始和结束值 if direction == self.Right: self._animation.setStartValue(1) self._animation.setEndValue(-180) elif direction == self.Left: self._animation.setStartValue(1) self._animation.setEndValue(180) self._animation.start() def paintEvent(self, event): super(FlipWidget, self).paintEvent(event) if hasattr(self, 'image1') and hasattr(self, 'image2') and self.isVisible(): painter = QPainter(self) painter.setRenderHint(QPainter.Antialiasing, True) painter.setRenderHint(QPainter.SmoothPixmapTransform, True) # 变换 transform = QTransform() # 把圆心设置为矩形中心 transform.translate(self.width() / 2, self.height() / 2) if self._angle >= -90 and self._angle <= 90: # 当翻转角度在90范围内显示第一张图,且从大图缩放到小图的过程 painter.save() # 设置翻转角度 transform.rotate(self._angle, Qt.YAxis) painter.setTransform(transform) # 缩放图片高度 width = self.image1.width() / 2 height = int(self.image1.height() * (1 - abs(self._angle / self.Scale) / 100)) image = self.image1.scaled(self.image1.width(), height, Qt.IgnoreAspectRatio, Qt.SmoothTransformation) painter.drawPixmap(QPointF(-width, -height / 2), image) painter.restore() else: # 当翻转角度在90范围内显示第二张图,且从小图缩放到原图的过程 painter.save() if self._angle > 0: angle = 180 + self._angle else: angle = self._angle - 180 # 设置翻转角度, 注意这里角度有差异 transform.rotate(angle, Qt.YAxis) painter.setTransform(transform) # 缩放图片高度 width = self.image2.width() / 2 height = int(self.image2.height() * (1 - ((360 - abs(angle)) / self.Scale / 100))) image = self.image2.scaled(self.image2.width(), height, Qt.IgnoreAspectRatio, Qt.SmoothTransformation) painter.drawPixmap(QPointF(-width, -height / 2), image) painter.restore()
class CurrencyCov(QtWidgets.QMainWindow): def __init__(self): super(CurrencyCov, self).__init__() self.ui = Ui_MainWindow() self.ui.setupUi(self) self.init_UI() def init_UI(self): self.ui.input_amount.setValidator(QtGui.QDoubleValidator()) self.setWindowTitle("Конвертер валют") self.setFixedSize(1068, 732) self.ui.convert_slide_btn.clicked.connect(self.convert_page_show) self.ui.history_slide_btn.clicked.connect(self.history_page_show) self.ui.pushButton.clicked.connect(self.slide_bar) self.ui.input_amount.setPlaceholderText("Cума:") self.ui.convert_button.clicked.connect(self.converter) with open("data.txt", "r") as data: for i in data: self.ui.history_listWidget.addItem(i) def slide_bar(self): width = self.ui.left_side_menu.width() if width == 70: newWidth = 220 self.ui.convert_slide_btn.setStyleSheet("padding-left:0;") self.ui.history_slide_btn.setStyleSheet("padding-left:0;") else: newWidth = 70 self.ui.convert_slide_btn.setStyleSheet("padding-left:110;") self.ui.history_slide_btn.setStyleSheet("padding-left:110;") self.animation = QPropertyAnimation(self.ui.left_side_menu, b"minimumWidth") self.animation.setDuration(200) self.animation.setStartValue(width) self.animation.setEndValue(newWidth) self.animation.setEasingCurve(QtCore.QEasingCurve.InOutQuart) self.animation.start() def convert_page_show(self): self.ui.stackedWidget.setCurrentWidget(self.ui.convert_page) def history_page_show(self): self.ui.stackedWidget.setCurrentWidget(self.ui.history_page) def readFile(self): f = open("data.txt", "r") lineList = f.readlines() f.close() self.ui.history_listWidget.addItem(lineList[-1]) def converter(self): c = CurrencyConverter() if self.ui.input_amount.text(): input_amount = float(self.ui.input_amount.text()) input_currency = self.ui.input_currency.currentText() output_currency = self.ui.output_currency.currentText() amount = input_amount = float(self.ui.input_amount.text()) if input_currency != 'USD': input_amount = round(input_amount / currencies[input_currency], 2) output_result = round(input_amount * currencies[output_currency], 2) self.ui.result_label.setText( str(amount) + " " + str(input_currency) + " = " + str(output_result) + " " + str(output_currency)) f = open("data.txt", "a") f.write( str(input_amount) + " " + str(input_currency) + " -> " + str(output_result) + " " + str(output_currency) + "\n") f.close() self.readFile()
class Preferences(QDialog): # Signal to warn that the window is closed settingsClosed = pyqtSignal() def __init__(self, parent=None): super(Preferences, self).__init__(parent) # Main container # This contains a grid main_box = QVBoxLayout(self) main_box.setContentsMargins(200, 50, 200, 100) # The grid contains two containers # left container and right container grid = QGridLayout() # Left Container left_container = QVBoxLayout() left_container.setContentsMargins(0, 0, 0, 0) # General group_gral = QGroupBox(self.tr("General")) box_gral = QVBoxLayout(group_gral) # Updates btn_updates = QPushButton(self.tr("Check for updates")) box_gral.addWidget(btn_updates) # Language group_language = QGroupBox(self.tr("Language")) box = QVBoxLayout(group_language) # Find .qm files in language path available_langs = file_manager.get_files_from_folder( settings.LANGUAGE_PATH) languages = ["English"] + available_langs self._combo_lang = QComboBox() box.addWidget(self._combo_lang) self._combo_lang.addItems(languages) self._combo_lang.currentIndexChanged[int].connect( self._change_lang) if PSetting.LANGUAGE: self._combo_lang.setCurrentText(PSetting.LANGUAGE) box.addWidget(QLabel(self.tr("(Requires restart)"))) # Add widgets left_container.addWidget(group_gral) left_container.addWidget(group_language) left_container.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Expanding)) # Right Container right_container = QVBoxLayout() right_container.setContentsMargins(0, 0, 0, 0) # Editor editor_group = QGroupBox(self.tr("Editor Configurations")) box_editor = QHBoxLayout(editor_group) # Current line self._highlight_current_line = QCheckBox( self.tr("Highlight Current Line")) self._highlight_current_line.setChecked( PSetting.HIGHLIGHT_CURRENT_LINE) self._highlight_current_line.stateChanged[int].connect( self.__current_line_value_changed) box_editor.addWidget(self._highlight_current_line) # Matching paren self._matching_paren = QCheckBox(self.tr("Matching Parenthesis")) self._matching_paren.setChecked( PSetting.MATCHING_PARENTHESIS) self._matching_paren.stateChanged[int].connect( self.__set_enabled_matching_parenthesis) box_editor.addWidget(self._matching_paren) # Font group font_group = QGroupBox(self.tr("Font")) font_grid = QGridLayout(font_group) font_grid.addWidget(QLabel(self.tr("Family")), 0, 0) self._combo_font = QFontComboBox() self._combo_font.setCurrentFont(PSetting.FONT) font_grid.addWidget(self._combo_font, 0, 1) font_grid.addWidget(QLabel(self.tr("Point Size")), 1, 0) self._combo_font_size = QComboBox() fdb = QFontDatabase() combo_sizes = fdb.pointSizes(PSetting.FONT.family()) current_size_index = combo_sizes.index( PSetting.FONT.pointSize()) self._combo_font_size.addItems([str(f) for f in combo_sizes]) self._combo_font_size.setCurrentIndex(current_size_index) font_grid.addWidget(self._combo_font_size, 1, 1) right_container.addWidget(editor_group) right_container.addWidget(font_group) right_container.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Expanding)) # Add widgets grid.addLayout(left_container, 0, 0) grid.addLayout(right_container, 0, 1) main_box.addLayout(grid) # Button close and reset hbox = QHBoxLayout() hbox.setSpacing(20) hbox.addItem(QSpacerItem(1, 0, QSizePolicy.Expanding)) btn_cancel = QPushButton(self.tr("Back")) hbox.addWidget(btn_cancel) btn_reset = QPushButton(self.tr("Reset Configurations")) hbox.addWidget(btn_reset) main_box.addLayout(hbox) # Overlay self.overlay = overlay_widget.OverlayWidget(self) self.overlay.hide() # Effect and animations self.effect = QGraphicsOpacityEffect() self.setGraphicsEffect(self.effect) duration, x = 180, 150 # Animation duration # Animation start # Opacity animation self.opacity_animation_s = QPropertyAnimation(self.effect, b"opacity") self.opacity_animation_s.setDuration(duration) self.opacity_animation_s.setStartValue(0.0) self.opacity_animation_s.setEndValue(1.0) # X animation self.x_animation_s = QPropertyAnimation(self, b"geometry") self.x_animation_s.setDuration(duration) self.x_animation_s.setStartValue(QRect(x, 0, parent.width(), parent.height())) self.x_animation_s.setEndValue(QRect(0, 0, parent.width(), parent.height())) # Animation end # Opacity animation self.opacity_animation_e = QPropertyAnimation(self.effect, b"opacity") self.opacity_animation_e.setDuration(duration) self.opacity_animation_e.setStartValue(1.0) self.opacity_animation_e.setEndValue(0.0) # X animation self.x_animation_e = QPropertyAnimation(self, b"geometry") self.x_animation_e.setDuration(duration) self.x_animation_e.setStartValue(QRect(0, 0, parent.width(), parent.height())) self.x_animation_e.setEndValue(QRect(-x, 0, parent.width(), parent.height())) # Group animation start self.group_animation_s = QParallelAnimationGroup() self.group_animation_s.addAnimation(self.opacity_animation_s) self.group_animation_s.addAnimation(self.x_animation_s) # Group animation end self.group_animation_e = QParallelAnimationGroup() self.group_animation_e.addAnimation(self.opacity_animation_e) self.group_animation_e.addAnimation(self.x_animation_e) # Connections self.group_animation_e.finished.connect( self._on_group_animation_finished) btn_cancel.clicked.connect(self.close) btn_reset.clicked.connect(self._reset_settings) btn_updates.clicked.connect(self._check_for_updates) # self.thread.finished.connect(self._on_thread_finished) self._combo_font.currentFontChanged.connect( self._change_font) self._combo_font_size.currentTextChanged.connect( self._change_font_size) def __current_line_value_changed(self, value): qs = QSettings(settings.SETTINGS_PATH, QSettings.IniFormat) qs.setValue('highlight_current_line', value) PSetting.HIGHLIGHT_CURRENT_LINE = value def __set_enabled_matching_parenthesis(self, value): qs = QSettings(settings.SETTINGS_PATH, QSettings.IniFormat) qs.setValue("matching_parenthesis", value) PSetting.MATCHING_PARENTHESIS = value def _change_font(self, font): # FIXME: un quilombo esto central = Pireal.get_service("central") mcontainer = central.get_active_db() if mcontainer is not None: query_widget = mcontainer.query_container.currentWidget() if query_widget is not None: weditor = query_widget.get_editor() if weditor is not None: qs = QSettings(settings.SETTINGS_PATH, QSettings.IniFormat) weditor.set_font(font) qs.setValue("font", font) def _change_font_size(self, size): # FIXME: un quilombo esto font = self._combo_font.currentFont() font.setPointSize(int(size)) central = Pireal.get_service("central") mcontainer = central.get_active_db() if mcontainer is not None: query_widget = mcontainer.query_container.currentWidget() if query_widget is not None: weditor = query_widget.get_editor() if weditor is not None: qs = QSettings(settings.SETTINGS_PATH, QSettings.IniFormat) weditor.set_font(font) qs.setValue("font", font) def showEvent(self, event): super(Preferences, self).showEvent(event) self.group_animation_s.start() def resizeEvent(self, event): self.overlay.resize(self.size()) event.accept() def done(self, result): self.res = result self.group_animation_e.start() def _on_group_animation_finished(self): super(Preferences, self).done(self.res) self.settingsClosed.emit() def _check_for_updates(self): # Thread self._thread = QThread() self._updater = updater.Updater() self._updater.moveToThread(self._thread) self._thread.started.connect(self._updater.check_updates) self._updater.finished.connect(self.__on_thread_update_finished) # Show overlay widget self.overlay.show() # Start thread self._thread.start() def __on_thread_update_finished(self): # Hide overlay widget self.overlay.hide() self._thread.quit() msg = QMessageBox(self) if not self._updater.error: if self._updater.version: version = self._updater.version msg.setWindowTitle(self.tr("New version available!")) msg.setText(self.tr("Check the web site to " "download <b>Pireal {}</b>".format( version))) download_btn = msg.addButton(self.tr("Download!"), QMessageBox.YesRole) msg.addButton(self.tr("Cancel"), QMessageBox.RejectRole) msg.exec_() r = msg.clickedButton() if r == download_btn: webbrowser.open_new( "http://centaurialpha.github.io/pireal") else: msg.setWindowTitle(self.tr("Information")) msg.setText(self.tr("Last version installed")) msg.addButton(self.tr("Ok"), QMessageBox.AcceptRole) msg.exec_() else: msg.critical(self, self.tr("Error"), self.tr("Connection error")) self._thread.deleteLater() self._updater.deleteLater() def _reset_settings(self): """ Remove all settings """ msg = QMessageBox(self) msg.setWindowTitle(self.tr("Reset Settings")) msg.setText(self.tr("Are you sure you want to clear all settings?")) msg.setIcon(QMessageBox.Question) msg.addButton(self.tr("No"), QMessageBox.NoRole) yes_btn = msg.addButton(self.tr("Yes"), QMessageBox.YesRole) msg.exec_() r = msg.clickedButton() if r == yes_btn: QSettings(settings.SETTINGS_PATH, QSettings.IniFormat).clear() self.close() def _change_lang(self, index): lang = self._combo_lang.itemText(index) qs = QSettings(settings.SETTINGS_PATH, QSettings.IniFormat) qs.setValue('language', lang)
class MiniMap(QPlainTextEdit): def __init__(self, parent): super(MiniMap, self).__init__(parent) self.setWordWrapMode(QTextOption.NoWrap) self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.setReadOnly(True) self.setCenterOnScroll(True) self.setMouseTracking(True) self.viewport().setCursor(Qt.PointingHandCursor) self.setTextInteractionFlags(Qt.NoTextInteraction) self._parent = parent self.highlighter = None self.lines_count = 0 if ACTIVATE_OPACITY: self.goe = QGraphicsOpacityEffect() self.setGraphicsEffect(self.goe) self.goe.setOpacity(settings.MINIMAP_MIN_OPACITY) self.animation = QPropertyAnimation(self.goe, b"opacity") self.slider = SliderArea(self) self.slider.show() def __calculate_max(self): line_height = self._parent.cursorRect().height() if line_height > 0: self.lines_count = self._parent.viewport().height() / line_height self.slider.update_position() self.update_visible_area() def set_code(self, source): self.setPlainText(source) self.__calculate_max() def adjust_to_parent(self): self.setFixedHeight(self._parent.height()) self.setFixedWidth(self._parent.width() * settings.SIZE_PROPORTION) x = self._parent.width() - self.width() self.move(x, 0) fontsize = int(self.width() / settings.MARGIN_LINE) if fontsize < 1: fontsize = 1 font = self.document().defaultFont() font.setPointSize(fontsize) self.setFont(font) self.__calculate_max() def update_visible_area(self): if not self.slider.pressed: line_number = self._parent.firstVisibleBlock().blockNumber() block = self.document().findBlockByLineNumber(line_number) cursor = self.textCursor() cursor.setPosition(block.position()) rect = self.cursorRect(cursor) self.setTextCursor(cursor) self.slider.move_slider(rect.y()) def enterEvent(self, event): if ACTIVATE_OPACITY: self.animation.setDuration(300) self.animation.setStartValue(settings.MINIMAP_MIN_OPACITY) self.animation.setEndValue(settings.MINIMAP_MAX_OPACITY) self.animation.start() def leaveEvent(self, event): if ACTIVATE_OPACITY: self.animation.setDuration(300) self.animation.setStartValue(settings.MINIMAP_MAX_OPACITY) self.animation.setEndValue(settings.MINIMAP_MIN_OPACITY) self.animation.start() def mousePressEvent(self, event): super(MiniMap, self).mousePressEvent(event) cursor = self.cursorForPosition(event.pos()) self._parent.jump_to_line(cursor.blockNumber()) def resizeEvent(self, event): super(MiniMap, self).resizeEvent(event) self.slider.update_position() def scroll_area(self, pos_parent, pos_slider): pos_parent.setY(pos_parent.y() - pos_slider.y()) cursor = self.cursorForPosition(pos_parent) self._parent.verticalScrollBar().setValue(cursor.blockNumber()) def wheelEvent(self, event): super(MiniMap, self).wheelEvent(event) self._parent.wheelEvent(event)
class PlayGround(MFrame): def __init__(self, parent=None): super(PlayGround, self).__init__(parent) # 效果 self.shadow_effect = None self.shadow_animation = None # 控件 self.top_bar = None self.line_label = None self.view_box = None self.setup_ui() def setup_ui(self): shadow_effect = QGraphicsDropShadowEffect() shadow_effect.setBlurRadius(1) shadow_effect.setColor(QColor(200, 200, 200)) shadow_effect.setOffset(0, 0) self.shadow_effect = shadow_effect self.setGraphicsEffect(self.shadow_effect) self.setStyleSheet( "MFrame{margin:0px;padding:0px;border:1px solid;" "border-color:rgb(220,220,220);background-color:white}") self.setGeometry(100, 100, 1366, 768) self.top_bar = MFrame(self) self.top_bar.setGeometry(0, 0, 1366, 80) font_id = QFontDatabase.addApplicationFont( "font/Roboto-Regular-14.ttf") font_name = QFontDatabase.applicationFontFamilies(font_id)[0] font = QFont(font_name, 14, 1) config_label = QLabel("Configuration", self.top_bar) config_label.setGeometry(1030, 1, 150, 78) config_label.setStyleSheet("color: rgb(100, 100, 100)") config_label.setFont(font) self.line_label = QLabel(self.top_bar) self.line_label.setStyleSheet("background-color:rgb(80, 80, 80)") self.line_label.setGeometry(50, 76, 200, 4) view_box = MFrame(self) view_box.setGeometry(0, 80, 1000, 688) view_box.setStyleSheet("border-top:none;background-color:#fafafa") self.view_box = view_box self.fillViewBox() self.buildupTopBtns() self.line_label.raise_() options = MFrame(self) options.setGeometry(1000, 80, 366, 688) options.setStyleSheet("border-top:none;border-left:none;") option_label = QLabel("Options", options) option_label.setGeometry(30, 30, 150, 60) font = QFont(font_name, 13, 1) option_label.setStyleSheet("color: rgb(100, 100, 100)") option_label.setFont(font) self.shadow_animation = QPropertyAnimation(self) self.shadow_animation.setTargetObject(self.shadow_effect) self.shadow_animation.setPropertyName(b"blurRadius") self.shadow_animation.setStartValue(1) self.shadow_animation.setEndValue(40) self.shadow_animation.setDuration(500) def buildupTopBtns(self): pass def buildupOptions(self): pass def fillViewBox(self): pass def moveSlider(self): animation = QPropertyAnimation(self) animation.setTargetObject(self.line_label) animation.setPropertyName(b"geometry") animation.setStartValue(self.line_label.geometry()) geo = self.sender().geometry() animation.setEndValue(QRect(geo.x(), 76, geo.width(), 4)) animation.setDuration(200) animation.start() def enterEvent(self, Qevent): self.shadow_animation.start() def leaveEvent(self, Qevent): self.shadow_animation.stop() self.shadow_effect.setBlurRadius(1)
class Ui_MainWindow(object): def setupUi(self, MainWindow): MainWindow.setObjectName("MainWindow") MainWindow.resize(364, 371) self.centralwidget = QtWidgets.QWidget(MainWindow) self.centralwidget.setObjectName("centralwidget") self.MusicPlayerFrame = QtWidgets.QFrame(self.centralwidget) self.MusicPlayerFrame.setGeometry(QtCore.QRect(10, 10, 311, 281)) self.MusicPlayerFrame.setFrameShape(QtWidgets.QFrame.StyledPanel) self.MusicPlayerFrame.setFrameShadow(QtWidgets.QFrame.Raised) self.MusicPlayerFrame.setObjectName("MusicPlayerFrame") self.AlbumPhoto = QtWidgets.QGraphicsView(self.MusicPlayerFrame) self.AlbumPhoto.setGeometry(QtCore.QRect(40, 10, 231, 192)) self.AlbumPhoto.setObjectName("AlbumPhoto") self.songSlider = QtWidgets.QSlider(self.MusicPlayerFrame) self.songSlider.setGeometry(QtCore.QRect(39, 210, 231, 20)) self.songSlider.setOrientation(QtCore.Qt.Horizontal) self.songSlider.setObjectName("songSlider") self.centerButton = QtWidgets.QPushButton(self.MusicPlayerFrame) self.centerButton.setGeometry(QtCore.QRect(140, 240, 31, 31)) self.centerButton.setObjectName("centerButton") self.LeftButton = QtWidgets.QPushButton(self.MusicPlayerFrame) self.LeftButton.setGeometry(QtCore.QRect(80, 240, 31, 31)) self.LeftButton.setObjectName("LeftButton") self.RightButton = QtWidgets.QPushButton(self.MusicPlayerFrame) self.RightButton.setGeometry(QtCore.QRect(200, 240, 31, 31)) self.RightButton.setObjectName("RightButton") self.songCurrentTime = QtWidgets.QLabel(self.MusicPlayerFrame) self.songCurrentTime.setGeometry(QtCore.QRect(10, 210, 31, 16)) self.songCurrentTime.setObjectName("songCurrentTime") self.songTotalTime = QtWidgets.QLabel(self.MusicPlayerFrame) self.songTotalTime.setGeometry(QtCore.QRect(280, 210, 31, 16)) self.songTotalTime.setObjectName("songTotalTime") MainWindow.setCentralWidget(self.centralwidget) self.menubar = QtWidgets.QMenuBar(MainWindow) self.menubar.setGeometry(QtCore.QRect(0, 0, 364, 21)) self.menubar.setObjectName("menubar") MainWindow.setMenuBar(self.menubar) self.statusbar = QtWidgets.QStatusBar(MainWindow) self.statusbar.setObjectName("statusbar") MainWindow.setStatusBar(self.statusbar) self.retranslateUi(MainWindow) QtCore.QMetaObject.connectSlotsByName(MainWindow) self.centerButton.clicked.connect(self.animateFrame) def retranslateUi(self, MainWindow): _translate = QtCore.QCoreApplication.translate MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow")) self.centerButton.setText(_translate("MainWindow", "||")) self.LeftButton.setText(_translate("MainWindow", "<<")) self.RightButton.setText(_translate("MainWindow", ">>")) self.songCurrentTime.setText(_translate("MainWindow", "--:--")) self.songTotalTime.setText(_translate("MainWindow", "--:--")) def playSong(self): pygame.mixer.init(48000) pygame.mixer.music.load('CakeByOcean.mp3') pygame.mixer.music.play() def sleeptime(self): time.sleep(1) self.MusicPlayerFrame.hide() time.sleep(1) self.MusicPlayerFrame.show() def animateFrame(self): self.anim = QPropertyAnimation(self.MusicPlayerFrame, b"geometry") self.anim.setDuration(1000) #time in miliseconds self.anim.setStartValue(QRect(0, 0, 311, 281)) self.anim.setEndValue(QRect(0, 900, 500, 500)) self.anim.start() threading.Thread(target=self.sleeptime).start()
class Button(QGraphicsObject): font: QFont = QFont("monospace", 16) clicked = pyqtSignal('PyQt_PyObject') hovered_ = pyqtSignal('PyQt_PyObject') def __init__(self, btn_id: str, label: str, tooltip: str = "", parent: QGraphicsItem = None): QGraphicsObject.__init__(self, parent) self.setFlag(QGraphicsItem.ItemIgnoresTransformations, True) self.scaling = 1.0 self.label = QGraphicsSimpleTextItem(label, self) self.label.setFont(Button.font) self.text_color_enabled = QColor(255, 255, 255, 255) self.text_color_disabled = QColor(200, 200, 200, 255) self.fill_color_disabled = QColor(125, 125, 125, 200) self.label.setBrush(QBrush(self.text_color_enabled)) self.btn_id = btn_id self.rect = QRectF(0, 0, 0, 0) self.tooltip = QGraphicsSimpleTextItem(tooltip, self) self.tooltip.setBrush(QColor(255, 255, 255, 200)) self.tooltip.setFont(Button.font) self.tooltip.setVisible(False) self.tooltip.setZValue(25) self.tooltip_shown = False self.base_color = ButtonColor.GRAY self.hor_margin = 10 self.ver_margin = 5 self.current_timer = 0 self.logic: Union[CheckbuttonLogic, PushbuttonLogic] = PushbuttonLogic("gray") self.fill_color_current = self.logic.idle_color() self.color_animation = QPropertyAnimation(self, b"current_fill_color") self.color_animation.setEasingCurve(QEasingCurve.Linear) self.hovered = False self.setAcceptHoverEvents(True) self.setZValue(4) self.set_height(12) self.pixmap: QPixmap = None self.max_pixmap_height = 128 self.disabled = False self.mode = ButtonMode.Button def set_height(self, h: int): self.prepareGeometryChange() self.ver_margin = int(0.25 * h) font: QFont = self.label.font() font.setPointSize(h) self.label.setFont(font) self.rect.setWidth(self.label.boundingRect().width() + 2 * self.hor_margin) self.rect.setHeight(self.label.boundingRect().height() + 2 * self.ver_margin) self._reposition_text() def set_width(self, w: int): if self.pixmap is not None: return self.prepareGeometryChange() self.rect.setWidth(w) self.hor_margin = self.ver_margin if self.label.boundingRect().width() > self.rect.width(): w = self.rect.width() - 2 * self.hor_margin factor = w / self.label.boundingRect().width() h = factor * self.label.boundingRect().height() font = self.label.font() font.setPixelSize(max(h, 12)) self.label.setFont(font) self._reposition_text() def set_button_height(self, h: int): self.rect.setHeight(h) self._reposition_text() def scale_button(self, factor: float): factor = 1.0 self.rect.setHeight(int(factor * self.rect.height())) self.rect.setWidth(int(factor * self.rect.width())) self.label.setScale(self.scaling) self.fit_to_contents() def _reposition_text(self): x = self.rect.width() / 2 - self.label.boundingRect().width() / 2 y = self.rect.height() / 2 - self.label.boundingRect().height() / 2 self.label.setPos(QPointF(x, y)) self.update() def boundingRect(self): return self.rect def paint(self, painter: QPainter, options, widget=None): painter.setBrush(QBrush(self.fill_color_current)) painter.setPen(QPen(QColor(0, 0, 0, 0))) painter.drawRoundedRect(self.rect, 5, 5) if self.pixmap is not None: painter.drawPixmap(self.hor_margin * self.scaling, self.ver_margin * self.scaling, self.pixmap) if self.tooltip_shown: painter.setBrush(QBrush(QColor(50, 50, 50, 200))) painter.drawRoundedRect(self.tooltip.boundingRect().translated(self.tooltip.pos()) .marginsAdded(QMarginsF(5, 0, 5, 0)), 5, 5) def mousePressEvent(self, event: QGraphicsSceneMouseEvent): if self.disabled or self.mode == ButtonMode.Label: return self.fill_color_current = self.logic.press_color() self.scene().update() def mouseReleaseEvent(self, event: QGraphicsSceneMouseEvent): if self.disabled or self.mode == ButtonMode.Label: return self.click_button() def hoverEnterEvent(self, event: QGraphicsSceneHoverEvent): if self.disabled or self.mode == ButtonMode.Label: return self.hovered_.emit({'btn_id': self.btn_id, 'button': self, 'hovered': True}) self.hovered = True if len(self.tooltip.text()) > 0: self.tooltip_shown = True self.tooltip.setVisible(True) view = self.scene().views()[0] rect_ = view.mapFromScene(self.tooltip.sceneBoundingRect()).boundingRect() pos = self.boundingRect().topRight() mouse_pos = view.mapFromScene(event.scenePos()) if mouse_pos.x() + rect_.width() >= view.viewport().width(): pos = QPointF(-self.tooltip.boundingRect().width(), 0) self.tooltip.setPos(pos) self.color_animation.setDuration(200) self.color_animation.setStartValue(self.logic.idle_color()) self.color_animation.setEndValue(self.logic.hover_enter_color()) self.scene().update() if self.current_timer >= 0: self.killTimer(self.current_timer) self.color_animation.start() self.current_timer = self.startTimer(self.color_animation.duration() // 80) def hoverLeaveEvent(self, event: QGraphicsSceneHoverEvent): if self.disabled or self.mode == ButtonMode.Label: return self.hovered_.emit({'btn_id': self.btn_id, 'button': self, 'hovered': False}) self.hovered = False self.tooltip_shown = False self.tooltip.setVisible(False) self.color_animation.setDuration(200) self.color_animation.setStartValue(self.logic.hover_enter_color()) self.color_animation.setEndValue(self.logic.hover_left_color()) self.scene().update() if self.current_timer > 0: self.killTimer(self.current_timer) self.color_animation.start() self.current_timer = self.startTimer(self.color_animation.duration() // 80) def hoverMoveEvent(self, event: QGraphicsSceneHoverEvent): pass @pyqtProperty(QColor) def current_fill_color(self): return self.fill_color_current @current_fill_color.setter def current_fill_color(self, color: QColor): self.fill_color_current = color def timerEvent(self, ev: QTimerEvent): self.scene().update() if self.color_animation.state() == QPropertyAnimation.Stopped: self.killTimer(ev.timerId()) self.current_timer = 0 def set_base_color(self, colors: List[ButtonColor]): self.logic.set_colors(colors) self.fill_color_current = self.logic.idle_color() def is_on(self): return self.logic.is_down() def set_on(self, value: bool): if isinstance(self.logic, CheckbuttonLogic): self.logic.down = value self.fill_color_current = self.logic.press_color() if value else self.logic.idle_color() self.update() def set_is_check_button(self, value: bool): if value: self.logic = CheckbuttonLogic() else: self.logic = PushbuttonLogic("gray") def set_pixmap(self, pixmap: QPixmap): if pixmap is not None: self.pixmap = pixmap.scaledToHeight(self.max_pixmap_height * self.scaling) if pixmap is not None else None self.fit_to_contents() def fit_to_contents(self): self.prepareGeometryChange() width = 2 * self.hor_margin * self.label.scale() height = 2 * self.ver_margin * self.label.scale() + self.label.boundingRect().height() * self.label.scale() if self.pixmap is not None: width += max(self.pixmap.width(), self.label.boundingRect().width() * self.label.scale()) height += self.ver_margin * self.scaling + self.pixmap.height() else: width += self.label.boundingRect().width() * self.label.scale() self.rect.setWidth(width) self.rect.setHeight(height) self.label.setPos(0.5 * width - 0.5 * self.label.boundingRect().width() * self.label.scale() + 0.0 * self.hor_margin, height - self.label.boundingRect().height() * self.label.scale() - self.ver_margin * self.scaling) self.update() def adjust_text_to_button(self): height_diff = 0.75 * self.rect.height() - self.label.boundingRect().height() fac = height_diff / (0.75 * self.rect.height()) self.label.setTransformOriginPoint(self.label.boundingRect().center()) self.label.setScale(1.0 + fac) self._reposition_text() def set_label(self, text: str, direction: str = 'horizontal'): if direction == 'vertical': text = '\n'.join(list(text)) self.label.setText(text) self._reposition_text() def click_button(self, artificial_emit: bool = False): if self.disabled: return self.logic.do_click() self.fill_color_current = self.logic.release_color() if not artificial_emit else self.logic.idle_color() self.clicked.emit({"btn_id": self.btn_id, "btn_label": self.label, "button": self, 'checked': self.is_on()}) if artificial_emit: self.hovered_.emit({'btn_id': self.btn_id, 'button': self, 'hovered': False}) self.update() if self.scene() is not None: self.scene().update() def set_opacity(self, opacity: float): self.setOpacity(opacity) self.update() def set_default_state(self): self.logic.reset_state() self.fill_color_current = self.logic.idle_color() self.tooltip.setVisible(False) self.tooltip_shown = False self.update() def set_disabled(self, disabled: bool): self.disabled = disabled if disabled: self.label.setBrush(QBrush(self.text_color_disabled)) self.fill_color_current = self.fill_color_disabled else: self.label.setBrush(QBrush(self.text_color_enabled)) self.fill_color_current = self.logic.idle_color() self.update() def set_tooltip(self, tooltip: str): self.tooltip.setVisible(False) self.tooltip_shown = False self.tooltip.setText(tooltip) def set_custom_color(self, colors: List[QColor]): if isinstance(self.logic, CheckbuttonLogic): if len(colors) < 2: return self.logic.set_colors(colors=[ colors[0], colors[0].lighter(120), colors[0].darker(120), colors[1], colors[1].lighter(120), colors[1].darker(120) ]) else: self.logic.set_colors(colors=[ colors[0], colors[0].lighter(120), colors[0].darker(120) ]) self.fill_color_current = self.logic.idle_color() self.update() def set_mode(self, mode: ButtonMode): self.mode = mode
class NotificationDialog(QDialog): NOTIFICATION_LIVETIME = 2000 def __init__(self, assignID, eventDescription, channelName, message, positionNumber, font, notificationManager): super(NotificationDialog, self).__init__( notificationManager.chatScreen.chatUI.centralWidget.mainWindow) self.setWindowFlag(Qt.WindowStaysOnTopHint) self.assignID = assignID self.setAttribute(Qt.WA_DeleteOnClose) self.mainWindow = notificationManager.chatScreen.chatUI.centralWidget.mainWindow self.notificationManager = notificationManager self.eventDescription = eventDescription self.channelName = channelName self.message = message self.closeTime = time.time() + NotificationDialog.NOTIFICATION_LIVETIME self.setWindowFlag(Qt.FramelessWindowHint) self.right = QApplication.desktop().screenGeometry().bottomRight().x( ) + 1 self.bottom = QApplication.desktop().screenGeometry().bottomRight().y() self.height = math.floor( QApplication.desktop().screenGeometry().bottomRight().y() / 10) self.width = math.floor( QApplication.desktop().screenGeometry().bottomRight().x() / 6) self.setGeometry(self.right - self.width, self.height * positionNumber, self.width, self.height - 10) self.label = QLabel() self.label.setObjectName("NotificationLabel") self.label.setText("\t" + eventDescription + "\n\t" + channelName + "\n\t" + message) self.label.setFont(font) self.label.mouseReleaseEvent = self.clicked self.label.setMouseTracking(True) self.label.leaveEvent = self.mouseLeave self.label.enterEvent = self.mouseEnter layout1 = QVBoxLayout() layout1.setContentsMargins(0, 0, 0, 0) layout1.addWidget(self.label) self.setLayout(layout1) self.setWindowModality(Qt.NonModal) self.animation = QPropertyAnimation(self, b"windowOpacity") self.animation.setEasingCurve(QEasingCurve.InCubic) self.animation.setDuration(1000) self.animation.setStartValue(self.windowOpacity()) self.animation.setEndValue(0.1) self.hovered = True self.animation.finished.connect(self.fadeOutClose) self.show() def moveUpByOne(self): self.setGeometry(self.x(), self.y() - self.height, self.width, self.height - 10) def mouseLeave(self, _): self.closeTime = time.time() + NotificationDialog.NOTIFICATION_LIVETIME self.notificationManager.addToSchedule(self) def mouseEnter(self, _): self.animation.stop() self.setWindowOpacity(1.0) self.notificationManager.removeFromScheduleByAssignID(self.assignID) def fadeOutClose(self): self.notificationManager.notificationHasFadedOut(self.assignID) self.close() def fadeOut(self): self.animation.start() def clicked(self, event): if event.button() == Qt.RightButton: self.notificationManager.chatScreen.joinChannel(self.channelName) self.notificationManager.closeNotification(self.assignID) self.close() def __eq__(self, other): return self.assignID == other
class MainWidget(QWidget): showed = pyqtSignal() closed = pyqtSignal() exited = pyqtSignal() def __init__(self, *args, **kwargs): super(MainWidget, self).__init__(*args, **kwargs) self.resize(800, 600) # 保证qss有效 self.setAttribute(Qt.WA_StyledBackground, True) # 左侧菜单栏和右侧内容栏 self._initView() def showEvent(self, event): super(MainWidget, self).showEvent(event) # 动画效果 self._initAnimations() def resizeEvent(self, event): super(MainWidget, self).resizeEvent(event) if not hasattr(self, "_animationGroupShow"): return self._initAnimationsValues() def onClose(self): self._animationGroup.stop() self._initAnimationsValues(False) self._animationGroup.finished.connect(self.exited.emit) self._animationGroup.start() def showNormalBtn(self, visible): self._titleBar.showNormalBtn(visible) def _initView(self): '''标题栏''' parent = self.parent() or self.parentWidget() or self self._titleBar = TitleWidget(parent=self) self._titleBar.minimized.connect(parent.showMinimized) self._titleBar.maximized.connect(parent.showMaximized) self._titleBar.normaled.connect(parent.showNormal) self._titleBar.closed.connect(self.onClose) '''左侧菜单栏和右侧内容栏''' cLayout = QHBoxLayout() self._menuWidget = MenuWidget(self) self._linkWidget = LinkWidget(self) self._contentWidget = ContentWidget(self) cLayout.addWidget(self._menuWidget) cLayout.addWidget(self._linkWidget) cLayout.addWidget(self._contentWidget) # 总体布局 layout = QVBoxLayout(self, spacing=0) layout.setContentsMargins(0, 0, 0, 0) layout.addWidget(self._titleBar) layout.addLayout(cLayout) def _initAnimations(self): '''动画效果''' if hasattr(self, "_animationGroup"): return # 由于showEvent的关系,这里要防止多次实例化 self._animationGroup = QParallelAnimationGroup(self) # 并行动画 # 标题栏 self._animationTitleBar = QPropertyAnimation( self._titleBar, b"geometry", self, easingCurve=QEasingCurve.OutBounce, duration=1000) # 菜单栏 self._animationMenuWidget = QPropertyAnimation( self._menuWidget, b"geometry", self, easingCurve=QEasingCurve.OutBounce, duration=1000) # 链接 self._animationLinkWidget = QPropertyAnimation( self._linkWidget, b"geometry", self, easingCurve=QEasingCurve.OutBounce, duration=1000) # 内容 self._animationContentWidget = QPropertyAnimation( self._contentWidget, b"geometry", self, easingCurve=QEasingCurve.OutBounce, duration=1000) # add to group self._animationGroup.addAnimation(self._animationTitleBar) self._animationGroup.addAnimation(self._animationMenuWidget) self._animationGroup.addAnimation(self._animationLinkWidget) self._animationGroup.addAnimation(self._animationContentWidget) # 初始化位置 self._initAnimationsValues(True) # 启动动画效果 self._animationGroup.start() def _initAnimationsValues(self, show=True): # 标题栏 startValue = QRect(self.width(), 0, self._titleBar.width(), self._titleBar.height()) endValue = QRect(0, 0, self._titleBar.width(), self._titleBar.height()) self._animationTitleBar.setStartValue(startValue if show else endValue) self._animationTitleBar.setEndValue(endValue if show else startValue) # 菜单栏 startValue = QRect(-self._menuWidget.width(), self._titleBar.height(), self._menuWidget.width(), self._menuWidget.height()) endValue = QRect(0, self._titleBar.height(), self._menuWidget.width(), self._menuWidget.height()) self._animationMenuWidget.setStartValue( startValue if show else endValue) self._animationMenuWidget.setEndValue(endValue if show else startValue) # 链接 startValue = QRect(self._menuWidget.width( ), -self.height(), self._linkWidget.width(), self._linkWidget.height()) endValue = QRect( self._menuWidget.width(), self._titleBar.height(), self._linkWidget.width(), self._linkWidget.height()) self._animationLinkWidget.setStartValue( startValue if show else endValue) self._animationLinkWidget.setEndValue(endValue if show else startValue) # 内容 startValue = QRect(self.width(), self.height(), self._contentWidget.width(), self._contentWidget.height()) endValue = QRect( self._menuWidget.width() + self._linkWidget.width(), self._titleBar.height(), self._contentWidget.width(), self._contentWidget.height()) self._animationContentWidget.setStartValue( startValue if show else endValue) self._animationContentWidget.setEndValue( endValue if show else startValue)
class UiTasklist(object): def setup(self, Dialog): Dialog.setObjectName("TaskList") Dialog.setEnabled(True) Dialog.setWindowFlags(QtCore.Qt.FramelessWindowHint) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(Dialog.sizePolicy().hasHeightForWidth()) Dialog.setSizePolicy(sizePolicy) Dialog.setStyleSheet(CSS) self.label_3 = QtWidgets.QLabel(Dialog) self.label_3.setGeometry(QtCore.QRect(100, 0, 91, 16)) self.label_3.setObjectName("label_3") self.verticalLayoutWidget = QtWidgets.QWidget(Dialog) self.verticalLayoutWidget.setGeometry(QtCore.QRect(0, 0, 341, 541)) self.verticalLayoutWidget.setObjectName("verticalLayoutWidget") self.verticalLayout = QtWidgets.QVBoxLayout(self.verticalLayoutWidget) self.verticalLayout.setSizeConstraint(QtWidgets.QLayout.SetFixedSize) self.verticalLayout.setContentsMargins(0, 0, 0, 0) self.verticalLayout.setSpacing(0) self.verticalLayout.setObjectName("verticalLayout") self.verticalLayout_2 = QtWidgets.QVBoxLayout() self.verticalLayout_2.setSizeConstraint( QtWidgets.QLayout.SetMaximumSize) self.verticalLayout_2.setContentsMargins(0, 0, 0, 6) self.verticalLayout_2.setSpacing(4) self.verticalLayout_2.setObjectName("verticalLayout_2") self.lbl_status = QtWidgets.QLabel(self.verticalLayoutWidget) font = QtGui.QFont() font.setPointSize(10) font.setBold(True) font.setWeight(75) self.lbl_status.setFont(font) self.lbl_status.setAlignment(QtCore.Qt.AlignCenter) self.lbl_status.setObjectName("lbl_status") self.verticalLayout_2.addWidget(self.lbl_status) self.label_2 = QtWidgets.QLabel(self.verticalLayoutWidget) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.label_2.sizePolicy().hasHeightForWidth()) self.label_2.setSizePolicy(sizePolicy) font = QtGui.QFont() font.setPointSize(9) font.setBold(False) font.setWeight(50) self.label_2.setFont(font) self.label_2.setTextFormat(QtCore.Qt.AutoText) self.label_2.setScaledContents(False) self.label_2.setAlignment(QtCore.Qt.AlignCenter) self.label_2.setWordWrap(False) self.label_2.setObjectName("label_2") self.verticalLayout_2.addWidget(self.label_2) self.verticalLayout.addLayout(self.verticalLayout_2) self.listWidget = QtWidgets.QListWidget(self.verticalLayoutWidget) self.listWidget.setFixedHeight(460) self.listWidget.setFixedWidth(340) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.listWidget.sizePolicy().hasHeightForWidth()) self.listWidget.setSizePolicy(sizePolicy) self.listWidget.setAutoFillBackground(False) self.listWidget.setFrameShape(QtWidgets.QFrame.NoFrame) self.listWidget.setFrameShadow(QtWidgets.QFrame.Raised) self.listWidget.setHorizontalScrollBarPolicy( QtCore.Qt.ScrollBarAlwaysOff) self.listWidget.setEditTriggers( QtWidgets.QAbstractItemView.NoEditTriggers) self.listWidget.setSelectionMode( QtWidgets.QAbstractItemView.NoSelection) self.listWidget.setMovement(QtWidgets.QListView.Static) #self.listWidget.setProperty("isWrapping", False) self.listWidget.setResizeMode(QtWidgets.QListView.Fixed) self.listWidget.setLayoutMode(QtWidgets.QListView.SinglePass) self.listWidget.setViewMode(QtWidgets.QListView.ListMode) self.listWidget.setSelectionRectVisible(False) self.listWidget.setObjectName("listWidget") self.verticalLayout.addWidget(self.listWidget) self.retranslate(Dialog) QtCore.QMetaObject.connectSlotsByName(Dialog) def retranslate(self, Dialog): _translate = QtCore.QCoreApplication.translate Dialog.setWindowTitle(_translate("Dialog", "GSyncftp - Tasklist")) self.lbl_status.setText( _translate("TaskList", "O GSyncftp está atualizado")) self.label_2.setText(_translate("TaskList", " Enterprise Coorp. LTDA")) self.listWidget.setSortingEnabled(False) self.listWidget.addItem("Nenhum arquivo na fila") def status_sync(self): _translate = QtCore.QCoreApplication.translate self.lbl_status.setText( _translate("TaskList", "Enviando os arquivos...")) def status_synced(self): _translate = QtCore.QCoreApplication.translate self.lbl_status.setText( _translate("TaskList", "O GSyncftp está atualizado")) def do_animation(self, Dialog): size_screen = QtWidgets.QDesktopWidget().screenGeometry(-1) pt_x = size_screen.width() - 339 pt_y = size_screen.height() - 537 self.anim = QPropertyAnimation(Dialog, b"geometry") self.anim.setDuration(250) self.anim.setStartValue(QRect(pt_x, size_screen.height(), 339, 537)) self.anim.setEndValue(QRect(pt_x, pt_y, 339, 537)) self.anim.start() Dialog.setEnabled(True) def not_in_animation(self): return self.anim and self.anim.state() != 2
class LoginView(QWidget): signal_login = pyqtSignal() def __init__(self): super(LoginView, self).__init__() self.resize(476, 200) stack_layout = QStackedLayout(self) stack_layout.setStackingMode(QStackedLayout.StackAll) stack_layout.addChildWidget(UICreatetor.create_background()) content = self.create_login_content() content.move( self.width()-content.width() >> 1, self.height()-content.height() >> 1 ) stack_layout.addChildWidget(content) self.msg_alert = QLabel("密码不能为空") self.msg_alert.setStyleSheet("background-color: rgb(242, 206, 58);" "color: rgb(80, 80, 80);font: 12pt \"Microsoft YaHei UI\";") self.msg_alert.resize(476, 30) self.msg_alert.setAlignment(Qt.AlignCenter) self.msg_alert.move(0, 200) stack_layout.addChildWidget(self.msg_alert) self.alert_anim_in = QPropertyAnimation(self.msg_alert, b"pos") self.alert_anim_in.setStartValue(QPoint(0, 200)) self.alert_anim_in.setEndValue(QPoint(0, 200)) self.alert_anim_in.setEasingCurve(QEasingCurve.OutBack) self.alert_anim_in.setKeyValueAt(0.05, QPoint(0, 170)) self.alert_anim_in.setKeyValueAt(0.95, QPoint(0, 170)) self.alert_anim_in.setDuration(8000) self.anim_in = QPropertyAnimation(self, b"pos") self.anim_out = QPropertyAnimation(self, b"pos") self.anim_in.setStartValue(QPoint(2, 0)) self.anim_in.setEndValue(QPoint(2, 200)) self.anim_in.setKeyValueAt(0.5, QPoint(2, 0)) self.anim_in.setEasingCurve(QEasingCurve.InOutBounce) self.anim_in.setDuration(2000) self.anim_out.setDuration(500) self.anim_out.setStartValue(QPoint(2, 200)) self.anim_out.setEndValue(QPoint(2, 0)) self.anim_out.setEasingCurve(QEasingCurve.OutExpo) if os.path.exists("ac.bin"): with open("ac.bin", "r") as file: content = file.read() dec_str = LoginTool.decrypt(content) print(dec_str) dec_str = dec_str.replace("\x00", "") ups = dec_str.split("|") print(ups,len(ups)) if len(ups) == 2: self.username_edit.setText(ups[0]) self.password_edit.setText(ups[1]) file.close() else: print("密码文件不存在") def show_alert(self, msg): self.msg_alert.setText(msg) self.alert_anim_in.stop() self.alert_anim_in.start() def create_login_content(self): widget = QWidget() layout = QVBoxLayout(widget) self.username_edit = UICreatetor.create_username_input() layout.addWidget(self.username_edit, 0, Qt.AlignCenter) self.password_edit = UICreatetor.create_password_input() self.password_edit.returnPressed.connect(self.on_login_clicked) layout.addWidget(self.password_edit, 0, Qt.AlignCenter) center_layout = QHBoxLayout() self.save_paw_check = QCheckBox("保存密码") self.save_paw_check.setChecked(True) self.save_paw_check.setStyleSheet("font: 75 11pt \"Microsoft YaHei UI\";color: rgb(134, 134, 134);") center_layout.addWidget(self.save_paw_check) forget = QLabel("忘记密码") # forget.addAction() forget.setStyleSheet("font: 75 11pt \"Microsoft YaHei UI\";color: rgb(108, 202, 218);padding-right:0px") center_layout.addWidget(forget, 0, Qt.AlignRight) layout.addLayout(center_layout) layout.addSpacing(10) login_btn = UICreatetor.create_login_button() login_btn.clicked.connect(self.on_login_clicked) layout.addWidget(login_btn, 0, Qt.AlignCenter) login_btn.setFixedSize(188, 38) layout.addStretch() widget.resize(290, 200) return widget def on_login_clicked(self): self.signal_login.emit() def easing_in(self): self.anim_in.start() def easing_out(self): self.anim_out.start()
class SidebarCardHolder(QFrame): clicked = pyqtSignal(int) def __init__(self, wgt_id, text, parent=None): super().__init__(parent) # self.setFrameShape(QFrame.StyledPanel) # self.setFrameShadow(QFrame.Plain) self.widget_id = wgt_id self.setMouseTracking(True) self.text_lbl = QLabel(text) self.bottom_line = QFrame() self.bottom_line.setFrameShape(QFrame.HLine) self.bottom_line.setFrameShadow(QFrame.Sunken) self.bottom_line.setFixedHeight(1) self.bottom_line.setObjectName('CardHolderBLine') self.bottom_line.setStyleSheet('#CardHolderBLine{background: blue;}') mlayout = QVBoxLayout() mlayout.setContentsMargins(0, 0, 0, 0) mlayout.addWidget(self.text_lbl, 0, Qt.AlignCenter) mlayout.addWidget(self.bottom_line, 0, Qt.AlignCenter) self.setLayout(mlayout) size_hint = self.sizeHint() # Needed because of hover visuals when card-holder is triggered(displayed). size_hint.setHeight(size_hint.height() + 1) self.setFixedSize(size_hint) self.anim = QPropertyAnimation(self.bottom_line, b'minimumWidth') self.anim.setDuration(300) self.triggered = False def mousePressEvent(self, event): super().mousePressEvent(event) self.clicked.emit(self.widget_id) self.triggered = not self.triggered if self.triggered: self.anim.stop() self.bottom_line.setFixedHeight(2) self.anim.setStartValue(self.bottom_line.width()) self.anim.setEndValue(self.width() + 10) self.anim.start() else: self.bottom_line.setFixedHeight(1) def enterEvent(self, event): if self.triggered: self.bottom_line.setFixedHeight(2) else: self.anim.stop() self.anim.setStartValue(self.bottom_line.width()) self.anim.setEndValue(self.width() + 10) self.anim.start() def leaveEvent(self, event): if self.triggered: self.bottom_line.setFixedHeight(1) else: self.anim.stop() self.anim.setStartValue(self.bottom_line.width()) self.anim.setEndValue(0) self.anim.start()
class MainWindow(QMainWindow): htmlReady = pyqtSignal(str) def __init__(self, app): QMainWindow.__init__(self) self.install_directory = os.getcwd() self.app = app self.book = None self.last_book = "" self.filename = "" self._part_is_new = False self.tread_running = False self.initTheme() self.createUi() self.loadPlugins() self.createMenus() self.createStatusBar() self.readSettings() self.text_edit.textChanged.connect(self.textChanged) def initTheme(self): settings = QSettings(QSettings.IniFormat, QSettings.UserScope, QCoreApplication.organizationName(), QCoreApplication.applicationName()) self.theme = settings.value("theme", "DarkFusion") hilite_color = settings.value( "hiliteColor", self.palette().highlight().color().name()) self.changeStyle(self.theme, hilite_color) def showEvent(self, event): if self.last_book: self.loadBook(self.last_book) def changeStyle(self, theme, hilite_color): self.theme = theme if theme == "DarkFusion": QApplication.setStyle(DarkFusion(hilite_color)) else: QApplication.setStyle(QStyleFactory.create(theme)) pal = self.app.palette() pal.setColor(QPalette.Highlight, QColor(hilite_color)) self.app.setPalette(pal) def createUi(self): self.content = Expander("Content", ":/images/parts.svg") self.images = Expander("Images", ":/images/images.svg") self.settings = Expander("Settings", ":/images/settings.svg") self.setWindowTitle(QCoreApplication.applicationName() + " " + QCoreApplication.applicationVersion()) vbox = QVBoxLayout() vbox.addWidget(self.content) vbox.addWidget(self.images) vbox.addWidget(self.settings) vbox.addStretch() self.content_list = QListWidget() self.content_list.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Fixed) content_box = QVBoxLayout() content_box.addWidget(self.content_list) self.item_edit = QLineEdit() self.item_edit.setMaximumHeight(0) self.item_edit.editingFinished.connect(self.editItemFinished) self.item_anim = QPropertyAnimation(self.item_edit, "maximumHeight".encode("utf-8")) content_box.addWidget(self.item_edit) button_layout = QHBoxLayout() plus_button = FlatButton(":/images/plus.svg") self.edit_button = FlatButton(":/images/edit.svg") self.trash_button = FlatButton(":/images/trash.svg") self.up_button = FlatButton(":/images/up.svg") self.down_button = FlatButton(":/images/down.svg") self.trash_button.enabled = False self.up_button.enabled = False self.down_button.enabled = False button_layout.addWidget(plus_button) button_layout.addWidget(self.up_button) button_layout.addWidget(self.down_button) button_layout.addWidget(self.edit_button) button_layout.addWidget(self.trash_button) content_box.addLayout(button_layout) self.content.addLayout(content_box) plus_button.clicked.connect(self.addPart) self.trash_button.clicked.connect(self.dropPart) self.up_button.clicked.connect(self.partUp) self.down_button.clicked.connect(self.partDown) self.edit_button.clicked.connect(self.editPart) self.image_list = QListWidget() self.image_list.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Fixed) image_box = QVBoxLayout() image_box.addWidget(self.image_list) image_button_layout = QHBoxLayout() image_plus_button = FlatButton(":/images/plus.svg") self.image_trash_button = FlatButton(":/images/trash.svg") self.image_trash_button.enabled = False image_button_layout.addWidget(image_plus_button) image_button_layout.addWidget(self.image_trash_button) image_box.addLayout(image_button_layout) self.images.addLayout(image_box) image_plus_button.clicked.connect(self.addImage) self.image_trash_button.clicked.connect(self.dropImage) scroll_content = QWidget() scroll_content.setLayout(vbox) scroll = QScrollArea() scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded) scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded) scroll.setWidget(scroll_content) scroll.setWidgetResizable(True) scroll.setMaximumWidth(200) scroll.setMinimumWidth(200) self.navigationdock = QDockWidget("Navigation", self) self.navigationdock.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea) self.navigationdock.setWidget(scroll) self.navigationdock.setObjectName("Navigation") self.addDockWidget(Qt.LeftDockWidgetArea, self.navigationdock) self.splitter = QSplitter() self.text_edit = MarkdownEdit() self.text_edit.setFont(QFont("Courier", 11)) self.preview = QWebEngineView() self.preview.setMinimumWidth(300) self.setWindowTitle(QCoreApplication.applicationName()) self.splitter.addWidget(self.text_edit) self.splitter.addWidget(self.preview) self.setCentralWidget(self.splitter) self.content.expanded.connect(self.contentExpanded) self.images.expanded.connect(self.imagesExpanded) self.settings.expanded.connect(self.settingsExpanded) self.settings.clicked.connect(self.openSettings) self.content_list.currentItemChanged.connect(self.partSelectionChanged) self.image_list.currentItemChanged.connect(self.imageSelectionChanged) self.image_list.itemDoubleClicked.connect(self.insertImage) self.text_edit.undoAvailable.connect(self.undoAvailable) self.text_edit.redoAvailable.connect(self.redoAvailable) self.text_edit.copyAvailable.connect(self.copyAvailable) QApplication.clipboard().dataChanged.connect(self.clipboardDataChanged) def undoAvailable(self, value): self.undo_act.setEnabled(value) def redoAvailable(self, value): self.redo_act.setEnabled(value) def copyAvailable(self, value): self.copy_act.setEnabled(value) self.cut_act.setEnabled(value) def clipboardDataChanged(self): md = QApplication.clipboard().mimeData() self.paste_act.setEnabled(md.hasText()) def openSettings(self): dlg = Settings(self.book, self.install_directory) dlg.exec() if dlg.saved: self.setWindowTitle(QCoreApplication.applicationName() + " - " + self.book.name) def addPart(self): self.item_edit.setText("") self.item_edit.setFocus() self.item_anim.setStartValue(0) self.item_anim.setEndValue(23) self.item_anim.start() self._part_is_new = True def addItem(self): text = self.item_edit.text() if text: if not self.book.getPart(text): self.book.addPart(text) self.loadBook(self.last_book) def updateItem(self): text = self.item_edit.text() if text: if not self.book.getPart(text): self.book.updatePart( self.content_list.currentItem().data(1).name, text) self.loadBook(self.last_book) def editItemFinished(self): if self._part_is_new: self.addItem() else: self.updateItem() self.item_anim.setStartValue(23) self.item_anim.setEndValue(0) self.item_anim.start() def editPart(self): item = self.content_list.currentItem().data(1).name self.item_edit.setText(item) self.item_edit.setFocus() self.item_anim.setStartValue(0) self.item_anim.setEndValue(23) self.item_anim.start() self._part_is_new = False def dropPart(self): item = self.content_list.currentItem().data(1).name msgBox = QMessageBox() msgBox.setText("You are about to delete the part <i>" + item + "</i>") msgBox.setInformativeText("Do you really want to delete the item?") msgBox.setStandardButtons(QMessageBox.Yes | QMessageBox.Cancel) msgBox.setDefaultButton(QMessageBox.Cancel) ret = msgBox.exec() if ret == QMessageBox.Yes: self.book.dropPart(item) self.loadBook(self.last_book) def addImage(self): fileName = "" dialog = QFileDialog() dialog.setFileMode(QFileDialog.AnyFile) dialog.setNameFilter("Image Files(*.png *.jpg *.bmp *.gif);;All (*)") dialog.setWindowTitle("Load Image") dialog.setOption(QFileDialog.DontUseNativeDialog, True) dialog.setAcceptMode(QFileDialog.AcceptOpen) if dialog.exec_(): fileName = dialog.selectedFiles()[0] del dialog if not fileName: return base = os.path.basename(fileName) if not os.path.exists( os.path.join(self.book.source_path, "images", base)): copy(fileName, os.path.join(self.book.source_path, "images")) item = QListWidgetItem() item.setText(Path(fileName).name) item.setData( 1, os.path.join(self.book.source_path, "images", Path(fileName).name)) self.image_list.addItem(item) def dropImage(self): item = self.image_list.currentItem() image = item.data(1) filename = os.path.join(self.book.source_path, "parts", image) os.remove(filename) self.loadImages() def loadImages(self): self.image_list.clear() for root, dir, files in os.walk( os.path.join(self.book.source_path, "images")): for file in files: filename = os.path.join(self.book.source_path, "images", Path(file).name) item = QListWidgetItem() item.setToolTip("Doubleclick image to insert into text") item.setText(Path(file).name) item.setData(1, filename) self.image_list.addItem(item) def partUp(self): pos = self.content_list.currentRow() item = self.content_list.takeItem(pos) self.content_list.insertItem(pos - 1, item) self.content_list.setCurrentRow(pos - 1) self.book.partUp(item.data(1).name) def partDown(self): pos = self.content_list.currentRow() item = self.content_list.takeItem(pos) self.content_list.insertItem(pos + 1, item) self.content_list.setCurrentRow(pos + 1) self.book.partDown(item.data(1).name) def partSelectionChanged(self, item): if item: part = item.data(1) self.filename = os.path.join(self.book.source_path, "parts", part.src) with open(self.filename, "r") as f: t = f.read() self.text_edit.setPlainText(t) self.trash_button.enabled = True self.up_button.enabled = self.content_list.currentRow() > 0 self.down_button.enabled = self.content_list.currentRow( ) < self.content_list.count() - 1 self.edit_button.enabled = True else: self.text_edit.setText("") self.trash_button.enabled = False self.up_button.enabled = False self.down_button.enabled = False self.edit_button.enabled = False def imageSelectionChanged(self, item): if item: self.image_trash_button.enabled = True else: self.image_trash_button.enabled = False def contentExpanded(self, value): if value: self.images.setExpanded(False) self.settings.setExpanded(False) def imagesExpanded(self, value): if value: self.content.setExpanded(False) self.settings.setExpanded(False) def appearanceExpanded(self, value): if value: self.content.setExpanded(False) self.images.setExpanded(False) self.settings.setExpanded(False) def settingsExpanded(self, value): if value: self.content.setExpanded(False) self.images.setExpanded(False) def closeEvent(self, event): self.writeSettings() event.accept() def createMenus(self): new_icon = QIcon(QPixmap(":/images/new.svg")) open_icon = QIcon(QPixmap(":/images/open.svg")) book_icon = QIcon(QPixmap(":/images/book.svg")) bold_icon = QIcon(QPixmap(":/images/bold.svg")) italic_icon = QIcon(QPixmap(":/images/italic.svg")) image_icon = QIcon(QPixmap(":/images/image.svg")) table_icon = QIcon(QPixmap(":/images/table.svg")) á_icon = QIcon(QPixmap(":/images/á.svg")) ã_icon = QIcon(QPixmap(":/images/ã.svg")) é_icon = QIcon(QPixmap(":/images/é.svg")) ê_icon = QIcon(QPixmap(":/images/ê.svg")) ó_icon = QIcon(QPixmap(":/images/ó.svg")) new_act = QAction(new_icon, "&New", self) new_act.setShortcuts(QKeySequence.New) new_act.setStatusTip("Create a new ebook project") new_act.triggered.connect(self.newFile) new_act.setToolTip("Create new ebook project") open_act = QAction(open_icon, "&Open", self) open_act.setShortcuts(QKeySequence.Open) open_act.setStatusTip("Open an existing ebook project") open_act.triggered.connect(self.open) open_act.setToolTip("Open an existing ebook project") book_act = QAction(book_icon, "&Create Book", self) book_act.setShortcuts(QKeySequence.SaveAs) book_act.setStatusTip("Create an ebook") book_act.triggered.connect(self.create) book_act.setToolTip("Create an ebook") pdf_act = QAction("Create &PDF", self) pdf_act.setStatusTip("Create PDF") pdf_act.setToolTip("Create PDF") pdf_act.triggered.connect(self.pdfExport) settings_act = QAction("&Settings", self) settings_act.setStatusTip("Open settings dialog") settings_act.triggered.connect(self.settingsDialog) settings_act.setToolTip("Open settings dialog") exit_act = QAction("E&xit", self) exit_act.setShortcuts(QKeySequence.Quit) exit_act.setStatusTip("Exit the application") exit_act.triggered.connect(self.close) self.undo_act = QAction("Undo", self) self.undo_act.setShortcut(QKeySequence.Undo) self.undo_act.setEnabled(False) self.undo_act.triggered.connect(self.doUndo) self.redo_act = QAction("Redo", self) self.redo_act.setShortcut(QKeySequence.Redo) self.redo_act.setEnabled(False) self.undo_act.triggered.connect(self.doRedo) self.cut_act = QAction("Cu&t", self) self.cut_act.setShortcut(QKeySequence.Cut) self.cut_act.triggered.connect(self.doCut) self.cut_act.setEnabled(False) self.copy_act = QAction("&Copy", self) self.copy_act.setShortcut(QKeySequence.Copy) self.copy_act.triggered.connect(self.doCopy) self.copy_act.setEnabled(False) self.paste_act = QAction("&Paste", self) self.paste_act.setShortcut(QKeySequence.Paste) self.paste_act.triggered.connect(self.doPaste) self.paste_act.setEnabled(False) bold_act = QAction(bold_icon, "Bold", self) bold_act.setShortcut(Qt.CTRL + Qt.Key_B) bold_act.triggered.connect(self.bold) italic_act = QAction(italic_icon, "Italic", self) italic_act.setShortcut(Qt.CTRL + Qt.Key_I) italic_act.triggered.connect(self.italic) image_act = QAction(image_icon, "Image", self) image_act.setShortcut(Qt.CTRL + Qt.Key_G) image_act.triggered.connect(self.insertImage) image_act.setToolTip("Insert an image") table_act = QAction(table_icon, "Table", self) table_act.setShortcut(Qt.CTRL + Qt.Key_T) table_act.triggered.connect(self.insertTable) table_act.setToolTip("Insert a table") á_act = QAction(á_icon, "á", self) á_act.triggered.connect(self.insertLetterA1) á_act.setToolTip("Insert letter á") ã_act = QAction(ã_icon, "ã", self) ã_act.triggered.connect(self.insertLetterA2) ã_act.setToolTip("Insert letter ã") é_act = QAction(é_icon, "é", self) é_act.triggered.connect(self.insertLetterE1) é_act.setToolTip("Insert letter é") ê_act = QAction(ê_icon, "ê", self) ê_act.triggered.connect(self.insertLetterE2) ê_act.setToolTip("Insert letter ê") ó_act = QAction(ó_icon, "ó", self) ó_act.triggered.connect(self.insertLetterO1) ó_act.setToolTip("Insert letter ó") about_act = QAction("&About", self) about_act.triggered.connect(self.about) about_act.setStatusTip("Show the application's About box") spell_act = QAction("&Spellcheck", self) spell_act.setShortcut(Qt.CTRL + Qt.Key_P) spell_act.triggered.connect(self.spellCheck) spell_act.setStatusTip("Spellcheck") file_menu = self.menuBar().addMenu("&File") file_menu.addAction(new_act) file_menu.addAction(open_act) file_menu.addAction(book_act) file_menu.addAction(pdf_act) file_menu.addSeparator() file_menu.addAction(settings_act) file_menu.addSeparator() file_menu.addAction(exit_act) edit_menu = self.menuBar().addMenu("&Edit") edit_menu.addAction(self.undo_act) edit_menu.addAction(self.redo_act) edit_menu.addSeparator() edit_menu.addAction(self.cut_act) edit_menu.addAction(self.copy_act) edit_menu.addAction(self.paste_act) format_menu = self.menuBar().addMenu("&Format") format_menu.addAction(bold_act) format_menu.addAction(italic_act) insert_menu = self.menuBar().addMenu("&Insert") insert_menu.addAction(image_act) insert_menu.addAction(table_act) for key in Plugins.generatorPluginNames(): gen = Plugins.getGeneratorPlugin(key) if gen: act = QAction(gen.display_name, self) #act.triggered.connect(self.insertTable) #act.setToolTip("Insert a table") insert_menu.addAction(act) act.triggered.connect(gen.menu_action) help_menu = self.menuBar().addMenu("&Help") help_menu.addAction(about_act) help_menu.addAction(spell_act) file_tool_bar = self.addToolBar("File") file_tool_bar.addAction(new_act) file_tool_bar.addAction(open_act) file_tool_bar.addAction(book_act) format_tool_bar = self.addToolBar("Format") format_tool_bar.addAction(bold_act) format_tool_bar.addAction(italic_act) insert_toolbar = self.addToolBar("Insert") insert_toolbar.addAction(image_act) insert_toolbar.addAction(table_act) insert_toolbar.addAction(á_act) insert_toolbar.addAction(ã_act) insert_toolbar.addAction(é_act) insert_toolbar.addAction(ê_act) insert_toolbar.addAction(ó_act) def doUndo(self): self.text_edit.undo() def doRedo(self): self.text_edit.redo() def doCut(self): self.text_edit.cut() def doCopy(self): self.text_edit.copy() def doPaste(self): self.text_edit.paste() def insertImage(self): if not self.book: QMessageBox.warning(self, QCoreApplication.applicationName(), "You have to load or create a book first!") return if not self.filename: QMessageBox.warning( self, QCoreApplication.applicationName(), "You have to select part from the book content first!") return if self.image_list.count() == 0: QMessageBox.warning( self, QCoreApplication.applicationName(), "You have to add an image to the image list first!") return if not self.image_list.currentItem(): QMessageBox.warning( self, QCoreApplication.applicationName(), "You have to select an image from the image list first!") return item = self.image_list.currentItem() filename = item.text() cursor = self.text_edit.textCursor() pos = cursor.position() base = filename.split(".")[0].replace("_", "-") cursor.insertText("![" + base + "](../images/" + filename + " \"" + base + "\")") cursor.setPosition(pos) self.text_edit.setTextCursor(cursor) def insertTable(self): cursor = self.text_edit.textCursor() pos = cursor.position() cursor.insertText( "| alignLeft | alignCenter | unAligned | alignRight |\n" "| :--- | :---: | --- | ---: |\n" "| cell a | cell b | cell c | cell d |\n" "| cell e | cell f | cell g | cell h |\n") cursor.setPosition(pos) self.text_edit.setTextCursor(cursor) def insertLetterA1(self): cursor = self.text_edit.textCursor() pos = cursor.position() cursor.insertText("á") cursor.setPosition(pos + 1) self.text_edit.setTextCursor(cursor) def insertLetterA2(self): cursor = self.text_edit.textCursor() pos = cursor.position() cursor.insertText("ã") cursor.setPosition(pos + 1) self.text_edit.setTextCursor(cursor) def insertLetterE1(self): cursor = self.text_edit.textCursor() pos = cursor.position() cursor.insertText("é") cursor.setPosition(pos + 1) self.text_edit.setTextCursor(cursor) def insertLetterE2(self): cursor = self.text_edit.textCursor() pos = cursor.position() cursor.insertText("ê") cursor.setPosition(pos + 1) self.text_edit.setTextCursor(cursor) def insertLetterO1(self): cursor = self.text_edit.textCursor() pos = cursor.position() cursor.insertText("ó") cursor.setPosition(pos + 1) self.text_edit.setTextCursor(cursor) def createStatusBar(self): self.statusBar().showMessage("Ready") def about(self): QMessageBox.about( self, "About " + QCoreApplication.applicationName(), "EbookCreator\nVersion: " + QCoreApplication.applicationVersion() + "\n(C) Copyright 2020 CrowdWare. All rights reserved.\n\nThis program is provided AS IS with NO\nWARRANTY OF ANY KIND, INCLUDING THE\nWARRANTY OF DESIGN, MERCHANTABILITY AND\nFITNESS FOR A PATICULAR PURPOSE." ) def newFile(self): dlg = ProjectWizard(self.install_directory, parent=self) dlg.loadBook.connect(self.loadBook) dlg.show() def open(self): fileName = "" dialog = QFileDialog() dialog.setFileMode(QFileDialog.AnyFile) dialog.setNameFilter("EbookCreator (book.qml);;All (*)") dialog.setWindowTitle("Load Ebook") dialog.setOption(QFileDialog.DontUseNativeDialog, True) dialog.setAcceptMode(QFileDialog.AcceptOpen) dialog.setDirectory(os.path.join(self.install_directory, "sources")) if dialog.exec_(): fileName = dialog.selectedFiles()[0] del dialog if not fileName: return self.loadBook(fileName) def writeSettings(self): settings = QSettings(QSettings.IniFormat, QSettings.UserScope, QCoreApplication.organizationName(), QCoreApplication.applicationName()) settings.setValue("geometry", self.saveGeometry()) settings.setValue("lastBook", self.last_book) def readSettings(self): settings = QSettings(QSettings.IniFormat, QSettings.UserScope, QCoreApplication.organizationName(), QCoreApplication.applicationName()) geometry = settings.value("geometry", QByteArray()) self.last_book = settings.value("lastBook") if not geometry: availableGeometry = QApplication.desktop().availableGeometry(self) self.resize(availableGeometry.width() / 3, availableGeometry.height() / 2) self.move((availableGeometry.width() - self.width()) / 2, (availableGeometry.height() - self.height()) / 2) else: self.restoreGeometry(geometry) def bold(self): if not self.filename: QMessageBox.warning( self, QCoreApplication.applicationName(), "You have to select part from the book content first!") return cursor = self.text_edit.textCursor() pos = cursor.position() if not cursor.hasSelection(): cursor.select(QTextCursor.WordUnderCursor) cursor.insertText("**" + cursor.selectedText() + "**") cursor.setPosition(pos + 2) self.text_edit.setTextCursor(cursor) def italic(self): if not self.filename: QMessageBox.warning( self, QCoreApplication.applicationName(), "You have to select part from the book content first!") return cursor = self.text_edit.textCursor() pos = cursor.position() if not cursor.hasSelection(): cursor.select(QTextCursor.WordUnderCursor) cursor.insertText("*" + cursor.selectedText() + "*") cursor.setPosition(pos + 1) self.text_edit.setTextCursor(cursor) def create(self): filename = "" dialog = QFileDialog() dialog.setFileMode(QFileDialog.AnyFile) dialog.setNameFilter("ePub3 (*.epub);;All (*)") dialog.setWindowTitle("Create Ebook") dialog.setOption(QFileDialog.DontUseNativeDialog, True) dialog.setAcceptMode(QFileDialog.AcceptSave) dialog.setDirectory(self.book.source_path) dialog.setDefaultSuffix("epub") if dialog.exec_(): filename = dialog.selectedFiles()[0] del dialog if not filename: return QApplication.setOverrideCursor(Qt.WaitCursor) createEpub(filename, self.book, self) QApplication.restoreOverrideCursor() def loadStatusChanged(self, status): if status == 1: self.book = self.component.create() if self.book is not None: self.book.setFilename(self.last_book) self.book.setWindow(self) else: for error in self.component.errors(): print(error.toString()) return self.content_list.clear() for part in self.book.parts: item = QListWidgetItem() item.setText(part.name) item.setData(1, part) self.content_list.addItem(item) self.loadImages() self.setWindowTitle(QCoreApplication.applicationName() + " - " + self.book.name) self.content.setExpanded(True) self.content_list.setCurrentRow(0) elif status == 3: for error in self.component.errors(): print(error.toString()) return def loadBook(self, filename): self.last_book = filename self.filename = "" engine = QQmlEngine() self.component = QQmlComponent(engine) self.component.statusChanged.connect(self.loadStatusChanged) self.component.loadUrl(QUrl.fromLocalFile(filename)) def settingsDialog(self): dlg = SettingsDialog(self.theme, self.palette().highlight().color().name(), parent=self) dlg.exec() if dlg.theme != self.theme or dlg.hilite_color != self.palette( ).highlight().color().name(): settings = QSettings(QSettings.IniFormat, QSettings.UserScope, QCoreApplication.organizationName(), QCoreApplication.applicationName()) settings.setValue("theme", dlg.theme) settings.setValue("hiliteColor", dlg.hilite_color) msgBox = QMessageBox() msgBox.setText("Please restart the app to change the theme!") msgBox.exec() def textChanged(self): text = self.text_edit.toPlainText() if self.filename: with open(self.filename, "w") as f: f.write(text) self.lock = Lock() with self.lock: if not self.tread_running: self.tread_running = True self.htmlReady.connect(self.previewReady) thread = Thread(target=self.createHtml, args=(text, )) thread.daemon = True thread.start() def previewReady(self, html): self.preview.setHtml( html, baseUrl=QUrl( Path(os.path.join(self.book.source_path, "parts", "index.html")).as_uri())) self.htmlReady.disconnect() with self.lock: self.tread_running = False def createHtml(self, text): html = '<html>\n<head>\n' html += '<link href="../css/pastie.css" rel="stylesheet" type="text/css"/>\n' html += '<link href="../css/stylesheet.css" rel="stylesheet" type="text/css"/>\n' html += '</head>\n<body>\n' html += markdown(text, html4tags=False, extras=[ "fenced-code-blocks", "wiki-tables", "tables", "header-ids" ]) html += '\n</body>\n</html>' html = addLineNumbers(html) self.htmlReady.emit(html) def pdfExport(self): p = PdfExport(self.book, self.statusBar()) def spellCheck(self): if not self.filename: QMessageBox.warning( self, QCoreApplication.applicationName(), "You have to select part from the book content first!") return cursor = self.text_edit.textCursor() pos = cursor.position() if not cursor.hasSelection(): cursor.select(QTextCursor.WordUnderCursor) spell = Speller(lang='en') changed = spell(cursor.selectedText()) if changed != cursor.selectedText(): cursor.insertText(changed) self.text_edit.setTextCursor(cursor) def loadPlugins(self): # check if we are running in a frozen environment (pyinstaller --onefile) if getattr(sys, "frozen", False): bundle_dir = sys._MEIPASS # if we are running in a onefile environment, then copy all plugin to /tmp/... if bundle_dir != os.getcwd(): os.mkdir(os.path.join(bundle_dir, "plugins")) for root, dirs, files in os.walk( os.path.join(os.getcwd(), "plugins")): for file in files: shutil.copy(os.path.join(root, file), os.path.join(bundle_dir, "plugins")) print("copy", file) break # do not copy __pycache__ else: bundle_dir = os.getcwd() plugins_dir = os.path.join(bundle_dir, "plugins") for root, dirs, files in os.walk(plugins_dir): for file in files: modulename, ext = os.path.splitext(file) if ext == ".py": module = import_module("plugins." + modulename) for name, klass in inspect.getmembers( module, inspect.isclass): if klass.__module__ == "plugins." + modulename: instance = klass() if isinstance(instance, GeneratorInterface): Plugins.addGeneratorPlugin(name, instance) instance.setTextEdit(self.text_edit) #instance.registerContenType() break # not to list __pycache__
class KeyboardUI(QMainWindow): def __init__(self): super().__init__() self.keyboard() QThread.currentThread().setObjectName('main') self.__work_done=None self.__threads=None self.animation=None self.animation = None def __del__(self): sys.__stdout__ = sys.stdout # 初始化标准输出 sys.__stderr__ = sys.stderr # 初始化标准输出''' def closeEvent(self,event): if self.animation is None: self.animation=QPropertyAnimation(self,"windowOpacity") self.animation.setDuration(300) self.animation.setStartValue(1) self.animation.setEndValue(0) self.animation.finished.connect(self.close) self.animation.start() event.ignore() def keyboard(self): self.setWindowTitle('KeyBoard Test Tool Beta1.0') self.savedStdout = sys.stdout self.savedStderr = sys.stderr sys.stdout = EmittingStream(textWritten=self.normalOutputWritten) # 重新定义系统标准输出 sys.stderr = EmittingStream(textWritten=self.normalOutputWritten) # 重新定义系统标准错误''' mainLayout=QGridLayout() serailLayout=QGridLayout() line1Layout=QHBoxLayout() line2Layout=QHBoxLayout() line3Layout=QHBoxLayout() line4Layout=QHBoxLayout() line5Layout=QHBoxLayout() line6Layout=QHBoxLayout() line7Layout=QHBoxLayout() self.Serial_chose_Widget=QGroupBox('') self.TxtWidget=QTextEdit() self.Txtline=QLineEdit() self.Txtline.setFont(QFont("Roman times",13)) self.runbutton=QPushButton('RUN') self.serial_name_label=QLabel(' 串口') self.serial_name_widget=QComboBox() self.serial_name_widget.addItem("COM1") self.serial_name_widget.addItem("COM2") self.serial_name_widget.addItem("COM3") self.serial_name_widget.addItem("COM4") self.serial_name_widget.addItem("COM5") self.serial_name_widget.addItem("COM6") self.serial_name_widget.addItem("COM7") self.serial_name_widget.addItem("COM8") self.serial_name_widget.addItem("COM9") self.serial_name_widget.addItem("COM10") self.serail_baudrate_label=QLabel("波特率") self.serial_lineedit = QLineEdit() self.Serial_chose_Widget.setLayout(serailLayout) serailLayout.addWidget(self.serial_name_label,0,0,1,2) serailLayout.addWidget(self.serial_name_widget, 0,2,1,3) serailLayout.addWidget(self.serail_baudrate_label,1,0,1,2) serailLayout.addWidget(self.serial_lineedit,1,2,1,3) self.line1widget=QWidget() self.line1widget.setLayout(line1Layout) self.line2widget=QWidget() self.line2widget.setLayout(line2Layout) self.line3widget=QWidget() self.line3widget.setLayout(line3Layout) self.line4widget=QWidget() self.line4widget.setLayout(line4Layout) self.line5widget=QWidget() self.line5widget.setLayout(line5Layout) self.line6widget=QWidget() self.line6widget.setLayout(line6Layout) self.line7widget=QWidget() self.line7widget.setLayout(line7Layout) MainWindow=QWidget() MainWindow.setLayout(mainLayout) self.setCentralWidget(MainWindow) mainLayout.addWidget(self.Serial_chose_Widget,0,0,1,1) mainLayout.addWidget(self.TxtWidget,0,1,1,18) mainLayout.addWidget(self.runbutton,1,0,1,1) mainLayout.addWidget(self.Txtline,1,1,1,18) key_line1=['Esc','F1','F2','F3','F4','F5','F6','F7','F8','F9','F10','F11','F12','Home','End','Insert','Delete'] key_line2=['~\n·\n','!\n1\n','@\n2\n','#\n3\n','$\n4\n','%\n5\n','^\n6\n','&&\n7\n','*\n8\n','(\n9\n',')\n0\n','-\n-\n','+\n=\n','\nBackspace\n'] key_line3=['\nTab\n','\nQ\n','\nW\n','\nE\n','\nR\n','\nT\n','\nY\n','\nU\n','\nI\n','\nO\n','\nP\n','{\n[\n','}\n]\n','|\n\\\n'] key_line4=['\nCaps Lock\n','\nA\n','\nS\n','\nD\n','\nF\n','\nG\n','\nH\n','\nJ\n','\nK\n','\nL\n',':\n;\n','"\n\'\n','\nEnter\n'] key_line5=['\nShift\n','\nZ\n','\nX\n','\nC\n','\nV\n','\nB\n','\nN\n','\nM\n','<\n,\n','>\n.\n','?\n/\n','\nShift\n'] key_line6=['\nFn\n','\nCtrl\n','\n▆▇\n▇▇','\nAlt\n','\n------------------------------------------------------------------\n','\nAlt\n','\nPrtScn\n','\nCtrl\n','\nPgUp\n','\n↑\n','\nPgDn\n'] key_line7=['←','↓','→'] key_line=[] key_line.append(key_line1) key_line.append(key_line2) key_line.append(key_line3) key_line.append(key_line4) key_line.append(key_line5) key_line.append(key_line6) key_line.append(key_line7) self.button=locals() positions1= [ j for j in range(17)] for position,key in zip(positions1,key_line1): self.button['button1_%s'%position]=QPushButton(key) self.button['button1_%s'%position].setFont(QFont("Roman times",8,QFont.Bold)) #self.button['button1_%s'%position].setCheckable(True) #self.button['button1_%s'%position].setAutoExclusive(True) line1Layout.addWidget(self.button['button1_%s'%position],position) mainLayout.addWidget(self.line1widget,2,0,1,19) positions2= [ j for j in range(14)] for position,key in zip(positions2,key_line2): self.button['button2_%s'%position]=QPushButton(key) self.button['button2_%s'%position].setFont(QFont("Roman times",9,QFont.Bold)) line2Layout.addWidget(self.button['button2_%s'%position],position) line2Layout.setSpacing(8) mainLayout.addWidget(self.line2widget,3,0,1,19) positions3= [ j for j in range(14)] for position,key in zip(positions3,key_line3): self.button['button3_%s'%position]=QPushButton(key) self.button['button3_%s'%position].setFont(QFont("Roman times",9,QFont.Bold)) line3Layout.addWidget(self.button['button3_%s'%position],position) line3Layout.setSpacing(10) mainLayout.addWidget(self.line3widget,4,0,1,19) positions4= [ j for j in range(13)] for position,key in zip(positions4,key_line4): self.button['button4_%s'%position]=QPushButton(key) self.button['button4_%s'%position].setFont(QFont("Roman times",9,QFont.Bold)) line4Layout.addWidget(self.button['button4_%s'%position],position) line4Layout.setSpacing(13) mainLayout.addWidget(self.line4widget,5,0,1,19) positions5= [ j for j in range(12)] for position,key in zip(positions5,key_line5): self.button['button5_%s'%position]=QPushButton(key) self.button['button5_%s'%position].setFont(QFont("Roman times",9,QFont.Bold)) line5Layout.addWidget(self.button['button5_%s'%position],position) line5Layout.setSpacing(15) mainLayout.addWidget(self.line5widget,6,0,1,19) positions6= [ j for j in range(11)] for position,key in zip(positions6,key_line6): self.button['button6_%s'%position]=QPushButton(key) self.button['button6_%s'%position].setFont(QFont("Roman times",9,QFont.Bold)) if key=='\n------------------------------------------------------------------\n': self.button['button6_%s'%position].setStyleSheet(''' QPushButton{ color: rgb(211,211,211) ; } ''') line6Layout.addWidget(self.button['button6_%s'%position],position) line6Layout.setSpacing(12) mainLayout.addWidget(self.line6widget,7,0,1,19) positions7= [ j for j in range(3)] for position,key in zip(positions7,key_line7): self.button['button7_%s'%position]=QPushButton(key) self.button['button7_%s'%position].setFont(QFont("Roman times",9,QFont.Bold)) line7Layout.addWidget(self.button['button7_%s'%position],position+8) line7Layout.setSpacing(12) mainLayout.addWidget(self.line7widget,8,14,1,5) self.move(300,150) self.show() def normalOutputWritten(self, text): cursor = self.TxtWidget.textCursor() cursor.movePosition(QTextCursor.End) cursor.insertText(text) self.TxtWidget.setTextCursor(cursor) self.TxtWidget.ensureCursorVisible()
class MainWindow(QMainWindow): siteLoaded = pyqtSignal(object) def __init__(self, app): QMainWindow.__init__(self) self.app = app self.initGui() self.readSettings() self.dashboard.setExpanded(True) self.showDashboard() self.loadDatabase() self.loadClients() self.statusBar().showMessage("Ready") def initGui(self): self.installEventFilter(self) self.dashboard = Expander("Dashboard", ":/images/dashboard_normal.png", ":/images/dashboard_hover.png", ":/images/dashboard_selected.png") self.content = Expander("Clients", ":/images/clients_normal.png", ":/images/clients_hover.png", ":/images/clients_selected.png") self.settings = Expander("Settings", ":/images/settings_normal.png", ":/images/settings_hover.png", ":/images/settings_selected.png") self.setWindowTitle(QCoreApplication.applicationName() + " " + QCoreApplication.applicationVersion()) vbox = QVBoxLayout() vbox.addWidget(self.dashboard) vbox.addWidget(self.content) vbox.addWidget(self.settings) vbox.addStretch() content_box = QVBoxLayout() filter_label = QLabel("Filter") self.filter = QLineEdit() self.filter.textChanged.connect(self.filterChanged) self.client_list = QListWidget() self.client_list.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Fixed) self.client_list.currentItemChanged.connect(self.clientChanged) content_box.addWidget(filter_label) content_box.addWidget(self.filter) content_box.addWidget(self.client_list) self.content.addLayout(content_box) scroll_content = QWidget() scroll_content.setLayout(vbox) scroll = QScrollArea() scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded) scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded) scroll.setWidget(scroll_content) scroll.setWidgetResizable(True) scroll.setMaximumWidth(200) scroll.setMinimumWidth(200) self.navigationdock = QDockWidget("Navigation", self) self.navigationdock.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea) self.navigationdock.setWidget(scroll) self.navigationdock.setObjectName("Navigation") self.addDockWidget(Qt.LeftDockWidgetArea, self.navigationdock) self.showDock = FlatButton(":/images/edit_normal.png", ":/images/edit_hover.png") self.showDock.setToolTip("Show Navigation") self.statusBar().addPermanentWidget(self.showDock) self.dashboard.expanded.connect(self.dashboardExpanded) self.dashboard.clicked.connect(self.showDashboard) self.content.expanded.connect(self.contentExpanded) self.content.clicked.connect(self.showClient) self.settings.expanded.connect(self.settingsExpanded) self.settings.clicked.connect(self.showSettings) self.showDock.clicked.connect(self.showMenu) self.navigationdock.visibilityChanged.connect( self.dockVisibilityChanged) self.client = None self.client_editor = ClientEditor(self) def showDashboard(self): db = Dashboard() db.createSite.connect(self.addClient) self.setCentralWidget(db) def showClient(self): self.setCentralWidget(self.client_editor) def showSettings(self): s = SettingsEditor(self) self.setCentralWidget(s) def setCentralWidget(self, widget): old_widget = self.takeCentralWidget() super().setCentralWidget(widget) widget.show() def closeEvent(self, event): self.writeSettings() event.accept() def writeSettings(self): settings = QSettings(QSettings.IniFormat, QSettings.UserScope, QCoreApplication.organizationName(), QCoreApplication.applicationName()) settings.setValue("geometry", self.saveGeometry()) settings.setValue("state", self.saveState()) settings.setValue("databaseFile", self.databaseFile) settings.setValue("fontSize", str(self.fontSize)) def readSettings(self): settings = QSettings(QSettings.IniFormat, QSettings.UserScope, QCoreApplication.organizationName(), QCoreApplication.applicationName()) geometry = settings.value("geometry", QByteArray()) if geometry.isEmpty(): availableGeometry = QApplication.desktop().availableGeometry(self) self.resize(availableGeometry.width() / 3, availableGeometry.height() / 2) self.move(int(((availableGeometry.width() - self.width()) / 2)), int((availableGeometry.height() - self.height()) / 2)) else: self.restoreGeometry(geometry) self.restoreState(settings.value("state")) self.databaseFile = settings.value("databaseFile") if not self.databaseFile: self.databaseFile = "maria.json" fs = settings.value("fontSize") if not fs: fs = 10 self.fontSize = int(fs) font = QFont("Sans Serif", self.fontSize) self.app.setFont(font) def dashboardExpanded(self, value): if value: self.content.setExpanded(False) self.settings.setExpanded(False) def contentExpanded(self, value): if value: self.dashboard.setExpanded(False) self.settings.setExpanded(False) def settingsExpanded(self, value): if value: self.dashboard.setExpanded(False) self.content.setExpanded(False) def showMenu(self): self.navigationdock.setVisible(True) def dockVisibilityChanged(self, visible): self.showDock.setVisible(not visible) def animate(self, item): panel = self.centralWidget() self.list = item.tableWidget() self.row = item.row() # create a cell widget to get the right position in the table self.cellWidget = QWidget() self.cellWidget.setMaximumHeight(0) self.list.setCellWidget(self.row, 1, self.cellWidget) pos = self.cellWidget.mapTo(panel, QPoint(0, 0)) self.editor.setParent(panel) self.editor.move(pos) self.editor.resize(self.cellWidget.size()) self.editor.show() self.animation = QPropertyAnimation(self.editor, "geometry".encode("utf-8")) self.animation.setDuration(300) self.animation.setStartValue( QRect(pos.x(), pos.y(), self.cellWidget.size().width(), self.cellWidget.size().height())) self.animation.setEndValue( QRect(0, 0, panel.size().width(), panel.size().height())) self.animation.start() def editorClosed(self): pos = self.cellWidget.mapTo(self.centralWidget(), QPoint(0, 0)) # correct end values in case of resizing the window self.animation.setStartValue( QRect(pos.x(), pos.y(), self.cellWidget.size().width(), self.cellWidget.size().height())) self.animation.finished.connect(self.animationFineshedZoomOut) self.animation.setDirection(QAbstractAnimation.Backward) self.animation.start() def animationFineshedZoomOut(self): self.list.removeCellWidget(self.row, 1) del self.animation # in the case self.editor was a MenuEditor, we have to unregister it in the MenuList # should be refactored some day :-) list = self.centralWidget() if list is MenuEditor: list.unregisterMenuEditor() del self.editor self.editor = None if self.method_after_animation == "showDashboard": self.showDashboard() self.method_after_animation = "" elif self.method_after_animation == "showSettings": self.showSettings() if self.content_after_animation: self.previewSite(self.content_after_animation) self.content_after_animation = None def filterChanged(self): self.loadClients() def loadDatabase(self): self.db = TinyDB(self.databaseFile) self.clients = self.db.table('Clients') def updateClient(self): for i in range(self.client_list.count()): item = self.client_list.item(i) c = item.data(3) if c.doc_id == self.client.doc_id: item.setData(3, self.client) item.setText(self.client["name"]) break def loadClients(self): self.client_list.clear() filter = self.filter.text() a = [] for c in self.clients: if filter in c["name"]: a.append(c) s = sorted(a, key=namesort) for c in s: item = QListWidgetItem() item.setText(c["name"]) item.setData(3, c) self.client_list.addItem(item) self.client_list.setCurrentRow(0) def addClient(self): now = datetime.now() newclient = { "number": "", "name": "", "birthday_year": 1990, "birthday_month": 1, "birthday_day": 1, "profession": "", "address": "", "mobile": "", "email": "", "reason": "", "fiscal": "", "how": "", "first_contact_year": now.year, "first_contact_month": now.month, "first_contact_day": now.day, "notes": "" } self.clients.insert(newclient) self.showClient() self.loadClients() q = Query() self.client = self.clients.get(q.name == "") self.client["name"] = "" self.client_editor.reload() def clientChanged(self, item): if item: self.client = item.data(3) self.client_editor.reload() else: self.client = None self.client_editor.reload()
class Platform(QWidget): def __init__(self): super(Platform, self).__init__() self._desktop = QApplication.instance().desktop() self.__dir = os.path.dirname(os.path.dirname( os.path.abspath(__file__))) self.__WebContent() self.__initPosition() self.__connectJs() print("启动desk") def __WebContent(self): self.resize(self._desktop.screenGeometry().width() / 5, self._desktop.availableGeometry().height()) self.verticalLayout = QtWidgets.QVBoxLayout(self) self.verticalLayout.setContentsMargins(0, 0, 0, 0) self.webView = QWebView() # BASE_DIR = os.path.dirname(os.path.dirname(__file__)) # new = os.path.join(BASE_DIR, 'web') # # new_file_name = os.path.join(new, 'noticeContent.html') # fname = 'file:///'+new_file_name # print(fname) # self.webView.load(QUrl('file:///C:/Users/Administrator/Desktop/app/mainWin/desk/web/desk.html')) print('file:///' + self.__dir + '/web/desk.html') self.webView.load(QUrl('file:///' + self.__dir + '/web/desk.html')) # self.webView.load(QUrl(fname)) self.verticalLayout.addWidget(self.webView) # self.webView.loadFinished.connect(self.test) def onClose(self): #点击关闭按钮时 self.isShow = False QTimer.singleShot(100, self.closeAnimation) #启动弹回动画 def __initPosition(self): # 隐藏任务栏|去掉边框|顶层显示 self.setWindowFlags(Qt.Tool | Qt.X11BypassWindowManagerHint | Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint) # 是否在显示标志 self.isShow = True # 桌面 # self._desktop = QApplication.instance().desktop() # 窗口初始开始位置 self._startPos = QPoint( self._desktop.screenGeometry().width(), self._desktop.availableGeometry().height() - self.height()) print(self._startPos) # 窗口弹出结束位置 self._endPos = QPoint( self._desktop.screenGeometry().width() - self.width(), self._desktop.availableGeometry().height() - self.height()) print(self._endPos) # 初始化位置到右侧 self.move(self._startPos) # 动画 self.animation = QPropertyAnimation(self, b"pos") self.hide() # 先隐藏 super(Platform, self).show() def __connectJs(self): connector = ConnectJs(self) self.webView.page().mainFrame().javaScriptWindowObjectCleared.connect( lambda: self.webView.page().mainFrame( ).addToJavaScriptWindowObject('pyNotice', connector)) def add(self, content=""): if content: self.__notice_list.insert(0, content) self.webView.page().mainFrame().evaluateJavaScript( "pyNoticeAdd(%s)" % str(content)) def show(self, title="", content=""): # 显示动画 self.isShow = True self.animation.setStartValue(self.pos()) self.animation.setEndValue(self._endPos) self.animation.start() def closeAnimation(self): self.isShow = False self.animation.setStartValue(self.pos()) self.animation.setEndValue(self._startPos) self.animation.start()
class Point(QObject): valueChanged = pyqtSignal() def __init__(self, x, ox, y, oy, *args, **kwargs): super(Point, self).__init__(*args, **kwargs) self.__x = x self._x = x self.originX = ox self._y = y self.__y = y self.originY = oy # 5个闭合点 self.closest = [0, 0, 0, 0, 0] # 圆半径 self.radius = 2 + random() * 2 # 连线颜色 self.lineColor = QColor(156, 217, 249) # 圆颜色 self.circleColor = QColor(156, 217, 249) def initAnimation(self): # 属性动画 if not hasattr(self, 'xanimation'): self.xanimation = QPropertyAnimation( self, b'x', self, valueChanged=self.valueChanged.emit, easingCurve=QEasingCurve.InOutSine) self.yanimation = QPropertyAnimation( self, b'y', self, valueChanged=self.valueChanged.emit, easingCurve=QEasingCurve.InOutSine, finished=self.updateAnimation) self.updateAnimation() def updateAnimation(self): self.xanimation.stop() self.yanimation.stop() duration = (1 + random()) * 1000 self.xanimation.setDuration(duration) self.yanimation.setDuration(duration) self.xanimation.setStartValue(self.__x) self.xanimation.setEndValue(self.originX - 50 + random() * 100) self.yanimation.setStartValue(self.__y) self.yanimation.setEndValue(self.originY - 50 + random() * 100) self.xanimation.start() self.yanimation.start() @pyqtProperty(float) def x(self): return self._x @x.setter def x(self, x): self._x = x @pyqtProperty(float) def y(self): return self._y @y.setter def y(self, y): self._y = y
def __init__(self): super().__init__() self.setBackgroundBrush(QBrush(QPixmap(':/images/background.png'))) self.skill_label = self.addSimpleText(Config.UserName, Config.BigFont) self.skill_label.setPos(-400, -100) self.photos = list() group = QParallelAnimationGroup(self) for i in range(7): photo = Photo() self.photos.append(photo) self.addItem(photo) x = i * photo.boundingRect().width() + Config.Rect.x() y = Config.Rect.y() + 10 duration = 1500.0 * qrand() / RAND_MAX translation = QPropertyAnimation(photo, bytes("pos", 'utf-8')) translation.setEndValue(QPointF(x, y)) translation.setEasingCurve(QEasingCurve.OutBounce) translation.setDuration(duration) group.addAnimation(translation) self.photos[0].loadAvatar("generals/small/caocao.png") self.photos[1].loadAvatar("generals/small/liubei.png") self.photos[2].loadAvatar("generals/small/sunquan.png") self.photos[3].loadAvatar("generals/small/simayi.png") self.photos[4].loadAvatar("generals/small/guojia.png") self.photos[5].loadAvatar("generals/small/zhugeliang.png") self.photos[6].loadAvatar("generals/small/zhouyu.png") self.dashboard = Dashboard() self.dashboard.setGeneral(General("caocao", "wei", 4, True)) self.addItem(self.dashboard) start_pos = Config.Rect.topLeft() end_pos = QPointF( Config.Rect.x(), Config.Rect.bottom() - self.dashboard.boundingRect().height()) duration = 1500 translation = QPropertyAnimation(self.dashboard, bytes("pos", 'utf-8')) translation.setStartValue(start_pos) translation.setEndValue(end_pos) translation.setEasingCurve(QEasingCurve.OutBounce) translation.setDuration(duration) enlarge = QPropertyAnimation(self.dashboard, bytes("scale", 'utf-8')) enlarge.setStartValue(0.2) enlarge.setEndValue(1.0) enlarge.setEasingCurve(QEasingCurve.OutBounce) enlarge.setDuration(duration) group.addAnimation(translation) group.addAnimation(enlarge) group.start(QAbstractAnimation.DeleteWhenStopped) card1 = Card("savage_assault", Card.Spade, 1) card2 = Card("slash", Card.Club, 7) card3 = Card("jink", Card.Heart, 2) card4 = Card("peach", Card.Diamond, 10) card5 = Card("archery_attack", Card.Heart, 11) card6 = Card("crossbow", Card.Club, 12) self.dashboard.addCard(card1) self.dashboard.addCard(card2) self.dashboard.addCard(card3) self.dashboard.addCard(card4) self.dashboard.addCard(card5) self.dashboard.addCard(card6) card4.setEnabled(False)
class BlueApp: def __init__(self, argv): self.app = QApplication(argv) self.mainWindow = QtWidgets.QMainWindow() self.mainWindow.closeEvent = self.onClose self.ui = blueMainUi.Ui_MainWindow() self.ui.setupUi(self.mainWindow) #settings and statistics self.defaultSettings = dict(image_detect=True, text_detect=True, game_type=0, pipeRank=0, goal = 10, startDate = time.time(), avata = "res/icon.png", name = "窜天猴") self.defaultStat = dict(stat = [ [0, 0, 0, 0] for i in range(7)], achivement = 0, lastWater = 0, lastFertilize = 0, cleanHours = 0, cleanMinutes = 0) self.achivementsList = ["大淫魔", "从头开始", "欲火渐盛", "钢筋铁骨", "渐入佳境","心无杂念"] self.achivementsStd = [0, 24, 24 * 3, 24 * 7, 24 * 31, 27 * 365] self.loadSettings() self.validateSettings() self.loadStatistics() #setup the visibles self.setupUi2() self.setupWidget1() self.setupWidget2() self.setupWidget3() self.setupWidget4() self.refreshStatistics() #setup porn_detector self.devMode = False self.timeToExit = False self.pornDectector = porn_detector_final.PornDetector() self.pornDetected = False self.detectThread = threading.Thread(target = self.detectPorn) self.detectThread.start() self.alarm = False #first alarm, then take action #setup timer self.cleanMinute = 0 self.MinuteTimer = QTimer() self.MinuteTimer.setInterval(1000 * 60) self.MinuteTimer.timeout.connect(self.addCleanMinute) self.MinuteTimer.start() #lauch self.mainWindow.show() self.connections() def addCleanMinute(self): self.stat["cleanMinutes"] += 1 if self.stat["cleanMinutes"] == 60: self.self.stat["cleanMinutes"] = 0 self.stat["cleanHours"] += 1 self.saveStatistics() self.refreshStatistics() self.checkLevel() def call_zqz(self): if self.settings["game_type"] == 0: os.system("python2 easy_maze/PyMaze.py") else : os.system("python2 esay_game/play.py") QtWidgets.QMessageBox.information(None, "bluer", "你有10s的时间关掉黄黄的东西。") time.sleep(10) def detectPorn(self): while(True): if "PORN_DETECTED" == self.pornDectector.porn_detector(self.settings["image_detect"], self.settings["text_detect"], self.devMode): if self.alarm: self.call_zqz() self.stat["cleanHours"] -= 24 if self.stat["cleanHours"] < 0: self.stat["cleanHours"] = 0 l = self.stat["stat"][time.localtime(time.time())[6]] h = time.localtime(time.time())[3] if h >= 0 and h < 6: l[0] = 1 elif h >= 6 and h < 12: l[1] = 1 elif h >= 12 and h < 18: l[2] = 1; else: l[3] = 1; else: self.alarm = True else: self.alarm = True self.saveStatistics() self.refreshStatistics() time.sleep(10) def onClose(self, event): self.mainWindow.hide() event.ignore() def onTrayClicked(self, event): if event == QSystemTrayIcon.Trigger or event == QSystemTrayIcon.DoubleClick: self.mainWindow.show() def saveSettings(self, event): QtWidgets.QMessageBox.Question = QIcon("res/logo-tray.png") if self.settings["goal"] != self.ui.spin_goal.value(): ret = QtWidgets.QMessageBox.question(self.mainWindow, "Blue", "确定要将目标改为" + str(self.ui.spin_goal.value()) + "天吗?\n" "此操作会重置当前任务的进度。") if ret != QtWidgets.QMessageBox.No: self.settings["goal"] = self.ui.spin_goal.value() self.saveStatistics() self.refreshStatistics() QtWidgets.QMessageBox.information(None, "Blue", "新目标设置为" + str(self.settings["goal"]) + "天") else: QtWidgets.QMessageBox.information(None, "Blue", "目标没有被重置") try: sfile = open(PATH_TO_SETTINGS, "w") json.dump(self.settings, sfile) sfile.close() except Exception: return QtWidgets.QMessageBox.information(None, "Blue", "设置已保存:D") self.refreshStatistics() def checkLevel(self): for i in range(5, -1, -1): if self.stat["cleanHours"] >= self.achivementsStd[i] and self.stat["achivement"] < i: QtWidgets.QMessageBox.information(None, "Blue", "等级提升为Lv. " + str(i) + " :" + self.achivementsList[i]) self.stat["achivement"] = i self.saveStatistics() break def saveStatistics(self): json.dump(self.stat, open(PATH_TO_STATISTICS, "w")) def refreshStatistics(self): days = time.localtime(time.time()) delta = self.settings["goal"] - self.stat["cleanHours"] if delta == 0: QtWidgets.QMessageBox.information(None, "Blue", "目标达成!!!\n请设置新的目标!!!") self.slideClicked3(None) self.ui.lb_days.setText(str(delta)) self.ui.lb_goal.setText(str(self.settings["goal"])) self.ui.lb_achv.setText(self.achivementsList[self.stat["achivement"]]) self.ui.lb_lv.setText("Lv. " + str(self.stat["achivement"])) self.ui.lb_growth.setText(str(self.stat["cleanHours"] // 24)) #setup the water and ferilization if days[7] == time.localtime(self.stat["lastWater"])[7]: self.ui.lb_jiaoshui.setPixmap(QPixmap("res/ack.png")) self.watered = True else: self.watered = False if days[7] == time.localtime(self.stat["lastFertilize"])[7]: self.ui.lb_shifei.setPixmap(QPixmap("res/ack.png")) self.fertilized = True else: self.fertilized = False #setup the calendar pixmapA = QPixmap("res/lu.png") pixmapB = QPixmap("res/blue.png") h = days[3] if h >= 0 and h < 6: r = 0 elif h >= 6 and h < 12: r = 1 elif h >= 12 and h < 18: r = 2 else: r = 3 for i in range(days[6]): for j in range(4): if self.stat["stat"][i][j] == 0: self.statLabels[i][j].setPixmap(pixmapA) else: self.statLabels[i][j].setPixmap(pixmapB) day = days[6] for j in range(r): if self.stat["stat"][day][j] == 0: self.statLabels[day][j].setPixmap(pixmapA) else: self.statLabels[day][j].setPixmap(pixmapB) #setup the wall for i in range(6): self.achivIcons[i].setPixmap(QPixmap("res/" + str(i) * 2)) for i in range(self.stat["achivement"] + 1): self.achivIcons[i].setPixmap(QPixmap("res/" + str(i))) def loadSettings(self): try: sfile = open(PATH_TO_SETTINGS, "r") self.settings = json.load(sfile) sfile.close() except: self.settings = self.defaultSettings self.saveSettings(None) def validateSettings(self): for keys in self.defaultSettings: try: self.settings[keys] except: self.settings[keys] = self.defaultSettings[keys] def loadStatistics(self): try: sfile = open(PATH_TO_STATISTICS, "r") self.stat = json.load(sfile) except: self.stat = self.defaultStat for keys in self.defaultStat: try: self.stat[keys] except: self.stat[keys] = self.defaultStat[keys] self.saveStatistics() def refreshInfo(self): #setup avata pixmap = QPixmap() pixmap.load("res/avata_mask") pixmap.scaled(115, 115) self.ui.lb_avata.setMask(pixmap.mask()) pixmap.load(self.settings["avata"]) self.ui.lb_avata.setPixmap(pixmap) # self.ui.lb_avata2.setMask(pixmap.mask()) # pixmap.load(self.settings["avata"]) # self.ui.lb_avata2.setPixmap(pixmap) #setup the name self.ui.lb_welcomname.setText(self.settings["name"]) self.ui.lb_nick.setText(self.settings["name"]) def appExit(self, event): if self.devMode == False: QtWidgets.QMessageBox.information(None, "bluer", "开发者模式开启") self.devMode = True else: QtWidgets.QMessageBox.information(None, "bluer", "开发者模式关闭") self.devMode = False def avataEdit(self, event): openDlg = QtWidgets.QFontDialog() openDlg.open() def setupUi2(self): #setup event handling self.sideButtons = [self.ui.lb1, self.ui.lb2, self.ui.lb3, self.ui.lb4] self.ui.lb_exit.mousePressEvent = self.appExit self.setupAnimes() self.setupSideButtons() self.refreshInfo() #setup tray self.icon = QIcon("res/logo-tray.png") self.trayIcon = QSystemTrayIcon() self.trayIcon.setIcon(self.icon) self.trayIcon.activated.connect(self.onTrayClicked) self.trayIcon.show() #setup the info edit self.ui.lb_avata.mousePressEvent = self.avataEdit def setupAnimes(self): self.shiftAnime1 = QPropertyAnimation() self.shiftAnime1.setTargetObject(self.ui.widget1) self.shiftAnime1.setPropertyName("geometry".encode()) self.shiftAnime1.setDuration(400) self.shiftAnime1.setStartValue(QRect(177, 29, 0, 571)) self.shiftAnime1.setEndValue(QRect(177, 29, 623, 571)) self.shiftAnime2 = QPropertyAnimation() self.shiftAnime2.setTargetObject(self.ui.widget2) self.shiftAnime2.setPropertyName("geometry".encode()) self.shiftAnime2.setDuration(400) self.shiftAnime2.setStartValue(QRect(800, 29, 0, 571)) self.shiftAnime2.setEndValue(QRect(177, 29, 623, 571)) self.shiftAnime3 = QPropertyAnimation() self.shiftAnime3.setTargetObject(self.ui.widget3) self.shiftAnime3.setPropertyName("geometry".encode()) self.shiftAnime3.setDuration(400) self.shiftAnime3.setStartValue(QRect(800, 29, 623, 571)) self.shiftAnime3.setEndValue(QRect(177, 29, 623, 571)) self.shiftAnime4 = QPropertyAnimation() self.shiftAnime4.setTargetObject(self.ui.widget4) self.shiftAnime4.setPropertyName("geometry".encode()) self.shiftAnime4.setDuration(400) self.shiftAnime4.setStartValue(QRect(800, 29, 623, 571)) self.shiftAnime4.setEndValue(QRect(177, 29, 623, 571)) self.selectedWidget = self.ui.widget1 def setSlideMid(self, bt): if self.selectedSideButton != bt: bt.setStyleSheet(slide_bt_mid) def setSlideUp(self, bt): if self.selectedSideButton != bt: bt.setStyleSheet(slide_bt_up) def setSlideDown(self, bt): self.selectedSideButton.setStyleSheet(slide_bt_up) self.selectedSideButton = bt bt.setStyleSheet(slide_bt_down) def slideEnter1(self, event): self.setSlideMid(self.ui.lb1) def slideEnter2(self, event): self.setSlideMid(self.ui.lb2) def slideEnter3(self, event): self.setSlideMid(self.ui.lb3) def slideEnter4(self, event): self.setSlideMid(self.ui.lb4) def slideLeave1(self, event): self.setSlideUp(self.ui.lb1) def slideLeave2(self, event): self.setSlideUp(self.ui.lb2) def slideLeave3(self, event): self.setSlideUp(self.ui.lb3) def slideLeave4(self, event): self.setSlideUp(self.ui.lb4) def slideBack(self, event): self.setSlideDown(self.ui.lb1) self.ui.widget1.raise_() self.shiftAnime1.start() self.selectedWidget = self.ui.widget1 def slideClicked1(self, event): self.setSlideDown(self.ui.lb1) if self.selectedWidget != self.ui.widget1: self.ui.widget1.raise_() self.shiftAnime1.start() self.selectedWidget = self.ui.widget1 def slideClicked2(self, event): self.setSlideDown(self.ui.lb2) if self.selectedWidget != self.ui.widget2: self.ui.widget2.raise_() self.shiftAnime2.start() self.selectedWidget = self.ui.widget2 def slideClicked3(self, event): self.setSlideDown(self.ui.lb3) if self.selectedWidget != self.ui.widget3: self.ui.widget3.raise_() self.shiftAnime3.start() self.selectedWidget = self.ui.widget3 def jiaoshuiCheck(self, event): pixmap = QPixmap() pixmap.load("res/ack.png") self.ui.lb_jiaoshui.setPixmap(pixmap) self.stat["lastWater"] = time.time() self.saveStatistics() def shifeiCheck(self, event): pixmap = QPixmap() pixmap.load("res/ack.png") self.ui.lb_shifei.setPixmap(pixmap) self.stat["lastFertilize"] = time.time() self.saveStatistics() def slideClicked4(self, event): self.setSlideDown(self.ui.lb4) if self.selectedWidget != self.ui.widget4: self.ui.widget4.raise_() self.shiftAnime4.start() self.selectedWidget = self.ui.widget4 def setupWidget1(self): #setup the tree movie = QMovie() movie.setFileName("res/tree.gif") self.ui.lb_tree.setMovie(movie) self.ui.lb_tree_big.setMovie(movie) movie.start() #setup the statistics self.ui.gridLayout.setHorizontalSpacing(60) self.ui.gridLayout.setVerticalSpacing(10) self.ui.gridLayout.setGeometry(QRect(0, 51, 291, 224)) self.ui.gridLayout.setAlignment(QtCore.Qt.AlignCenter) self.statLabels = [] for i in range(7): self.statLabels.append([]) for j in range(4): self.statLabels[i].append(QLabel()) self.statLabels[i][j].setScaledContents(True) self.statLabels[i][j].setAutoFillBackground(False) self.statLabels[i][j].setAlignment(QtCore.Qt.AlignCenter) self.ui.gridLayout.addWidget(self.statLabels[i][j], i, j, 1, 1) def setupWidget2(self): self.ui.lb_jiaoshui.mousePressEvent = self.jiaoshuiCheck self.ui.lb_shifei.mousePressEvent = self.shifeiCheck def setupWidget3(self): self.ui.check_maze.mousePressEvent = self.mazeCliked self.ui.check_paper.mousePressEvent = self.paperCliked self.ui.check_pic.mousePressEvent = self.picCliked self.ui.check_text.mousePressEvent = self.textClicked self.ui.lb_save.mousePressEvent = self.saveSettings self.ui.spin_goal.setValue(self.settings["goal"]) if self.settings["game_type"] == 0: self.mazeCliked(None) else: self.paperCliked(None) self.picCliked(None) self.picCliked(None) self.textClicked(None) self.textClicked(None) def setupWidget4(self): self.achivIcons = [self.ui.lb_a0, self.ui.lb_a1, self.ui.lb_a2, self.ui.lb_a3, self.ui.lb_a4, self.ui.lb_a5] for i in range(6): self.achivIcons[i].setPixmap(QPixmap("res/" + str(i) * 2)) def mazeCliked(self, event): pixmap = QPixmap() pixmap.load("res/checked.png") self.ui.check_maze.setPixmap(pixmap) pixmap.load("res/unchecked.png") self.ui.check_paper.setPixmap(pixmap) self.settings["game_type"] = 0 def paperCliked(self, event): pixmap = QPixmap() pixmap.load("res/checked.png") self.ui.check_paper.setPixmap(pixmap) pixmap.load("res/unchecked.png") self.ui.check_maze.setPixmap(pixmap) self.settings["game_type"] = 1 def picCliked(self, event): pixmap = QPixmap() pixmap.load("res/checked.png") self.ui.check_pic.setPixmap(pixmap) pixmap.load("res/unchecked.png") self.ui.check_text.setPixmap(pixmap) self.settings["pic_detect"] = 1 self.settings["text_detect"] = 0 def textClicked(self, event): pixmap = QPixmap() pixmap.load("res/checked.png") self.ui.check_text.setPixmap(pixmap) pixmap.load("res/unchecked.png") self.ui.check_pic.setPixmap(pixmap) self.settings["pic_detect"] = 1 self.settings["text_detect"] = 1 def setupSideButtons(self): self.ui.lb1.enterEvent = self.slideEnter1 self.ui.lb1.leaveEvent = self.slideLeave1 self.ui.lb1.mousePressEvent = self.slideClicked1 self.ui.lb2.enterEvent = self.slideEnter2 self.ui.lb2.leaveEvent = self.slideLeave2 self.ui.lb2.mousePressEvent = self.slideClicked2 self.ui.lb3.enterEvent = self.slideEnter3 self.ui.lb3.leaveEvent = self.slideLeave3 self.ui.lb3.mousePressEvent = self.slideClicked3 self.ui.lb4.enterEvent = self.slideEnter4 self.ui.lb4.leaveEvent = self.slideLeave4 self.ui.lb4.mousePressEvent = self.slideClicked4 self.ui.lb4.enterEvent = self.slideEnter4 self.ui.lb4.leaveEvent = self.slideLeave4 self.ui.lb4.mousePressEvent = self.slideClicked4 self.ui.lb_back2.mousePressEvent = self.slideBack self.ui.lb_back3.mousePressEvent = self.slideBack self.ui.lb_back4.mousePressEvent = self.slideBack for lb in self.sideButtons: lb.setStyleSheet(slide_bt_up) self.selectedSideButton = self.ui.lb1 self.slideClicked1(None) def connections(self): pass
class Widgets(QWidget): def __init__(self, parent=None): super(Widgets, self).__init__(parent) self.parent = parent self.initUI() def initUI(self): # ======================== WIDGETS =========================== framePrincipal = QFrame(self) framePrincipal.setFrameShape(QFrame.Box) framePrincipal.setFrameShadow(QFrame.Sunken) framePrincipal.setAutoFillBackground(True) framePrincipal.setBackgroundRole(QPalette.Light) framePrincipal.setFixedSize(662, 503) framePrincipal.move(10, 10) frame = QFrame(framePrincipal) frame.setFixedSize(640, 480) frame.move(10, 10) self.labelImagen = QLabel(frame) self.labelImagen.setAlignment(Qt.AlignCenter) self.labelImagen.setGeometry(0, 0, 640, 480) # self.labelImagen.setScaledContents(True) self.labelImagenUno = QLabel(frame) self.labelImagenUno.setAlignment(Qt.AlignCenter) self.labelImagenUno.setGeometry(-650, 0, 640, 480) # =================== BOTONES (QPUSHBUTTON) ================== self.buttonCargar = QPushButton("Cargar imagen", self) self.buttonCargar.setCursor(Qt.PointingHandCursor) self.buttonCargar.setFixedSize(325, 30) self.buttonCargar.move(10, 519) self.buttonEliminar = QPushButton("Eliminar imagen", self) self.buttonEliminar.setCursor(Qt.PointingHandCursor) self.buttonEliminar.setFixedSize(255, 30) self.buttonEliminar.move(345, 519) self.buttonAnterior = QPushButton("<", self) self.buttonAnterior.setObjectName("Anterior") self.buttonAnterior.setToolTip("Imagen anterior") self.buttonAnterior.setCursor(Qt.PointingHandCursor) self.buttonAnterior.setFixedSize(30, 30) self.buttonAnterior.move(607, 519) self.buttonSiguiente = QPushButton(">", self) self.buttonSiguiente.setObjectName("Siguiente") self.buttonSiguiente.setToolTip("Imagen siguiente") self.buttonSiguiente.setCursor(Qt.PointingHandCursor) self.buttonSiguiente.setFixedSize(30, 30) self.buttonSiguiente.move(642, 519) # ===================== CONECTAR SEÑALES ===================== self.buttonCargar.clicked.connect(self.Cargar) self.buttonEliminar.clicked.connect(self.Eliminar) self.buttonAnterior.clicked.connect(self.anteriorSiguiente) self.buttonSiguiente.clicked.connect(self.anteriorSiguiente) # Establecer los valores predeterminados self.posicion = int self.estadoAnterior, self.estadoSiguiente = False, False self.carpetaActual = QDir() self.imagenesCarpeta = [] # ======================= FUNCIONES ============================== def bloquearBotones(self, bool): self.buttonCargar.setEnabled(bool) self.buttonEliminar.setEnabled(bool) self.buttonAnterior.setEnabled(bool) self.buttonSiguiente.setEnabled(bool) def Mostrar(self, label, imagen, nombre, posicionX=650): imagen = QPixmap.fromImage(imagen) # Escalar imagen a 640x480 si el ancho es mayor a 640 o el alto mayor a 480 if imagen.width() > 640 or imagen.height() > 480: imagen = imagen.scaled(640, 480, Qt.KeepAspectRatio, Qt.SmoothTransformation) # Mostrar imagen label.setPixmap(imagen) # Animación (al finalizar la animación se muestra en la barra de estado el nombre y la extensión de la imagen # y se desbloquean los botones). self.animacionMostar = QPropertyAnimation(label, b"geometry") self.animacionMostar.finished.connect( lambda: (self.parent.statusBar.showMessage(nombre), self.bloquearBotones(True))) self.animacionMostar.setDuration(200) self.animacionMostar.setStartValue(QRect(posicionX, 0, 640, 480)) self.animacionMostar.setEndValue(QRect(0, 0, 640, 480)) self.animacionMostar.start(QAbstractAnimation.DeleteWhenStopped) def Limpiar(self, labelConImagen, labelMostrarImagen, imagen, nombre, posicionInternaX, posicionX=None): def Continuar(estado): if estado: if posicionX: self.Mostrar(labelMostrarImagen, imagen, nombre, posicionX) else: self.Mostrar(labelMostrarImagen, imagen, nombre) self.animacionLimpiar = QPropertyAnimation(labelConImagen, b"geometry") self.animacionLimpiar.finished.connect(lambda: labelConImagen.clear()) self.animacionLimpiar.setDuration(200) # self.animacionLimpiar.valueChanged.connect(lambda x: print(x)) self.animacionLimpiar.stateChanged.connect(Continuar) self.animacionLimpiar.setStartValue(QRect(0, 0, 640, 480)) self.animacionLimpiar.setEndValue(QRect(posicionInternaX, 0, 640, 480)) self.animacionLimpiar.start(QAbstractAnimation.DeleteWhenStopped) def Cargar(self): nombreImagen, _ = QFileDialog.getOpenFileName( self, "Seleccionar imagen", QDir.currentPath(), "Archivos de imagen (*.jpg *.png *.ico *.bmp)") if nombreImagen: # Verificar que QLabel tiene imagen labelConImagen = "" if self.labelImagen.pixmap(): labelConImagen = self.labelImagen elif self.labelImagenUno.pixmap(): labelConImagen = self.labelImagenUno imagen = QImage(nombreImagen) if imagen.isNull(): if labelConImagen: self.Eliminar() QMessageBox.information( self, "Visor de imágenes", "No se puede cargar %s." % nombreImagen) return # Obtener ruta de la carpeta que contiene la imagen seleccionada self.carpetaActual = QDir( QFileInfo(nombreImagen).absoluteDir().path()) # Obtener la ruta y el nombre de las imagenes que se encuentren en la carpeta de # la imagen seleccionada imagenes = self.carpetaActual.entryInfoList( ["*.jpg", "*.png", "*.ico", "*.bmp"], QDir.Files, QDir.Name) self.imagenesCarpeta = [ imagen.absoluteFilePath() for imagen in imagenes ] self.posicion = self.imagenesCarpeta.index(nombreImagen) self.estadoAnterior = True if self.posicion == 0 else False self.estadoSiguiente = True if self.posicion == len( self.imagenesCarpeta) - 1 else False # Función encargada de bloquear o desbloquear los botones self.bloquearBotones(False) # Nombre y extensión de la imagen nombre = QFileInfo(nombreImagen).fileName() if labelConImagen: posicionInternaX = -650 labelMostrarImagen = self.labelImagen if self.labelImagenUno.pixmap( ) else self.labelImagenUno self.Limpiar(labelConImagen, labelMostrarImagen, imagen, nombre, posicionInternaX) else: self.Mostrar(self.labelImagen, imagen, nombre) def Eliminar(self): def establecerValores(): labelConImagen.clear() labelConImagen.move(0, 0) # Limpiar la barra de estado self.parent.statusBar.clearMessage() # Establecer los valores predeterminados self.posicion = int self.estadoAnterior, self.estadoSiguiente = False, False self.carpetaActual = QDir() self.imagenesCarpeta.clear() self.bloquearBotones(True) # Verificar que QLabel tiene imagen labelConImagen = "" if self.labelImagen.pixmap(): labelConImagen = self.labelImagen elif self.labelImagenUno.pixmap(): labelConImagen = self.labelImagenUno if labelConImagen: self.bloquearBotones(False) self.animacionEliminar = QPropertyAnimation( labelConImagen, b"geometry") self.animacionEliminar.finished.connect(establecerValores) self.animacionEliminar.setDuration(200) self.animacionEliminar.setStartValue(QRect(0, 0, 640, 480)) self.animacionEliminar.setEndValue(QRect(-650, 0, 640, 480)) self.animacionEliminar.start(QAbstractAnimation.DeleteWhenStopped) def anteriorSiguiente(self): if self.imagenesCarpeta: widget = self.sender().objectName() if widget == "Anterior": self.estadoAnterior = True if self.posicion == 0 else False self.estadoSiguiente = False self.posicion -= 1 if self.posicion > 0 else 0 posicionInternaX, posicionX = 650, -650 else: self.estadoSiguiente = True if self.posicion == len( self.imagenesCarpeta) - 1 else False self.estadoAnterior = False self.posicion += 1 if self.posicion < len( self.imagenesCarpeta) - 1 else 0 posicionInternaX, posicionX = -650, 650 if self.estadoAnterior or self.estadoSiguiente: return else: imagen = self.imagenesCarpeta[self.posicion] # Verificar que la carpeta que contiene la imagene exista if not QDir(self.carpetaActual).exists(): self.Eliminar() return elif not QFile.exists(imagen): # Obtener la ruta y el nombre de las imagenes que se encuentren en la # carpeta de la imagen seleccionada imagenes = self.carpetaActual.entryInfoList( ["*.jpg", "*.png", "*.ico", "*.bmp"], QDir.Files, QDir.Name) if not imagenes: self.Eliminar() return self.imagenesCarpeta = [ imagen.absoluteFilePath() for imagen in imagenes ] self.posicion = randint(0, len(self.imagenesCarpeta) - 1) self.estadoAnterior = True if self.posicion == 0 else False self.estadoSiguiente = True if self.posicion == len( self.imagenesCarpeta) - 1 else False elif QImage(imagen).isNull(): del self.imagenesCarpeta[self.posicion] if not self.imagenesCarpeta: self.Eliminar() return self.posicion = randint(0, len(self.imagenesCarpeta) - 1) self.estadoAnterior = True if self.posicion == 0 else False self.estadoSiguiente = True if self.posicion == len( self.imagenesCarpeta) - 1 else False imagen = self.imagenesCarpeta[self.posicion] if self.labelImagen.pixmap(): labelConImagen = self.labelImagen elif self.labelImagenUno.pixmap(): labelConImagen = self.labelImagenUno # Función encargada de bloquear o desbloquear los botones self.bloquearBotones(False) # Nombre y extensión de la imagen nombre = QFileInfo(imagen).fileName() # Label en el que se va a mostrar la imagen labelMostrarImagen = self.labelImagen if self.labelImagenUno.pixmap( ) else self.labelImagenUno # Quitar la imagen actual y mostrar la siguiente self.Limpiar(labelConImagen, labelMostrarImagen, QImage(imagen), nombre, posicionInternaX, posicionX)
from PyQt5.QtCore import QPropertyAnimation, QEasingCurve animation = QPropertyAnimation() animation.setTargetObject() animation.setStartValue(0) animation.setEndValue(1000) animation.setDuration(1000) animation.setEasingCurve(QEasingCurve.InOutQuad) animation.start()
class StateToolTip(QWidget): """ 进度提示框 """ def __init__(self, title='', content='', associatedThread=None, parent=None): super().__init__(parent) self.title = title self.content = content self.associatedThread = associatedThread # 实例化小部件 self.createWidgets() # 初始化参数 self.isDone = False self.rotateAngle = 0 self.deltaAngle = 18 # 初始化 self.initWidget() self.initLayout() self.setQss() def createWidgets(self): """ 创建小部件 """ icon_path = { 'normal': r'resource\images\createPlaylistPanel\stateToolTip_closeBt_normal_14_14.png', 'hover': r'resource\images\createPlaylistPanel\stateToolTip_closeBt_hover_14_14.png', 'pressed': r'resource\images\createPlaylistPanel\stateToolTip_closeBt_hover_14_14.png' } self.closeButton = ThreeStateButton(icon_path, self, (14, 14)) self.titleLabel = QLabel(self.title, self) self.contentLabel = QLabel(self.content, self) self.rotateTimer = QTimer(self) self.closeTimer = QTimer(self) self.animation = QPropertyAnimation(self, b'windowOpacity') self.busyImage = QPixmap( r'resource\images\createPlaylistPanel\running_22_22.png') self.doneImage = QPixmap( r'resource\images\createPlaylistPanel\complete_20_20.png') def initWidget(self): """ 初始化小部件 """ self.setFixedSize(370, 60) self.setWindowFlags(Qt.FramelessWindowHint | Qt.Window) self.rotateTimer.setInterval(50) self.closeTimer.setInterval(3000) self.contentLabel.setMinimumWidth(200) # 分配ID self.titleLabel.setObjectName('titleLabel') self.contentLabel.setObjectName('contentLabel') # 将信号连接到槽函数 self.closeButton.clicked.connect(self.closeButtonEvent) self.rotateTimer.timeout.connect(self.timeOutEvent) self.closeTimer.timeout.connect(self.slowlyClose) # 打开定时器 self.rotateTimer.start() def initLayout(self): """ 初始化布局 """ self.titleLabel.move(39, 11) self.contentLabel.move(15, 34) self.closeButton.move(self.width() - 29, 23) def setQss(self): """ 设置层叠样式 """ with open(r'resource\css\stateToolTip.qss', encoding='utf-8') as f: self.setStyleSheet(f.read()) def setTitle(self, title): """ 更新提示框的标题 """ self.title = title self.titleLabel.setText(title) def setContent(self, content): """ 更新提示框内容 """ self.content = content self.contentLabel.setText(content) def setState(self, isDone=False): """ 设置运行状态 """ self.isDone = isDone self.update() # 运行完成后主动关闭窗口 if self.isDone: self.closeTimer.start() def closeButtonEvent(self): """ 按下关闭按钮前摧毁相关线程 """ if self.associatedThread: self.associatedThread.stop() self.associatedThread.requestInterruption() self.associatedThread.wait() self.deleteLater() def slowlyClose(self): """ 缓慢关闭窗口 """ self.rotateTimer.stop() self.animation.setEasingCurve(QEasingCurve.Linear) self.animation.setDuration(500) self.animation.setStartValue(1) self.animation.setEndValue(0) self.animation.finished.connect(self.deleteLater) self.animation.start() def timeOutEvent(self): """ 定时器溢出时旋转箭头 """ self.rotateAngle = (self.rotateAngle + self.deltaAngle) % 360 self.update() def paintEvent(self, QPaintEvent): """ 绘制背景 """ super().paintEvent(QPaintEvent) # 绘制旋转箭头 painter = QPainter(self) painter.setRenderHints(QPainter.SmoothPixmapTransform) painter.setPen(Qt.NoPen) if not self.isDone: painter.translate(24, 20) # 原点平移到旋转中心 painter.rotate(self.rotateAngle) # 坐标系旋转 painter.drawPixmap(-int(self.busyImage.width() / 2), -int(self.busyImage.height() / 2), self.busyImage) else: painter.drawPixmap(14, 13, self.doneImage.width(), self.doneImage.height(), self.doneImage) def show(self): """ 重写show()函数 """ if self.parent(): self.move( self.parent().x() + self.parent().width() - self.width() - 30, self.parent().y() + 70) super().show()
class RecoveryKeyExporter(QObject): done = pyqtSignal(str) def __init__(self, parent=None): super(RecoveryKeyExporter, self).__init__(parent) self.parent = parent self.filepath = None self.progress = None self.animation = None self.crypter = None self.crypter_thread = None self.ciphertext = None def _on_encryption_failed(self, message): self.crypter_thread.quit() error(self.parent, "Error encrypting data", message) self.crypter_thread.wait() def _on_encryption_succeeded(self, ciphertext): self.crypter_thread.quit() if self.filepath: with atomic_write(self.filepath, mode="wb", overwrite=True) as f: f.write(ciphertext) self.done.emit(self.filepath) self.filepath = None else: self.ciphertext = ciphertext self.crypter_thread.wait() def _export_encrypted_recovery(self, gateway, password): settings = gateway.get_settings(include_rootcap=True) if gateway.use_tor: settings["hide-ip"] = True data = json.dumps(settings) self.progress = QProgressDialog("Encrypting...", None, 0, 100) self.progress.show() self.animation = QPropertyAnimation(self.progress, b"value") self.animation.setDuration(6000) # XXX self.animation.setStartValue(0) self.animation.setEndValue(99) self.animation.start() self.crypter = Crypter(data.encode(), password.encode()) self.crypter_thread = QThread() self.crypter.moveToThread(self.crypter_thread) self.crypter.succeeded.connect(self.animation.stop) self.crypter.succeeded.connect(self.progress.close) self.crypter.succeeded.connect(self._on_encryption_succeeded) self.crypter.failed.connect(self.animation.stop) self.crypter.failed.connect(self.progress.close) self.crypter.failed.connect(self._on_encryption_failed) self.crypter_thread.started.connect(self.crypter.encrypt) self.crypter_thread.start() dest, _ = QFileDialog.getSaveFileName( self.parent, "Select a destination", os.path.join( os.path.expanduser("~"), gateway.name + " Recovery Key.json.encrypted", ), ) if not dest: return if self.ciphertext: with atomic_write(dest, mode="wb", overwrite=True) as f: f.write(self.ciphertext) self.done.emit(dest) self.ciphertext = None else: self.filepath = dest def _export_plaintext_recovery(self, gateway): dest, _ = QFileDialog.getSaveFileName( self.parent, "Select a destination", os.path.join(os.path.expanduser("~"), gateway.name + " Recovery Key.json"), ) if not dest: return try: gateway.export(dest, include_rootcap=True) except Exception as e: # pylint: disable=broad-except error(self.parent, "Error exporting Recovery Key", str(e)) return self.done.emit(dest) def do_export(self, gateway): password, ok = PasswordDialog.get_password( self.parent, "Encryption passphrase (optional):", "A long passphrase will help keep your files safe in the event " "that your Recovery Key is ever compromised.", ) if ok and password: self._export_encrypted_recovery(gateway, password) elif ok: self._export_plaintext_recovery(gateway)
class FlatTabWidget(QWidget): tabClicked = pyqtSignal(int) scrolledUp = pyqtSignal() scrolledDown = pyqtSignal() fadein = True # 是否添加淡入效果,默认True,注意需要设置边框为none,不然会变形 def __init__(self, *args, **kwargs): super(FlatTabWidget, self).__init__(*args, **kwargs) self.setupUi() self.normal_color = ResourceLoader().qt_color_sub_text self.active_color = ResourceLoader().qt_color_text self.currentSelection = 0 self.lineMorph = QPropertyAnimation() self.pages = [] self.enqueueSeparatorRepaint = True self.animatePageChange = True self.customSW = None self.detachCustomStackedWidget = False def scrolledUp(): if self.currentSelection - 1 < 0 or len(self.pages) == 0: return self.scrolledUp.emit() item = self.pages[self.currentSelection - 1] if item.label != None: self.setCurrentTab(self.currentSelection - 1) self.TabBarContainer.scrolledUp.connect(scrolledUp) def scrolledDown(): if self.currentSelection + 1 >= len(self.pages) or len(self.pages) == 0: return self.scrolledDown.emit() item = self.pages[self.currentSelection + 1] if item.label != None: self.setCurrentTab(self.currentSelection + 1) self.TabBarContainer.scrolledDown.connect(scrolledDown) def setupUi(self): self.setObjectName("FlatTabWidget") self.resize(601, 352) self.horizontalLayout = QtWidgets.QHBoxLayout(self) self.horizontalLayout.setContentsMargins(0, 0, 0, 0) self.horizontalLayout.setObjectName("horizontalLayout") self.MasterLayout = QtWidgets.QVBoxLayout() self.MasterLayout.setContentsMargins(-1, 0, -1, -1) self.MasterLayout.setSpacing(1) self.MasterLayout.setObjectName("MasterLayout") self.TabBarContainer = CustomTabBar(self) self.TabBarContainer.setMinimumSize(QtCore.QSize(0, 0)) self.TabBarContainer.setObjectName("TabBarContainer") self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.TabBarContainer) self.horizontalLayout_2.setContentsMargins(0, 0, 0, 0) self.horizontalLayout_2.setObjectName("horizontalLayout_2") spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) self.horizontalLayout_2.addItem(spacerItem) self.MasterLayout.addWidget(self.TabBarContainer) self.SeparatorContainer = QtWidgets.QWidget(self) self.SeparatorContainer.setMinimumSize(QtCore.QSize(0, 5)) self.SeparatorContainer.setMaximumSize(QtCore.QSize(16777215, 5)) self.SeparatorContainer.setObjectName("SeparatorContainer") self.SeparatorLine = QtWidgets.QLabel(self.SeparatorContainer) self.SeparatorLine.setGeometry(QtCore.QRect(0, 0, 100, 1)) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.SeparatorLine.sizePolicy().hasHeightForWidth()) self.SeparatorLine.setSizePolicy(sizePolicy) self.SeparatorLine.setMaximumSize(QtCore.QSize(16777215, 1)) self.SeparatorLine.setFrameShape(QtWidgets.QFrame.HLine) self.SeparatorLine.setText("") self.SeparatorLine.setObjectName("SeparatorLine") self.MasterLayout.addWidget(self.SeparatorContainer) self.Content = QtWidgets.QStackedWidget(self) self.Content.setObjectName("Content") self.MasterLayout.addWidget(self.Content) self.horizontalLayout.addLayout(self.MasterLayout) self.retranslateUi() self.Content.setCurrentIndex(-1) QtCore.QMetaObject.connectSlotsByName(self) def retranslateUi(self): _translate = QtCore.QCoreApplication.translate self.setWindowTitle(_translate("FlatTabWidget", "FlatTabWidget")) def insertWidget(self, layout, reference, widget, pos=InsertPosition.InsertBefore, stretch=0, alignment=0): index = -1 for i, item in enumerate(layout.count()): if item.widget() == reference: index = i break if index < 0: return False if pos == InsertPosition.InsertAfter: return False layout.insertWidget(index, widget, stretch, alignment) return True def addPage(self, title, page, index = -1): textcolor_active = self.getColor(ColorRole.Active) textcolor_disabled = self.getColor(ColorRole.Inactive) lbl = ClickableLabel() lbl.setText(title) if len(self.pages) == 0: lbl.setColor(textcolor_active) self.currentSelection = 0 else: lbl.setColor(textcolor_disabled) lbl.clicked.connect(self.lblHandler) if index < 0: self.pages.append(FlatTabItem(lbl, page)) else: self.pages.insert(index, FlatTabItem(lbl, page)) self.updatePages() def updatePages(self, overrideSeparator=False): activeContainer = self.getActiveStackedWidget() spacer = self.TabBarContainer.layout().takeAt(len(self.TabBarContainer.layout()) - 1) wItem = self.TabBarContainer.layout().takeAt(0) while wItem: wItem.widget().hide() del wItem wItem = self.TabBarContainer.layout().takeAt(0) if not self.detachCustomStackedWidget: while len(activeContainer) > 0: widget = activeContainer.widget(0) activeContainer.removeWidget(widget) self.TabBarContainer.repaint() for page in self.pages: self.TabBarContainer.layout().addWidget(page.label) if not self.detachCustomStackedWidget: activeContainer.addWidget(page.widget) page.label.show() self.TabBarContainer.layout().addItem(spacer) if overrideSeparator: self.repaintDivider() self.setCurrentTab(self.currentSelection) def paintEvent(self, event): if self.enqueueSeparatorRepaint: if len(self.pages) == 0 or self.currentSelection < 0 or self.currentSelection >= len(self.pages): return button = self.pages[self.currentSelection].label rect = QRect(button.x(), 0, button.width(), button.height()) self.lineMorph.stop() self.SeparatorLine.setGeometry(rect) self.enqueueSeparatorRepaint = False if event.type() == QPaintEvent.PaletteChange: self.redrawTabBar() QWidget.paintEvent(self, event) def showEvent(self, event): self.repaintDivider() self.setPalette(self.palette()) QWidget.showEvent(self, event) def redrawTabBar(self): for page in self.pages: page.label.setColor(self.getColor(ColorRole.Inactive)) temp = self.currentSelection self.setCurrentTab(temp) def removePage(self, id): textcolor_disabled = self.getColor(ColorRole.Inactive) if len(self.pages) != 0 and id >= 0 and id < len(self.pages): if id < len(self.pages) - 1: self.pages[id + 1].label.setColor(textcolor_disabled) self.pages.remove(id) self.updatePages() def setCurrentTab(self, id): if len(self.pages) == 0: return if id < 0: id = 0 if id >= len(self.pages): id = len(self.pages) - 1 textcolor_active = self.getColor(ColorRole.Active) textcolor_disabled = self.getColor(ColorRole.Inactive) button = self.pages[id].label rect = QRect(button.x(), 0, button.width(), button.height()) if id == self.currentSelection: self.pages[id].label.setColor(textcolor_active) self.lineMorph.stop() self.SeparatorLine.setGeometry(rect) else: self.pages[id].fadeIn.stop() self.pages[id].fadeOut.stop() self.pages[id].fadeIn = QPropertyAnimation(self.pages[id].label, b"_color") self.pages[id].fadeIn.setDuration(300) self.pages[id].fadeIn.setStartValue(textcolor_disabled) self.pages[id].fadeIn.setEndValue(textcolor_active) if len(self.pages) > self.currentSelection: self.pages[self.currentSelection].fadeIn.stop() self.pages[self.currentSelection].fadeOut.stop() self.pages[self.currentSelection].fadeOut = QPropertyAnimation(self.pages[self.currentSelection].label, b"_color") self.pages[self.currentSelection].fadeOut.setDuration(300) self.pages[self.currentSelection].fadeOut.setStartValue(textcolor_active) self.pages[self.currentSelection].fadeOut.setEndValue(textcolor_disabled) self.pages[self.currentSelection].fadeOut.start() self.pages[id].fadeIn.start() self.lineMorph.stop() self.lineMorph = QPropertyAnimation(self.SeparatorLine, b"geometry") self.lineMorph.setDuration(300) self.lineMorph.setEasingCurve(QEasingCurve.OutCirc) self.lineMorph.setStartValue(self.SeparatorLine.geometry()) self.lineMorph.setEndValue(rect) self.lineMorph.start() if self.animatePageChange: widget = self.getActiveStackedWidget().widget(id) if widget != None: if self.fadein: StackedWidgetAnimation.fadeIn(self.getActiveStackedWidget(), widget) else: self.getActiveStackedWidget().setCurrentWidget(widget) else: self.getActiveStackedWidget().setCurrentIndex(id) self.currentSelection = id def getCurrentTab(self): return self.currentSelection def repaintDivider(self): self.enqueueSeparatorRepaint = True self.repaint() def getActiveStackedWidget(self): if self.customSW != None: return self.customSW else: return self.Content def getColor(self, role): if role == ColorRole.Active: return self.active_color else: return self.normal_color # pal = self.palette() # textcolor_active = pal.color(QPalette.ButtonText).darker(0) # textcolor_disabled_light = pal.color(QPalette.Disabled, QPalette.WindowText).darker(150) # textcolor_disabled_dark = pal.color(QPalette.Disabled, QPalette.WindowText).lighter(150) # # if role == ColorRole.Active: # return textcolor_active # else: # return textcolor_disabled_dark def getItem(self, id): if id >= 0 and id < len(self.pages): return self.pages[id] return FlatTabItem() def getItem(self, title): id = self.getId(title) if id < 0: return FlatTabItem() else: return self.getItem(id) def getId(self, title): for index, page in enumerate(self.pages): if page.label.text() == title: return index return -1 def lblHandler(self): id = self.getId(self.sender().text()) if id >= 0: self.setCurrentTab(id) self.tabClicked.emit(id) def getDetachCustomStackedWidget(self): return self.detachCustomStackedWidget def setDetachCustomStackedWidget(self, value): self.detachCustomStackedWidget = value def getCustomStackWidget(self): return self.customSW def setCustomStackWidget(self, value): self.customSW = value if value == None: self.Content.show() else: self.Content.hide() def getAnimatePageChange(self): return self.animatePageChange def setAnimatePageChange(self, value): self.animatePageChange = value
class RecoveryKeyImporter(QObject): done = pyqtSignal(dict) def __init__(self, parent=None): super(RecoveryKeyImporter, self).__init__() self.parent = parent self.filepath = None self.progress = None self.animation = None self.crypter = None self.crypter_thread = None def _on_decryption_failed(self, msg): logging.error("%s", msg) self.crypter_thread.quit() if msg == "Decryption failed. Ciphertext failed verification": msg = "The provided passphrase was incorrect. Please try again." reply = QMessageBox.critical( self.parent, "Decryption Error", msg, QMessageBox.Abort | QMessageBox.Retry, ) self.crypter_thread.wait() if reply == QMessageBox.Retry: self._load_from_file(self.filepath) def _on_decryption_succeeded(self, plaintext): logging.debug("Decryption of %s succeeded", self.filepath) self.crypter_thread.quit() try: settings = json.loads(plaintext.decode("utf-8")) except (UnicodeDecodeError, json.decoder.JSONDecodeError) as e: error(self, type(e).__name__, str(e)) return self.done.emit(settings) self.crypter_thread.wait() def _decrypt_content(self, data, password): logging.debug("Trying to decrypt %s...", self.filepath) self.progress = QProgressDialog( "Trying to decrypt {}...".format(os.path.basename(self.filepath)), None, 0, 100, ) self.progress.show() self.animation = QPropertyAnimation(self.progress, b"value") self.animation.setDuration(6000) # XXX self.animation.setStartValue(0) self.animation.setEndValue(99) self.animation.start() self.crypter = Crypter(data, password.encode()) self.crypter_thread = QThread() self.crypter.moveToThread(self.crypter_thread) self.crypter.succeeded.connect(self.animation.stop) self.crypter.succeeded.connect(self.progress.close) self.crypter.succeeded.connect(self._on_decryption_succeeded) self.crypter.failed.connect(self.animation.stop) self.crypter.failed.connect(self.progress.close) self.crypter.failed.connect(self._on_decryption_failed) self.crypter_thread.started.connect(self.crypter.decrypt) self.crypter_thread.start() def _parse_content(self, content): try: settings = json.loads(content.decode("utf-8")) except (UnicodeDecodeError, json.decoder.JSONDecodeError): logging.debug("JSON decoding failed; %s is likely encrypted", self.filepath) password, ok = PasswordDialog.get_password( self.parent, "Decryption passphrase (required):", "This Recovery Key is protected by a passphrase. Enter the " "correct passphrase to decrypt it.", show_stats=False, ) if ok: self._decrypt_content(content, password) return self.done.emit(settings) def _load_from_file(self, path): logging.debug("Loading %s...", self.filepath) try: with open(path, "rb") as f: content = f.read() except Exception as e: # pylint: disable=broad-except error(self, type(e).__name__, str(e)) return self._parse_content(content) def _select_file(self): dialog = QFileDialog(self.parent, "Select a Recovery Key") dialog.setDirectory(os.path.expanduser("~")) dialog.setFileMode(QFileDialog.ExistingFile) if dialog.exec_(): return dialog.selectedFiles()[0] return None def do_import(self, filepath=None): if not filepath: filepath = self._select_file() self.filepath = filepath if self.filepath: self._load_from_file(self.filepath)
class CoffeeFundWindow(QWidget): signal_back = pyqtSignal() signal_coffee = pyqtSignal() signal_account = pyqtSignal() def __init__(self, parent=None): super().__init__() self.cards = {} # type: Dict[GuiCards, QWidget] """ Python's GC will clean up QPropertyAnimations as soon as it leaves the button handler, therefore they will appear not to work. Use members to store the animations. see http://stackoverflow.com/a/6953965 """ self.slide_in_animation = None self.slide_out_animation = None self.animation_group = None self.setObjectName("coffeeFundWindow") """ Store the position and size of visible/hidden cards for the animation sequences """ self.hidden_geometry = None self.visible_geometry = None layout = QStackedLayout() layout.setStackingMode(QStackedLayout.StackAll) card_remove = RemoveCard() self.cards[GuiCards.RemoveCard] = card_remove layout.addWidget(card_remove) card_choose_action = ChooseActionCard() self.cards[GuiCards.ChooseAction] = card_choose_action layout.addWidget(card_choose_action) card_account = AccountCard() self.cards[GuiCards.AccountInfo] = card_account layout.addWidget(card_account) # keep this as last initialized card, the last card will be shown on startup! card_start = StartCard() self.cards[GuiCards.Start] = card_start layout.addWidget(card_start) self.setLayout(layout) self.setWindowTitle("Kaffeekasse") layout.setCurrentWidget(card_start) self.active_card = None card_choose_action.button_account.clicked.connect(self.signal_account) card_choose_action.button_coffee.clicked.connect(self.signal_coffee) card_account.button_back.clicked.connect(self.signal_back) def set_card_hidden(self, card: QWidget): card.setGeometry(self.hidden_geometry) def show_start(self): self.show_card(GuiCards.Start) def show_account(self, name, value): self.cards[GuiCards.AccountInfo].set_user_name(name) self.cards[GuiCards.AccountInfo].set_balance(value) self.show_card(GuiCards.AccountInfo) def show_choose_action(self, name: str): self.cards[GuiCards.ChooseAction].set_user_name(name) self.show_card(GuiCards.ChooseAction) def show_remove(self): self.show_card(GuiCards.RemoveCard) def show_card(self, card_id: GuiCards): if self.active_card is None: self.active_card = self.cards[GuiCards.Start] if self.active_card == self.cards[card_id]: return if self.visible_geometry is None or self.hidden_geometry is None: self.visible_geometry = self.active_card.geometry() # type: QRect self.hidden_geometry = QRect(self.visible_geometry.x(), self.visible_geometry.height() * 1.5, self.visible_geometry.width(), self.visible_geometry.height()) for key in self.cards.keys(): if key != self.active_card: self.set_card_hidden(self.cards[key]) card_to_show = self.cards[card_id] self.start_card_switch(card_to_show) self.active_card = self.cards[card_id] self.layout().setCurrentWidget(self.active_card) def start_card_switch(self, card_to_show): self.slide_out_animation = QPropertyAnimation(self.active_card, "geometry") self.slide_out_animation.setDuration(ANIMATION_DURATION) self.slide_out_animation.setEasingCurve(QEasingCurve.OutCubic) self.slide_out_animation.setStartValue(self.visible_geometry) self.slide_out_animation.setEndValue(self.hidden_geometry) self.set_card_hidden(card_to_show) self.slide_in_animation = QPropertyAnimation(card_to_show, "geometry") self.slide_in_animation.setDuration(ANIMATION_DURATION) self.slide_in_animation.setEasingCurve(QEasingCurve.InCubic) self.slide_in_animation.setStartValue(self.hidden_geometry) self.slide_in_animation.setEndValue(self.visible_geometry) self.animation_group = QParallelAnimationGroup() self.animation_group.addAnimation(self.slide_out_animation) self.animation_group.addAnimation(self.slide_in_animation) self.animation_group.start()
class ScreensharingToolbox(base_class, ui_class): exposedPixels = 3 def __init__(self, parent): super(ScreensharingToolbox, self).__init__(parent) with Resources.directory: self.setupUi() parent.installEventFilter(self) self.animation = QPropertyAnimation(self, 'pos') self.animation.setDuration(250) self.animation.setDirection(QPropertyAnimation.Forward) self.animation.setEasingCurve(QEasingCurve.Linear) # or OutCirc with 300ms self.retract_timer = QTimer(self) self.retract_timer.setInterval(3000) self.retract_timer.setSingleShot(True) self.retract_timer.timeout.connect(self.retract) self.resize(self.size().expandedTo(self.toolbox_layout.minimumSize())) def setupUi(self): super(ScreensharingToolbox, self).setupUi(self) # fix the SVG icons, as the generated code loads them as pixmaps, losing their ability to scale -Dan scale_icon = QIcon() scale_icon.addFile(Resources.get('icons/scale.svg'), mode=QIcon.Normal, state=QIcon.Off) viewonly_icon = QIcon() viewonly_icon.addFile(Resources.get('icons/viewonly.svg'), mode=QIcon.Normal, state=QIcon.Off) screenshot_icon = QIcon() screenshot_icon.addFile(Resources.get('icons/screenshot.svg'), mode=QIcon.Normal, state=QIcon.Off) fullscreen_icon = QIcon() fullscreen_icon.addFile(Resources.get('icons/fullscreen.svg'), mode=QIcon.Normal, state=QIcon.Off) fullscreen_icon.addFile(Resources.get('icons/fullscreen-exit.svg'), mode=QIcon.Normal, state=QIcon.On) fullscreen_icon.addFile(Resources.get('icons/fullscreen-exit.svg'), mode=QIcon.Active, state=QIcon.On) fullscreen_icon.addFile(Resources.get('icons/fullscreen-exit.svg'), mode=QIcon.Disabled, state=QIcon.On) fullscreen_icon.addFile(Resources.get('icons/fullscreen-exit.svg'), mode=QIcon.Selected, state=QIcon.On) minimize_icon = QIcon() minimize_icon.addFile(Resources.get('icons/minimize.svg'), mode=QIcon.Normal, state=QIcon.Off) minimize_icon.addFile(Resources.get('icons/minimize-active.svg'), mode=QIcon.Active, state=QIcon.Off) close_icon = QIcon() close_icon.addFile(Resources.get('icons/close.svg'), mode=QIcon.Normal, state=QIcon.Off) close_icon.addFile(Resources.get('icons/close-active.svg'), mode=QIcon.Active, state=QIcon.Off) self.scale_action.setIcon(scale_icon) self.viewonly_action.setIcon(viewonly_icon) self.screenshot_action.setIcon(screenshot_icon) self.fullscreen_action.setIcon(fullscreen_icon) self.minimize_action.setIcon(minimize_icon) self.close_action.setIcon(close_icon) self.scale_button.setIcon(scale_icon) self.viewonly_button.setIcon(viewonly_icon) self.screenshot_button.setIcon(screenshot_icon) self.fullscreen_button.setIcon(fullscreen_icon) self.minimize_button.setIcon(minimize_icon) self.close_button.setIcon(close_icon) self.scale_button.setDefaultAction(self.scale_action) self.viewonly_button.setDefaultAction(self.viewonly_action) self.screenshot_button.setDefaultAction(self.screenshot_action) self.fullscreen_button.setDefaultAction(self.fullscreen_action) self.minimize_button.setDefaultAction(self.minimize_action) self.close_button.setDefaultAction(self.close_action) self.color_depth_button.clear() self.color_depth_button.addItem('Default Color Depth', ServerDefault) self.color_depth_button.addItem('TrueColor (24 bits)', TrueColor) self.color_depth_button.addItem('HighColor (16 bits)', HighColor) self.color_depth_button.addItem('LowColor (8 bits)', LowColor) def eventFilter(self, watched, event): if watched is self.parent() and event.type() == QEvent.Resize: new_x = (watched.width() - self.width()) / 2 self.move(new_x, self.y()) self.animation.setStartValue(QPoint(new_x, -self.height() + self.exposedPixels)) self.animation.setEndValue(QPoint(new_x, 0)) return False def enterEvent(self, event): super(ScreensharingToolbox, self).enterEvent(event) self.retract_timer.stop() self.expose() def leaveEvent(self, event): super(ScreensharingToolbox, self).leaveEvent(event) self.retract_timer.start() def paintEvent(self, event): # make the widget style aware option = QStyleOption() option.initFrom(self) painter = QStylePainter(self) painter.drawPrimitive(QStyle.PE_Widget, option) def expose(self): if self.animation.state() == QPropertyAnimation.Running and self.animation.direction() == QPropertyAnimation.Forward: return elif self.animation.state() == QPropertyAnimation.Stopped and self.pos() == self.animation.endValue(): return self.animation.setDirection(QPropertyAnimation.Forward) self.animation.start() def retract(self): if self.animation.state() == QPropertyAnimation.Running and self.animation.direction() == QPropertyAnimation.Backward: return elif self.animation.state() == QPropertyAnimation.Stopped and self.pos() == self.animation.startValue(): return self.animation.setDirection(QPropertyAnimation.Backward) self.animation.start()
class Eye(QWidget): def __init__(self, *args, **kwargs): QWidget.__init__(self, *args, **kwargs) self.body_color = QColor(0xffffff) self.border_color = QColor(0x000000) self.border_size = 0.02 self.iris_size = 0.4 self.watch_direction = (0.0, 0.0) self.iris = Iris(QColor(0x00aa00), parent=self) self.iris_move_anim = QPropertyAnimation( self.iris, b'pos') # Animation for iris position self.iris_move_anim.setDuration(100) self.iris_size_anim = QPropertyAnimation( self.iris, b'pupil_size') # Animation for pupil size self.iris_size_anim.setDuration(500) self.resize_iris() def resize_iris(self): pupil_size = int(min(self.width(), self.height()) * self.iris_size) self.iris.setFixedSize(pupil_size, pupil_size) self.set_watch_direction(*self.watch_direction, animate=False) def resizeEvent(self, event: QResizeEvent): self.resize_iris() def paintEvent(self, event): size = min(self.width(), self.height()) painter = QPainter(self) painter.setRenderHint(QPainter.Antialiasing) painter.translate(self.width() / 2, self.height() / 2) # draw border around eye painter.setBrush(QBrush(self.border_color)) painter.drawEllipse(QPointF(0, 0), size / 2, size / 2) # draw sclera (white part of eyes) painter.setBrush(QBrush(self.body_color)) body_size = size * (1 - self.border_size) * 0.5 painter.drawEllipse(QPointF(0, 0), body_size, body_size) @property def radius(self): return min(self.width(), self.height()) / 2 @property def body_radius(self): return self.radius * (1 - self.border_size) @staticmethod def cart2pol(x, y): """Convert cartesian coordinate to polar""" # https://stackoverflow.com/a/26757297/8181134 mag = np.sqrt(x**2 + y**2) angle = np.arctan2(y, x) return (mag, angle) @staticmethod def pol2cart(mag, angle): """Convert polar coordinate to cartesian""" # https://stackoverflow.com/a/26757297/8181134 x = mag * np.cos(angle) y = mag * np.sin(angle) return (x, y) def set_watch_direction(self, horizontal, vertical, animate=True): """ Move the eyes to the specified direction :param horizontal: float [-1 1] :param vertical: float [-1 1] """ self.watch_direction = (horizontal, vertical) mag, angle = self.cart2pol(horizontal, vertical) mag = np.clip(mag, 0, 1) # Limit the magnitude to max 1 mag *= (self.body_radius - self.iris.radius ) # Max value for mag is so the edge of iris hits edge of eye x, y = self.pol2cart(mag, angle) x += (self.width() / 2) - self.iris.radius # Position of top-left corner of iris y += (self.height() / 2) - self.iris.radius if self.iris_move_anim.state() != QPropertyAnimation.Stopped: self.iris_move_anim.stop() if animate: self.iris_move_anim.setStartValue(self.iris.pos()) self.iris_move_anim.setEndValue(QPointF(x, y)) QTimer.singleShot(0, self.iris_move_anim.start) else: QTimer.singleShot(0, lambda x=x, y=y: self.iris.move(x, y)) def set_pupil_size(self, size: float): """Set the pupil size :arg size: Size of the pupil [0..1] """ self.iris_size_anim.stop() self.iris_size_anim.setStartValue(self.iris.pupil_size) self.iris_size_anim.setEndValue(size) QTimer.singleShot(0, self.iris_size_anim.start)
class Example(QDialog): ''' 按钮动画 ''' def __init__(self): super().__init__() self.initUI() def initUI(self): ''' 一些界面设置 ''' self.resize(350, 200) self.setWindowTitle('你爱我吗?微信公众号号:学点编程吧出品') self.btbuai = QPushButton("不爱", self) self.btai = QPushButton('爱', self) self.btbuai.resize(70, 25) self.btbuai.move(200, 150) self.btai.resize(70, 25) self.btai.move(100, 150) label = QLabel('你难道不爱我吗????', self) label.move(50, 50) self.show() self.flag = 'move' self.btai.setMouseTracking(True) self.btbuai.setMouseTracking(True) # 启用鼠标追踪 self.btai.installEventFilter(self) self.btbuai.installEventFilter(self) # 按钮安装事件过滤器 def eventFilter(self, object, event): ''' 事件过滤器,分别调用不同的动画 ''' if object == self.btbuai: if event.type() == QEvent.Enter: self.doAnim1() elif object == self.btai: if event.type() == QEvent.Enter: self.doAnim2() elif event.type() == QEvent.MouseButtonRelease: self.makelove() return QDialog.eventFilter(self, object, event) def closeEvent(self, event): ''' 关闭事件 ''' QMessageBox.about(self, 'Love', '你就算关闭了窗口也阻止不了你心中对我的爱!') def doAnim1(self): ''' 动画效果 ''' if self.flag == 'move' and self.btbuai.pos() == QPoint(200, 150): self.anim = QPropertyAnimation(self.btbuai, b"geometry") self.anim.setDuration(1500) # 这里我们设置了动画的时间1500毫秒 self.anim.setStartValue(QRect(200, 150, 70, 25)) self.anim.setEndValue(QRect(200, 30, 70, 25)) # 动画的对象的起始终点位置和大小; self.anim.setEasingCurve(QEasingCurve.OutCubic) # 动画的移动样式 self.anim.start() # 启动动画 # 下同 elif self.flag == 'move' and self.btbuai.pos() == QPoint(200, 30): self.anim = QPropertyAnimation(self.btbuai, b"geometry") self.anim.setDuration(1500) self.anim.setStartValue(QRect(200, 30, 70, 25)) self.anim.setEndValue(QRect(200, 150, 70, 25)) self.anim.setEasingCurve(QEasingCurve.OutCubic) self.anim.start() self.flag = 'change' elif self.flag == 'change' and self.btbuai.text() == '不爱': self.btbuai.setText('爱') self.btai.setText('不爱') # 爱和不爱的变化 def doAnim2(self): ''' 爱与不爱的转换 ''' if self.flag == 'change' and self.btbuai.text() == '爱': self.btbuai.setText('不爱') self.btai.setText('爱') self.flag = 'move' def makelove(self): ''' 爱你 ''' msg = MsgBox() msg.exec()
class LoginDialog(QDialog): """登录对话框""" clicked_ok = pyqtSignal() def __init__(self, config): super().__init__() self._cwd = os.getcwd() self._config = config self._cookie_assister = 'login_assister.exe' self._user = "" self._pwd = "" self._cookie = {} self._del_user = "" self.initUI() self.setStyleSheet(dialog_qss_style) self.setMinimumWidth(380) self.name_ed.setFocus() # 信号 self.name_ed.textChanged.connect(self.set_user) self.pwd_ed.textChanged.connect(self.set_pwd) self.cookie_ed.textChanged.connect(self.set_cookie) def update_selection(self, user): """显示已经保存的登录用户信息""" user_info = self._config.get_user_info(user) if user_info: self._user = user_info[0] self._pwd = user_info[1] self._cookie = user_info[2] # 更新控件显示内容 self.name_ed.setText(self._user) self.pwd_ed.setText(self._pwd) try: text = ";".join([f'{k}={v}' for k, v in self._cookie.items()]) except: text = '' self.cookie_ed.setPlainText(text) def initUI(self): self.setWindowTitle("登录蓝奏云") self.setWindowIcon(QIcon(SRC_DIR + "login.ico")) logo = QLabel() logo.setPixmap(QPixmap(SRC_DIR + "logo3.gif")) logo.setStyleSheet("background-color:rgb(0,153,255);") logo.setAlignment(Qt.AlignCenter) self.tabs = QTabWidget() self.auto_tab = QWidget() self.hand_tab = QWidget() # Add tabs self.tabs.addTab(self.auto_tab, "自动获取Cookie") self.tabs.addTab(self.hand_tab, "手动输入Cookie") self.auto_get_cookie_ok = AutoResizingTextEdit("🔶点击👇自动获取浏览器登录信息👇") self.auto_get_cookie_ok.setReadOnly(True) self.auto_get_cookie_btn = QPushButton("自动读取浏览器登录信息") auto_cookie_notice = '支持浏览器:Chrome, Chromium, Opera, Edge, Firefox' self.auto_get_cookie_btn.setToolTip(auto_cookie_notice) self.auto_get_cookie_btn.clicked.connect(self.call_auto_get_cookie) self.auto_get_cookie_btn.setStyleSheet( "QPushButton {min-width: 210px;max-width: 210px;}") self.name_lb = QLabel("&U 用户") self.name_lb.setAlignment(Qt.AlignCenter) self.name_ed = QLineEdit() self.name_lb.setBuddy(self.name_ed) self.pwd_lb = QLabel("&P 密码") self.pwd_lb.setAlignment(Qt.AlignCenter) self.pwd_ed = QLineEdit() self.pwd_ed.setEchoMode(QLineEdit.Password) self.pwd_lb.setBuddy(self.pwd_ed) self.cookie_lb = QLabel("&Cookie") self.cookie_ed = QTextEdit() notice = "由于滑动验证的存在,需要输入cookie,cookie请使用浏览器获取\n" + \ "cookie会保存在本地,下次使用。其格式如下:\n ylogin=value1; phpdisk_info=value2" self.cookie_ed.setPlaceholderText(notice) self.cookie_lb.setBuddy(self.cookie_ed) self.show_input_cookie_btn = QPushButton("显示Cookie输入框") self.show_input_cookie_btn.setToolTip(notice) self.show_input_cookie_btn.setStyleSheet( "QPushButton {min-width: 110px;max-width: 110px;}") self.show_input_cookie_btn.clicked.connect( self.change_show_input_cookie) self.ok_btn = QPushButton("登录") self.ok_btn.clicked.connect(self.change_ok_btn) self.cancel_btn = QPushButton("取消") self.cancel_btn.clicked.connect(self.change_cancel_btn) lb_line_1 = QLabel() lb_line_1.setText('<html><hr />切换用户</html>') lb_line_2 = QLabel() lb_line_2.setText('<html><hr /></html>') self.form = QFormLayout() self.form.setLabelAlignment(Qt.AlignRight) self.form.addRow(self.name_lb, self.name_ed) self.form.addRow(self.pwd_lb, self.pwd_ed) if is_windows: def set_assister_path(): """设置辅助登录程序路径""" assister_path = QFileDialog.getOpenFileName( self, "选择辅助登录程序路径", self._cwd, "EXE Files (*.exe)") if not assister_path[0]: return None assister_path = os.path.normpath( assister_path[0]) # windows backslash if assister_path == self._cookie_assister: return None self.assister_ed.setText(assister_path) self._cookie_assister = assister_path self.assister_lb = QLabel("登录辅助程序") self.assister_lb.setAlignment(Qt.AlignCenter) self.assister_ed = MyLineEdit(self) self.assister_ed.setText(self._cookie_assister) self.assister_ed.clicked.connect(set_assister_path) self.assister_lb.setBuddy(self.assister_ed) self.form.addRow(self.assister_lb, self.assister_ed) hbox = QHBoxLayout() hbox.addWidget(self.show_input_cookie_btn) hbox.addStretch(1) hbox.addWidget(self.ok_btn) hbox.addWidget(self.cancel_btn) user_box = QHBoxLayout() self.user_num = 0 self.user_btns = {} for user in self._config.users_name: user = str(user) # TODO: 可能需要删掉 self.user_btns[user] = QDoublePushButton(user) self.user_btns[user].setStyleSheet("QPushButton {border:none;}") if user == self._config.name: self.user_btns[user].setStyleSheet( "QPushButton {background-color:rgb(0,153,2);}") self.tabs.setCurrentIndex(1) self.user_btns[user].setToolTip(f"点击选中,双击切换至用户:{user}") self.user_btns[user].doubleClicked.connect(self.choose_user) self.user_btns[user].clicked.connect(self.delete_chose_user) user_box.addWidget(self.user_btns[user]) self.user_num += 1 user_box.addStretch(1) self.layout = QVBoxLayout(self) self.layout.addWidget(logo) vbox = QVBoxLayout() if self._config.name: vbox.addWidget(lb_line_1) user_box.setAlignment(Qt.AlignCenter) vbox.addLayout(user_box) vbox.addWidget(lb_line_2) if self.user_num > 1: self.del_user_btn = QPushButton("删除账户") self.del_user_btn.setIcon(QIcon(SRC_DIR + "delete.ico")) self.del_user_btn.setStyleSheet( "QPushButton {min-width: 180px;max-width: 180px;}") self.del_user_btn.clicked.connect(self.call_del_chose_user) vbox.addWidget(self.del_user_btn) else: self.del_user_btn = None vbox.addStretch(1) vbox.addLayout(self.form) vbox.addStretch(1) vbox.addLayout(hbox) vbox.setAlignment(Qt.AlignCenter) self.hand_tab.setLayout(vbox) auto_cookie_vbox = QVBoxLayout() auto_cookie_vbox.addWidget(self.auto_get_cookie_ok) auto_cookie_vbox.addWidget(self.auto_get_cookie_btn) auto_cookie_vbox.setAlignment(Qt.AlignCenter) self.auto_tab.setLayout(auto_cookie_vbox) self.layout.addWidget(self.tabs) self.setLayout(self.layout) self.update_selection(self._config.name) def call_del_chose_user(self): if self._del_user: if self._del_user != self._config.name: self.user_num -= 1 self._config.del_user(self._del_user) self.user_btns[self._del_user].close() self._del_user = "" if self.user_num <= 1: self.del_user_btn.close() self.del_user_btn = None return else: title = '不能删除' msg = '不能删除当前登录账户,请先切换用户!' else: title = '请选择账户' msg = '请单击选择需要删除的账户\n\n注意不能删除当前账户(绿色)' message_box = QMessageBox(self) message_box.setIcon(QMessageBox.Critical) message_box.setStyleSheet(btn_style) message_box.setWindowTitle(title) message_box.setText(msg) message_box.setStandardButtons(QMessageBox.Close) buttonC = message_box.button(QMessageBox.Close) buttonC.setText('关闭') message_box.exec() def delete_chose_user(self): """更改单击选中需要删除的用户""" user = str(self.sender().text()) self._del_user = user if self.del_user_btn: self.del_user_btn.setText(f"删除 <{user}>") def choose_user(self): """切换用户""" user = self.sender().text() if user != self._config.name: self.ok_btn.setText("切换用户") else: self.ok_btn.setText("登录") self.update_selection(user) def change_show_input_cookie(self): row_c = 4 if is_windows else 3 if self.form.rowCount() < row_c: self.org_height = self.height() self.form.addRow(self.cookie_lb, self.cookie_ed) self.show_input_cookie_btn.setText("隐藏Cookie输入框") self.change_height = None self.adjustSize() else: if not self.change_height: self.change_height = self.height() if self.cookie_ed.isVisible(): self.cookie_lb.setVisible(False) self.cookie_ed.setVisible(False) self.show_input_cookie_btn.setText("显示Cookie输入框") start_height, end_height = self.change_height, self.org_height else: self.cookie_lb.setVisible(True) self.cookie_ed.setVisible(True) self.show_input_cookie_btn.setText("隐藏Cookie输入框") start_height, end_height = self.org_height, self.change_height gm = self.geometry() x, y = gm.x(), gm.y() wd = self.width() self.animation = QPropertyAnimation(self, b'geometry') self.animation.setDuration(400) self.animation.setStartValue(QRect(x, y, wd, start_height)) self.animation.setEndValue(QRect(x, y, wd, end_height)) self.animation.start() def set_user(self, user): self._user = user if not user: return None if user not in self._config.users_name: self.ok_btn.setText("添加用户") self.cookie_ed.setPlainText("") elif user != self._config.name: self.update_selection(user) self.ok_btn.setText("切换用户") else: self.update_selection(user) self.ok_btn.setText("登录") def set_pwd(self, pwd): if self._user in self._config.users_name: user_info = self._config.get_user_info(self._user) if pwd and pwd != user_info[1]: # 改变密码,cookie作废 self.cookie_ed.setPlainText("") self._cookie = None if not pwd: # 输入空密码,表示删除对pwd的存储,并使用以前的cookie self._cookie = user_info[2] try: text = ";".join( [f'{k}={v}' for k, v in self._cookie.items()]) except: text = '' self.cookie_ed.setPlainText(text) self._pwd = pwd def set_cookie(self): cookies = self.cookie_ed.toPlainText() if cookies: try: self._cookie = { kv.split("=")[0].strip(" "): kv.split("=")[1].strip(" ") for kv in cookies.split(";") } except: self._cookie = None def change_cancel_btn(self): self.update_selection(self._config.name) self.close() def change_ok_btn(self): if self._user and self._pwd: if self._user not in self._config.users_name: self._cookie = None if self._cookie: up_info = { "name": self._user, "pwd": self._pwd, "cookie": self._cookie, "work_id": -1 } if self.ok_btn.text() == "切换用户": self._config.change_user(self._user) else: self._config.set_infos(up_info) self.clicked_ok.emit() self.close() elif USE_WEB_ENG: self.web = LoginWindow(self._user, self._pwd) self.web.cookie.connect(self.get_cookie_by_web) self.web.setWindowModality(Qt.ApplicationModal) self.web.exec() elif os.path.isfile(self._cookie_assister): try: result = os.popen( f'{self._cookie_assister} {self._user} {self._pwd}') cookie = result.read() try: self._cookie = { kv.split("=")[0].strip(" "): kv.split("=")[1].strip(" ") for kv in cookie.split(";") } except: self._cookie = None if not self._cookie: return None up_info = { "name": self._user, "pwd": self._pwd, "cookie": self._cookie, "work_id": -1 } self._config.set_infos(up_info) self.clicked_ok.emit() self.close() except: pass else: title = '请使用 Cookie 登录或是选择 登录辅助程序' msg = '没有输入 Cookie,或者没有找到登录辅助程序!\n\n' + \ '推荐使用浏览器获取 cookie 填入 cookie 输入框\n\n' + \ '如果不嫌文件体积大,请下载登录辅助程序:\n' + \ 'https://github.com/rachpt/lanzou-gui/releases' message_box = QMessageBox(self) message_box.setIcon(QMessageBox.Critical) message_box.setStyleSheet(btn_style) message_box.setWindowTitle(title) message_box.setText(msg) message_box.setStandardButtons(QMessageBox.Close) buttonC = message_box.button(QMessageBox.Close) buttonC.setText('关闭') message_box.exec() def get_cookie_by_web(self, cookie): """使用辅助登录程序槽函数""" self._cookie = cookie self._close_dialog() def call_auto_get_cookie(self): """自动读取浏览器cookie槽函数""" try: self._cookie = get_cookie_from_browser() except Exception as e: logger.error(f"Browser_cookie3 Error: {e}") self.auto_get_cookie_ok.setPlainText(f"❌获取失败,错误信息\n{e}") else: if self._cookie: self._user = self._pwd = '' self.auto_get_cookie_ok.setPlainText("✅获取成功即将登录……") QTimer.singleShot(2000, self._close_dialog) else: self.auto_get_cookie_ok.setPlainText( "❌获取失败\n请提前使用支持的浏览器登录蓝奏云,读取前完全退出浏览器!\n支持的浏览器与顺序:\nchrome, chromium, opera, edge, firefox" ) def _close_dialog(self): """关闭对话框""" up_info = { "name": self._user, "pwd": self._pwd, "cookie": self._cookie } self._config.set_infos(up_info) self.clicked_ok.emit() self.close()
class MyForm(QDialog): def __init__(self): super(MyForm, self).__init__() self.ui = uic.loadUi('file_ui/Game.ui', self) self.ui.frame.setStyleSheet('background-image:url("image/Lane.png")') self.label_10.setPixmap(QPixmap('image/Super-car.png')) self.image = ["image/Car-Blue.png", "image/Car-Green.png", "image/Car-Oranges.png", "image/Car-Pink.png"] self.setWindowTitle('Car Rush') self.setWindowIcon(QIcon('image/Supercar.png')) self.ui.pushButton_4.setEnabled(True) self.ui.pushButton_3.setEnabled(False) self.ui.pushButton_5.setEnabled(False) self.ui.pushButton_3.clicked.connect(self.stop) self.ui.pushButton_4.clicked.connect(self.Go) self.ui.pushButton_5.clicked.connect(self.resume) # xoá dữ liệu file.txt # self.ctx = open('text1.txt', 'w') # self.ctx.write('') self.best_point = 0 self.bestscore() self.step = 30 self.x = 190 self.y = 400 self.settime2 = 6000 self.speed2 = 6000 self.settime = 5000 self.speed = 5000 self.xea = 0 self.lstR2 = [30, 190, 360] def bestscore(self): bp = open('text1.txt', 'r') for i in bp.readlines(): if int(i) > int(self.best_point): self.best_point = i self.ui.label_7.setText('BEST SCORE: ' + str(self.best_point)) def Go(self): self.p = vlc.MediaPlayer("music/Rush.mp3") self.p.play() self.p.audio_set_volume(50) print("Go") MF3 = MyForm3() MF3.show() self.resetpoint() self.setPos() # Xe1 self.timexe1 = QtCore.QTimer() self.timexe1.start(self.settime) self.timexe1.timeout.connect(self.create) # Xe2 self.timexe2 = QtCore.QTimer() self.timexe2.start(self.settime2) self.timexe2.timeout.connect(self.create2) # point self.time_point = QtCore.QTimer() self.time_point.start(self.speed) self.time_point.timeout.connect(self.calculatePoint) #point 2 self.time_point2 = QtCore.QTimer() self.time_point2.start(self.speed2) self.time_point2.timeout.connect(self.calculatePoint2) # check self.timeCheck = QtCore.QTimer() self.timeCheck.start(100) self.timeCheck.timeout.connect(self.check) # time Disable self.timeDisable = QtCore.QTimer() self.timeDisable.start(4000) self.timeDisable.timeout.connect(self.Enabled) def create(self): self.lstR2 = [30, 190, 360] image = random.choice(self.image) self.labelXe1.setPixmap(QPixmap(image)) self.xea = random.choice(self.lstR2) self.CN = QPropertyAnimation(self.ui.labelXe1, b"geometry") self.CN.setDuration(self.speed) self.CN.setStartValue(QRect(self.xea, -50, 100, 150)) self.CN.setEndValue(QRect(self.xea, 800, 100, 150)) self.CN.start() def create2(self): r2 = random.choice(self.lstR2) print(self.xea) if r2 != self.xea: print("run r2 "+str(r2)) self.labelXe2.setPixmap(QPixmap(random.choice(self.image))) self.CN2 = QPropertyAnimation(self.ui.labelXe2, b"geometry") self.CN2.setDuration(self.speed) self.CN2.setStartValue(QRect(r2, -50, 100, 150)) self.CN2.setEndValue(QRect(r2, 800, 100, 150)) self.CN2.start() else: self.lstR2.remove(self.xea) print(self.lstR2) r_again = random.choice(self.lstR2) print("run r_again "+str(r_again)) self.labelXe2.setPixmap(QPixmap(random.choice(self.image))) self.CN2 = QPropertyAnimation(self.ui.labelXe2, b"geometry") self.CN2.setDuration(self.speed) self.CN2.setStartValue(QRect(r_again, -50, 100, 150)) self.CN2.setEndValue(QRect(r_again, 800, 100, 150)) self.CN2.start() def Enabled(self): print("Enabled") self.ui.pushButton_3.setEnabled(True) self.ui.pushButton_4.setEnabled(False) self.ui.pushButton_5.setEnabled(True) self.timeDisable.stop() def Disable(self): print("Disable") self.ui.pushButton_3.setEnabled(False) self.ui.pushButton_4.setEnabled(False) self.ui.pushButton_5.setEnabled(False) def setPos(self): self.ui.labelXe1.setGeometry(180, -200, 100, 150) self.ui.label_10.setGeometry(190, 400, 100, 150) self.x = 190 self.y = 400 def check(self): self.a = None # tọa độ xe 1 w_car = self.ui.labelXe1.width() h_car = self.ui.labelXe1.height() X_car = self.ui.labelXe1.x() Y_car = self.ui.labelXe1.y() # tọa độ xe 2 w_car2 = self.ui.labelXe2.width() h_car2 = self.ui.labelXe2.height() X_car2 = self.ui.labelXe2.x() Y_car2 = self.ui.labelXe2.y() # chiều cao, rộng xe đỏ w_card = self.ui.label_10.width() h_card = self.ui.label_10.height() # print("Xe 1 ", X_car, Y_car, "|","Xe 2 ", X_car2, Y_car2,"|", self.x, self.y) if ((self.x <= (X_car + w_car) and self.x >= X_car) or (self.x + w_card >= X_car and self.x + w_card <= X_car + w_car)) \ and ((h_car + Y_car >= self.y) and (h_card + Y_car <= self.y + h_card) or ((Y_car >= self.y) and (Y_car <= self.y + w_card))): self.time_point.stop() self.time_point2.stop() self.timeCheck.stop() self.timexe1.stop() self.timexe2.stop() self.CN.stop() self.CN2.stop() self.p.stop() self.ui.labelXe1.move(-200, -200) self.ui.labelXe2.move(-200, -200) #Âm thanh đụng xe self.crash = vlc.MediaPlayer("music/BOOM.mp3") self.crash.play() self.crash = vlc.MediaPlayer("music/HEAVENLY.mp3") self.crash.play() self.Disable() print("Game Over") # append the point to text1.txt a = open('text1.txt', 'a') a.write(str(self.point)) a.write('\n') a.close() self.MF2 = MyForm2() self.MF2.ui.pushButton.clicked.connect(self.PlayAgain) # kiểm tra điểm a = open('text1.txt', 'r') for i in a.readlines(): if int(self.best_point) < int(i): self.best_point =i if int(self.best_point) <= int(self.point): self.MF2.ui.label.setText('BEST SCORE: ' + str(self.point)) else: self.MF2.ui.label.setText('SCORE: ' + str(self.point)) self.MF2.show() if ((self.x <= (X_car2 + w_car2) and self.x >= X_car2) or (self.x + w_card >= X_car2 and self.x + w_card <= X_car2 + w_car2)) \ and ((h_car2 + Y_car2 >= self.y) and (h_card + Y_car2 <= self.y + h_card) or ((Y_car2 >= self.y) and (Y_car2 <= self.y + w_card))): self.time_point.stop() self.time_point2.stop() self.timexe1.stop() self.timexe2.stop() self.timeCheck.stop() self.CN.stop() self.CN2.stop() self.p.stop() self.ui.labelXe1.move(-200, -200) self.ui.labelXe2.move(-200, -200) # Âm thanh đụng xe self.crash = vlc.MediaPlayer("music/BOOM.mp3") self.crash.play() self.crash = vlc.MediaPlayer("music/HEAVENLY.mp3") self.crash.play() self.Disable() print("Game Over") # append the point to text1.txt a = open('text1.txt', 'a') a.write(str(self.point)) a.write('\n') a.close() self.MF2 = MyForm2() self.MF2.ui.pushButton.clicked.connect(self.PlayAgain) # kiểm tra điểm a = open('text1.txt', 'r') for i in a.readlines(): if int(self.best_point) < int(i): self.best_point = i if int(self.best_point) <= int(self.point): self.MF2.ui.label.setText('BEST SCORE: ' + str(self.point)) else: self.MF2.ui.label.setText('SCORE: ' + str(self.point)) self.MF2.show() def PlayAgain(self): self.a = None self.crash.stop() self.settime2 = 7000 self.speed2 = 7000 self.settime = 5000 self.speed = 5000 self.Go() self.MF2.close() self.bestscore() def move(self): self.anim = QPropertyAnimation(self.ui.label_10, b"geometry") self.anim.setDuration(-10) self.anim.setStartValue(QRect(self.x, self.y, 100, 150)) self.anim.setEndValue(QRect(self.x, self.y, 100, 150)) self.anim.start() def stop(self): self.timexe1.stop() self.timexe2.stop() self.time_point.stop() self.time_point2.stop() self.timeCheck.stop() self.CN.pause() self.CN2.pause() self.ui.pushButton_3.setEnabled(False) self.step = 0 self.p.pause() print("Stop") def resume(self): self.timexe1.start() self.timexe2.start() self.time_point.start() self.time_point2.start() self.timeCheck.start() self.CN.resume() self.CN2.resume() self.ui.pushButton_3.setEnabled(True) self.ui.pushButton_5.setEnabled(True) self.step = 30 self.p.play() print("Resume") def calculatePoint(self): if self.ui.labelXe1.y() > 700: self.point += 10 self.ui.label.setText(str(self.point)) print("Calculate Point 1") if self.point == 20: self.settime = self.settime - 500 self.speed = self.speed - 500 print(self.settime, self.speed) print(self.point) if self.point == 50: self.settime = self.settime - 500 self.speed = self.speed - 500 print(self.settime, self.speed) if self.point == 70: self.settime = self.settime - 500 self.speed = self.speed - 500 print(self.settime, self.speed) if self.point == 100: self.settime = self.settime - 500 self.speed = self.speed - 500 print(self.settime, self.speed) if self.point == 150: self.settime = self.settime - 500 self.speed = self.speed - 500 print(self.settime, self.speed) if self.point == 200: self.settime = self.settime - 500 self.speed = self.speed - 500 print(self.settime, self.speed) def calculatePoint2(self): if self.ui.labelXe2.y() > 700: self.point += 10 print(self.point) self.ui.label.setText(str(self.point)) print("Calculate Point 2") if self.point == 30: self.settime2 = self.settime2 - 500 self.speed2 = self.speed2 - 500 print(self.settime2, self.speed2) print(self.point) if self.point == 60: self.settime2 = self.settime2 - 500 self.speed2 = self.speed2 - 500 print(self.settime2, self.speed2) if self.point == 80: self.settime2 = self.settime2 - 500 self.speed2 = self.speed2 - 500 print(self.settime2, self.speed2) if self.point == 110: self.settime2 = self.settime2 - 500 self.speed2 = self.speed2 - 500 print(self.settime2, self.speed2) if self.point == 160: self.settime2 = self.settime2 - 500 self.speed2 = self.speed2 - 500 print(self.settime2, self.speed2) if self.point == 210: self.settime2 = self.settime2 - 500 self.speed2 = self.speed2 - 500 print(self.settime2, self.speed2) def resetpoint(self): self.point = 0 self.ui.label.setText(str(0)) def keyPressEvent(self, e): if e.key() == QtCore.Qt.Key_W or e.key() == QtCore.Qt.Key_Up: if self.y > 250: self.y -= self.step self.x += 0 elif e.key() == QtCore.Qt.Key_S or e.key() == QtCore.Qt.Key_Down: if self.y < 420: self.y += self.step # self.x += 0 elif e.key() == QtCore.Qt.Key_A or e.key() == QtCore.Qt.Key_Right: if self.x > 10: self.y += 0 self.x -= self.step elif e.key() == QtCore.Qt.Key_D or e.key() == QtCore.Qt.Key_Left: if self.x < 350: self.y += 0 self.x += self.step self.move() def stopall(self): sys.exit()
class SubPlayWindow(QWidget): """ 桌面左上角子播放窗口 """ def __init__(self, parent=None, songInfo: dict = None): super().__init__(parent) self.songInfo = {} if songInfo: self.songInfo = songInfo self.__lastSongIconPath = { "normal": r"app\resource\images\sub_play_window\lastSong_50_50_normal.png", "hover": r"app\resource\images\sub_play_window\lastSong_50_50_hover.png", "pressed": r"app\resource\images\sub_play_window\lastSong_50_50_pressed.png", } self.__nextSongIconPath = { "normal": r"app\resource\images\sub_play_window\nextSong_50_50_normal.png", "hover": r"app\resource\images\sub_play_window\nextSong_50_50_hover.png", "pressed": r"app\resource\images\sub_play_window\nextSong_50_50_pressed.png", } # 创建小部件 self.volumeSlider = Slider(Qt.Vertical, self) self.volumeLabel = QLabel(self) self.lastSongButton = ThreeStateButton(self.__lastSongIconPath, self, (50, 50)) self.playButton = PlayButton(self) self.nextSongButton = ThreeStateButton(self.__nextSongIconPath, self, (50, 50)) self.albumPic = QLabel(self) self.songNameLabel = QLabel(self) self.songerNameLabel = QLabel(self) self.ani = QPropertyAnimation(self, b"windowOpacity") self.timer = QTimer(self) # 系统音量控制类 self.systemVolume = SystemVolume() # 初始化 self.__initWidget() def __initWidget(self): """ 初始化小部件 """ self.resize(635, 175) self.__initLayout() self.setAttribute(Qt.WA_TranslucentBackground) self.setWindowFlags(Qt.FramelessWindowHint | Qt.Window | Qt.WindowStaysOnTopHint) # 初始化音量滑块 self.volumeSlider.setRange(0, 100) self.volumeSlider.setSingleStep(1) # 初始化动画和定时器 self.timer.setInterval(3000) self.ani.setEasingCurve(QEasingCurve.Linear) self.ani.setDuration(700) self.ani.setStartValue(1) self.ani.setEndValue(0) # 分配ID self.volumeLabel.setObjectName("volumeLabel") self.songNameLabel.setObjectName("songNameLabel") self.songerNameLabel.setObjectName("songerNameLabel") # 设置层叠样式 self.__setQss() # 将信号连接到槽 self.__connectSignalToSlot() self.volumeSlider.setValue(self.systemVolume.getVolume()) # 设置封面和标签 self.updateWindow(self.songInfo) # 引用方法 self.setPlay = self.playButton.setPlay def __initLayout(self): """ 初始化布局 """ self.move(62, 75) self.albumPic.move(478, 25) self.playButton.move(222, 26) self.volumeLabel.move(32, 140) self.volumeSlider.move(34, 25) self.songNameLabel.move(122, 93) self.lastSongButton.move(122, 26) self.nextSongButton.move(322, 26) self.songerNameLabel.move(122, 135) self.albumPic.setFixedSize(125, 125) self.songNameLabel.setFixedWidth(285) self.songerNameLabel.setFixedWidth(290) self.volumeLabel.setFixedWidth(65) def updateWindow(self, songInfo: dict): """ 设置窗口内容 """ self.songInfo = songInfo self.songName = self.songInfo.get("songName", "未知歌曲") self.songerName = self.songInfo.get("songer", "未知歌手") # 调整长度 self.__adjustText() # 更新标签和专辑封面 self.songNameLabel.setText(self.songName) self.songerNameLabel.setText(self.songerName) self.__setAlbumCover() def timerSlot(self): """ 定时器溢出时间 """ self.timer.stop() self.ani.start() def enterEvent(self, e): """ 鼠标进入时停止动画并重置定时器 """ self.timer.stop() if self.ani.state() == QAbstractAnimation.Running: self.ani.stop() self.setWindowOpacity(1) def leaveEvent(self, e): """ 鼠标离开窗口时打开计时器 """ # 判断事件发生的位置发生在自己所占的rect内 notLeave = isNotLeave(self) if not notLeave: self.timer.start() def show(self): """ show()时重置透明度并根据鼠标位置决定是否打开计时器 """ self.setWindowOpacity(1) self.volumeSlider.setValue(self.systemVolume.getVolume()) super().show() notLeave = isNotLeave(self) if not notLeave: self.timer.start() def paintEvent(self, e): """ 绘制背景色 """ painter = QPainter(self) painter.setRenderHints(QPainter.Antialiasing) painter.setPen(Qt.NoPen) brush = QBrush(Qt.black) painter.setBrush(brush) # 绘制音量滑动条的背景 painter.drawRect(0, 0, 81, 175) # 绘制控制面板的背景 painter.drawRect(86, 0, 549, 175) def __connectSignalToSlot(self): """ 将信号连接到槽 """ self.ani.finished.connect(self.hide) self.timer.timeout.connect(self.timerSlot) self.volumeSlider.valueChanged.connect(self.sliderValueChangedSlot) def __setQss(self): """ 设置层叠样式 """ with open(r"app\resource\css\subPlayWindow.qss", encoding="utf-8") as f: self.setStyleSheet(f.read()) def __setAlbumCover(self): """ 设置封面 """ # 如果专辑信息为空就直接隐藏 self.coverPath = getCoverPath(self.songInfo.get("modifiedAlbum")) self.albumPic.setPixmap( QPixmap(self.coverPath).scaled(125, 125, Qt.KeepAspectRatio, Qt.SmoothTransformation)) def __adjustText(self): """ 根据文本长度决定是否显示省略号 """ fontMetrics_1 = QFontMetrics(QFont("Microsoft YaHei", 17, 63)) self.songName = fontMetrics_1.elidedText(self.songName, Qt.ElideRight, 285) fontMetrics_2 = QFontMetrics(QFont("Microsoft YaHei", 9)) self.songerName = fontMetrics_2.elidedText(self.songerName, Qt.ElideRight, 290) def __adjustVolumeLabelPos(self): """ 调整音量标签的位置 """ if 10 <= int(self.volumeLabel.text()) <= 99: self.volumeLabel.move(32, 140) elif 0 <= int(self.volumeLabel.text()) <= 9: self.volumeLabel.move(37, 140) else: self.volumeLabel.move(27, 140) def sliderValueChangedSlot(self, value): """ 音量改变时调整系统音量并更新标签 """ self.volumeLabel.setText(str(value)) self.__adjustVolumeLabelPos() self.systemVolume.setVolume(value)
def __init__(self, parent=None): QStatusBar.__init__(self, parent) self.setAutoFillBackground( True) # set the widget background to be filled automatically # Define colours to use in animations red = QColor(255, 0, 0) red_transparent = QColor(255, 0, 0, alpha=0) green = QColor(0, 255, 0) green_transparent = QColor(0, 255, 0, alpha=0) # Setup fade out animation for red fade_out = QPropertyAnimation(self, b"back_color") fade_out.setStartValue(red) fade_out.setEndValue(red_transparent) fade_out.setDuration(2000) # Setup fade in animation for red fade_in = QPropertyAnimation(self, b"back_color") fade_in.setStartValue(red_transparent) fade_in.setEndValue(red) fade_in.setDuration(2000) # Setup stay animation for red stay_red = QPropertyAnimation(self, b"back_color") stay_red.setStartValue(red) stay_red.setEndValue(red) stay_red.setDuration(1000) # Setup animation group for no connection self._no_conn_anim = QSequentialAnimationGroup() self._no_conn_anim.addAnimation(fade_out) self._no_conn_anim.addAnimation(fade_in) self._no_conn_anim.addAnimation(stay_red) self._no_conn_anim.setLoopCount(-1) # loop infinitely # Setup fade out animation for green fade_out = QPropertyAnimation(self, b"back_color") fade_out.setStartValue(green) fade_out.setEndValue(green_transparent) fade_out.setDuration(2000) # Setup fade in animation for green fade_in = QPropertyAnimation(self, b"back_color") fade_in.setStartValue(green_transparent) fade_in.setEndValue(green) fade_in.setDuration(2000) # Setup stay animation for green stay_green = QPropertyAnimation(self, b"back_color") stay_green.setStartValue(green) stay_green.setEndValue(green) stay_green.setDuration(1000) # Setup animation group for a connection self._conn_anim = QSequentialAnimationGroup() self._conn_anim.addAnimation(fade_out) self._conn_anim.addAnimation(fade_in) self._conn_anim.addAnimation(stay_green) self._conn_anim.setLoopCount(-1)
class AnimBox(QGraphicsObject): """A Box that draws an outline when hover over. Attributes ---------- hoverEnter: pyqtSignal Emitted when the mouse hover into the box hoverExit: pyqtSignal Emitted when the mouse hover out of the box """ hoverEnter = pyqtSignal() hoverExit = pyqtSignal() def __init__(self, x, y, width, height, parent=None): """Prepares the box and animation Parameters ---------- x: float x position of the top-left corner of the box y: float y position of the top-left corner of the box width: float Width of the box height: float Height of the box parent: object Passed into QGraphicsObject init method """ super().__init__(parent=parent) self.x = x self.y = y self.width = width self.height = height self.circumference = 2 * (width + height) self.default_pen = QPen() self.default_pen.setColor(Qt.white) self.outline_pen = QPen() self.outline_pen.setColor(Qt.white) self.outline_pen.setWidth(5) self.detected = False # Whether the mouse hover over the box self.btn_rect = QRectF(self.x, self.y, self.width, self.height) self.left = QLineF() self.down = QLineF() self.right = QLineF() self.up = QLineF() self.line_order = [self.up, self.right, self.down, self.left] self.set_freeze(False) self.length = 0 self.anim = QPropertyAnimation(self, b'length') self.anim.setStartValue(0) for t in range(1, 10): self.anim.setKeyValueAt(t / 10, self.logistic_func(t / 10)) self.anim.setEndValue(self.circumference) def set_freeze(self, freeze): """Set whether the box should accept the mouse events Parameters ---------- freeze: bool True to stop the box from accepting mouse inputs, False otherwise """ if freeze: self.setAcceptedMouseButtons(Qt.NoButton) self.setAcceptHoverEvents(False) else: self.setAcceptedMouseButtons(Qt.LeftButton) self.setAcceptHoverEvents(True) def toggle_anim(self, toggling): """Toggle the highlight animation to be play forward or backward Parameters ---------- toggling: bool True for forward, False for backwards """ if toggling: self.anim.setDirection(QAbstractAnimation.Forward) else: self.anim.setDirection(QAbstractAnimation.Backward) self.anim.start() def logistic_func(self, x): """The logistic function that determines the animation motion Parameters ---------- x: list or numpy array Values to be feed into the function Returns ------- list or numpy array Values of the logistic function corresponding to the input range """ return self.circumference / (1 + math.exp(-(x - 0.5) * 18)) def boundingRect(self): """Reimplemented from QGraphicsObject. """ return QRectF(self.x - 5, self.y - 5, self.width + 10, self.height + 10) def paint(self, painter, style, widget=None): """Reimplemented from QGraphicsObject. Draws the Box and the highlights. """ painter.setPen(self.outline_pen) for line in self.line_order: if line.length() > 1: painter.drawLine(line) painter.setPen(self.default_pen) painter.drawRect(self.btn_rect) @pyqtProperty(float) def length(self): """float: The length of the highlight to be drawn. When set, the length of the outlines are determined """ return self._length @length.setter def length(self, value): self._length = value remaining_length = value if remaining_length >= 2 * self.width + self.height: length_to_draw = remaining_length - (2 * self.width + self.height) remaining_length -= length_to_draw else: length_to_draw = 0 self.line_order[3].setLine(self.x, self.y + self.height, self.x, self.y + self.height - length_to_draw) if remaining_length >= self.width + self.height: length_to_draw = remaining_length - (self.width + self.height) remaining_length -= length_to_draw else: length_to_draw = 0 self.line_order[2].setLine(self.x + self.width, self.y + self.height, self.x + self.width - length_to_draw, self.y + self.height) if remaining_length >= self.width: length_to_draw = remaining_length - self.width remaining_length -= length_to_draw else: length_to_draw = 0 self.line_order[1].setLine(self.x + self.width, self.y, self.x + self.width, self.y + length_to_draw) self.line_order[0].setLine(self.x, self.y, self.x + remaining_length, self.y) self.update() def hoverEnterEvent(self, event): """Reimplemented hoverEnterEvent. Detect the mouse and toggle the animation """ if ~self.detected: self.hoverEnter.emit() self.detected = True self.toggle_anim(True) super().hoverEnterEvent(event) def hoverLeaveEvent(self, event): """Reimplemented hoverLeaveEvent. Detect the mouse leaving and reverse the animation """ if self.detected: self.hoverExit.emit() self.detected = False self.toggle_anim(False) super().hoverLeaveEvent(event)
class SidebarItem(QWidget): on_pressed = pyqtSignal(bool) def __init__(self, text, pixmap=None, parent=None): super().__init__(parent) rgb_value = 255 if options.theme == 'dark' else 0 self.theme = options.theme # You are supposed to set size policy like this, and not to override sizePolicy() # If vertical policy was preferred, then you would have to implement minimumSizeHint and # maximumSize to limit how much the item can shrink and grow. self.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Fixed) self.text = text self.pixmap = pixmap self._prepare_pixmap(QColor(rgb_value, rgb_value, rgb_value, 200)) self.spacing = 12 self.font = QApplication.font() self.font.setBold(True) self.fm = QFontMetrics(self.font) self.mouse_over = False self.checked = False self.active = False self.setMouseTracking(True) self.background_color = QColor(rgb_value, rgb_value, rgb_value, 0) self.background_animation = QPropertyAnimation(self, b'opacity') self.background_animation.setStartValue(0) self.background_animation.setEndValue(40) self.background_animation.setDuration(300) self.indicator_pos = 5 self.indicator_position_anim = QPropertyAnimation( self, b'indicator_position') self.indicator_position_anim.setStartValue(5) self.indicator_position_anim.setEndValue(-5) self.indicator_position_anim.setDuration(300) self.indicator_background = QColor(rgb_value, rgb_value, rgb_value, 0) self.indicator_opacity_anim = QPropertyAnimation( self, b'indicator_opacity') self.indicator_opacity_anim.setStartValue(0) self.indicator_opacity_anim.setEndValue(140) self.indicator_opacity_anim.setDuration(300) self.all_animations = QParallelAnimationGroup() self.all_animations.addAnimation(self.background_animation) self.all_animations.addAnimation(self.indicator_position_anim) self.all_animations.addAnimation(self.indicator_opacity_anim) OptionEventChannel.subscribe('theme', self.handle_theme_change) def mousePressEvent(self, event): super().mousePressEvent(event) self.on_pressed.emit(True) def set_checked(self, checked): self.checked = checked self.check_active() def check_active(self): old_active = self.active if self.checked: self.active = True else: self.active = self.mouse_over if old_active == self.active: return if self.active is True: self.all_animations.setDirection(QParallelAnimationGroup.Forward) self.all_animations.start() else: self.all_animations.setDirection(QParallelAnimationGroup.Backward) self.all_animations.start() # Calling update 10 times will result in only one update. # So it's fine to do this even after starting the animations. self.update() def enterEvent(self, event): self.mouse_over = True self.check_active() def leaveEvent(self, event): self.mouse_over = False self.check_active() def sizeHint(self): # sizeHint is used by layouts to get the recommended size of the widget. return QSize(100, 40) # def minimumSizeHint(self): # # minimumSizeHint is used by layouts to get the minimum size of the widget. # # It's ignored if minimumSize is also implemented # return self.sizeHint() def paintEvent(self, paint_event): super().paintEvent(paint_event) widget_rect = self.rect() painter = QPainter(self) painter.setRenderHint(QPainter.Antialiasing) painter.fillRect(widget_rect, self.background_color) if self.mouse_over: indicator_rect = QRect( widget_rect.width() + self.indicator_pos - 6, (widget_rect.height() - 6) // 2, 6, 9) triangle_path = QPainterPath(indicator_rect.topRight()) triangle_path.lineTo(indicator_rect.bottomRight()) mid_left = indicator_rect.bottomLeft() mid_left.setY(mid_left.y() - indicator_rect.height() // 2) triangle_path.lineTo(mid_left) triangle_path.lineTo(indicator_rect.topRight()) painter.fillPath(triangle_path, self.indicator_background) if self.pixmap: pixmap_rect = QRect(self.spacing, (widget_rect.height() - 20) // 2, 20, 20) painter.drawPixmap(pixmap_rect, self.pixmap, self.pixmap.rect()) # painter.drawRect(pixmap_rect) else: pixmap_rect = QRect(0, 0, 0, 0) text_rect = QRect(pixmap_rect.right() + self.spacing, 0, 0, widget_rect.height()) text_rect.setWidth(widget_rect.width() - text_rect.left()) # painter.drawRect(text_rect) text = self.fm.elidedText(self.text, Qt.ElideRight, text_rect.width()) painter.setFont(self.font) painter.drawText(text_rect, Qt.AlignVCenter | Qt.AlignLeft, text) def _prepare_pixmap(self, qcolor): if self.pixmap is None: return painter = QPainter(self.pixmap) painter.setCompositionMode(QPainter.CompositionMode_SourceAtop) painter.fillRect(self.pixmap.rect(), qcolor) painter.end() def _get_opacity(self): return self.background_color.alpha() def _set_opacity(self, new_value): self.background_color.setAlpha(new_value) self.update() opacity = pyqtProperty('int', _get_opacity, _set_opacity) def _get_indicator_position(self): return self.indicator_pos def _set_indicator_position(self, new_value): self.indicator_pos = new_value self.update() indicator_position = pyqtProperty('int', _get_indicator_position, _set_indicator_position) def _get_indicator_opacity(self): return self.indicator_background.alpha() def _set_indicator_opacity(self, new_value): self.indicator_background.setAlpha(new_value) self.update() indicator_opacity = pyqtProperty('int', _get_indicator_opacity, _set_indicator_opacity) def handle_theme_change(self, theme): if theme == self.theme: return self.theme = theme if theme == 'dark': rgb_value = 255 else: rgb_value = 0 self.background_color.setRgb(rgb_value, rgb_value, rgb_value, self.background_color.alpha()) self.indicator_background.setRgb(rgb_value, rgb_value, rgb_value, self.indicator_background.alpha()) self._prepare_pixmap(QColor(rgb_value, rgb_value, rgb_value, 200)) self.update()