def __init__(self, game, boardrect, parent=None): super().__init__(parent) self.game = game self.boardrect = boardrect margin_size = self.boardrect.x() self.__answerbarrect = boardrect.adjusted(-ANSWERBARS, 0, ANSWERBARS, 0) self.__correctrect = QRect(0, 0, margin_size, self.boardrect.height()) self.__incorrectrect = QRect(self.boardrect.right(), 0, margin_size, self.boardrect.height()) arrow_size = QSize(int(margin_size * 0.7), int(margin_size * 0.7)) self.__leftarrowrect = QRect(QPoint(0, 0), arrow_size) self.__leftarrowrect.moveCenter(self.__correctrect.center()) self.__rightarrowrect = QRect(QPoint(0, 0), arrow_size) self.__rightarrowrect.moveCenter(self.__incorrectrect.center()) self.__leftarrowimage = QPixmap(resource_path("left-arrow.png")) self.__rightarrowimage = QPixmap(resource_path("right-arrow.png")) self.__spaceimage = QPixmap(resource_path("space.png")) self.show() self.__lit = False self.arrowhints = False self.spacehints = False
def __init__( self, parent=None, direction=Qt.Orientation.Horizontal, duration=500, animationType=QEasingCurve.Type.OutCubic, wrap=False, ): '''Create new Slider object. Parameters: parent (QWidget obj/QLayout obj): Parent element direction (Qt.Orientation obj): direction of animation duration (int): animation during in milliseconds animationType (QEasingCurve.Type obj): animation type wrap (bool): wrap around slides Returns: Slider obj ''' if parent: super().__init__(parent) else: super().__init__() self.direction = direction self.duration = duration self.animationType = animationType self.wrap = wrap self.currentSlide = 0 self.nextSlide = 0 self.currentPosition = QPoint(0, 0) self.active = False
def slideWidget(self, widget): if self.active: return self.active = True i = self.currentIndex() i_next = self.indexOf(widget) if i == i_next: self.active = False return offsetX = self.frameRect().width() offsetY = self.frameRect().height() self.widget(i_next).setGeometry(self.frameRect()) if self.direction == Qt.Orientation.Horizontal: if i < i_next: offsetX = -offsetX offsetY = 0 else: offsetY = 0 else: if i < i_next: offsetX = 0 offsetY = -offsetY else: offsetX = 0 positionCurrent = self.widget(i).pos() positionNext = self.widget(i_next).pos() self.currentPosition = positionCurrent offset = QPoint(offsetX, offsetY) self.widget(i_next).move(positionNext - offset) self.widget(i_next).show() self.widget(i_next).raise_() animationGroup = QParallelAnimationGroup( self, finished=self.animationDoneSlot) for index, start, end in zip((i, i_next), (positionCurrent, positionNext - offset), (positionCurrent + offset, positionNext)): animation = QPropertyAnimation( self.widget(index), b'pos', duration=self.duration, easingCurve=self.animationType, startValue=start, endValue=end, ) animationGroup.addAnimation(animation) self.nextSlide = i_next self.currentSlide = i self.active = True animationGroup.start( QAbstractAnimation.DeletionPolicy.DeleteWhenStopped)
def _new_player(self, player): label = self.labels[self.num_players] self.num_players += 1 label.setText(player.name) labelwidth = self.parent().size().width() // 3 label.setFixedWidth(labelwidth) # label.move(label.pos() + QPoint((MOVIEWIDTH - labelwidth) / 2, 0)) label.move(QPoint(labelwidth * (self.num_players - 1), 0)) label.setAlignment(Qt.AlignmentFlag.AlignCenter)
def reparent(self): # print("Reparent: ", self.buffer.url) qwindow = self.windowHandle() if not get_emacs_func_cache_result( "eaf-emacs-not-use-reparent-technology", []): qwindow.setParent(QWindow.fromWinId(int(self.emacs_xid))) qwindow.setPosition(QPoint(self.x, self.y))
def getInitialSettings(self): """Get initial settings of the application using QSettings upon startup.""" position = self.settings.value("position", QPoint(200, 0)) size = self.settings.value("size", QSize(800, 500)) self.is_delete_checked = self.settings.value("delete_images", type=bool) # restoreState() is used here to restore the image_preview_dock widget self.restoreState(self.settings.value("window_state", bytes(QByteArray()))) self.resize(size) self.move(position) return self.is_delete_checked
def draw_item(self, painter, style, option): option.features |= option.HasDecoration option.icon = self.icon text_rect = style.subElementRect(style.SE_ItemViewItemText, option, None) if not option.icon.isNull(): icon_rect = style.subElementRect(style.SE_ItemViewItemDecoration, option, None) option.icon.paint(painter, icon_rect, alignment=Qt.AlignmentFlag.AlignBottom | Qt.AlignmentFlag.AlignHCenter) option.icon = QIcon() x, y = text_rect.x(), text_rect.y() y += (text_rect.height() - self.text.size().height()) // 2 painter.drawStaticText(QPoint(x, y), self.text)
def draw_item(self, painter, style, option): option.features |= QStyleOptionViewItem.ViewItemFeature.HasDecoration option.icon = self.icon text_rect = style.subElementRect(QStyle.SubElement.SE_ItemViewItemText, option, None) x, y = text_rect.x(), text_rect.y() y += int(text_rect.height() - self.left.size().height()) // 2 if not option.icon.isNull(): icon_rect = style.subElementRect( QStyle.SubElement.SE_ItemViewItemDecoration, option, None) icon_rect.setTop(y), icon_rect.setBottom(int(text_rect.bottom())) option.icon.paint(painter, icon_rect) option.icon = QIcon() width = (text_rect.width() // 2) - 10 painter.setClipRect(x, int(text_rect.y()), int(width), int(text_rect.height())) painter.drawStaticText(QPoint(int(x), int(y)), self.left) painter.setClipRect(text_rect) x += width + 20 painter.drawStaticText(QPoint(int(x), int(y)), self.right)
def drawPolygon(self, polygons): for polygon in polygons: xy = [] for p in polygon[:-1]: x = self.evaluate(p.getX() + self.widget.width() / 2) y = self.evaluate(-p.getY() + self.widget.height() / 2) xy.append(QPoint(x, y)) self.setBrush(QColor(polygon[-1][0])) if self.widget.camera.controler.mode: self.setPen(QColor(polygon[-1][0])) else: self.setPen(QColor('white')) super().drawPolygon(QPolygon(xy)) self.setPen(QColor('white'))
def __init__(self, parent = None): super().__init__(parent) # FIXME: As of time of writing, you can not reference flags by name in QT6 # You can find the list of flags by value here https://doc.qt.io/qt-6/qquickitem.html#Flag-enum # This flag is QQuickItem::ItemHasContents self.setFlag(QQuickItem.Flag(8)) self._arrow_size = 0 self._color = QColor(255, 255, 255, 255) self._target = QPoint(0,0) self._border_width = 0 self._border_color = QColor(0, 0, 0, 255) self._geometry = None self._material = None self._node = None self._border_geometry = None self._border_material = None self._border_node = None
def __init__(self): super().__init__() self.app = QApplication.instance() self.setWindowTitle(gbl.title) self.setMinimumSize(QSize(1000, 400)) self.minesite_changed.connect(self.update_minesite_label) self.minesite_label = QLabel( self ) # permanent label for status bar so it isnt changed by statusTips self.minesite_label.setToolTip( 'Global MineSite > Set with [Ctrl + Shift + M]') self.rows_label = QLabel(self) self.statusBar().addPermanentWidget(self.rows_label) self.statusBar().addPermanentWidget(self.minesite_label) # Settings s = QSettings('sms', 'smseventlog', self) screen_point = s.value('window position', False) screen_size = s.value('window size', False) # if screen size/left anchor pt values are not set or out of range, use default if not (screen_point and screen_size and gbl.check_screen_point(screen_point)): screen_point = QPoint(50, 50) screen_size = QSize(1200, 1000) # move/resize MainWindow to last position/size self.resize(screen_size) self.move(screen_point) self.settings = s self.menus = {} self.create_actions() self.tabs = TabWidget(self) self.setCentralWidget(self.tabs) self.update_minesite_label() self.threadpool = QThreadPool(self) log.debug('Mainwindow init finished.')
def test_sanity(tmp_path): # Segfault test app = QApplication([]) ex = Example() assert app # Silence warning assert ex # Silence warning for mode in ("1", "RGB", "RGBA", "L", "P"): # to QPixmap im = hopper(mode) data = ImageQt.toqpixmap(im) assert isinstance(data, QPixmap) assert not data.isNull() # Test saving the file tempfile = str(tmp_path / f"temp_{mode}.png") data.save(tempfile) # Render the image qimage = ImageQt.ImageQt(im) data = QPixmap.fromImage(qimage) qt_format = QImage.Format if ImageQt.qt_version == "6" else QImage qimage = QImage(128, 128, qt_format.Format_ARGB32) painter = QPainter(qimage) image_label = QLabel() image_label.setPixmap(data) image_label.render(painter, QPoint(0, 0), QRegion(0, 0, 128, 128)) painter.end() rendered_tempfile = str(tmp_path / f"temp_rendered_{mode}.png") qimage.save(rendered_tempfile) assert_image_equal_tofile(im.convert("RGBA"), rendered_tempfile) # from QPixmap roundtrip(hopper(mode)) app.quit() app = None
def mouseMoveEvent(self, mouseEvent: QMouseEvent): if self.scrolling: if not self.handIsClosed: QApplication.restoreOverrideCursor() QApplication.setOverrideCursor( QtCore.Qt.CursorShape.OpenHandCursor) self.handIsClosed = True if self.scrollMousePress != None: delta = mouseEvent.pos() - self.positionMousePress self.setScrollPosition( QPoint(int(self.scrollMousePress.x()), int(self.scrollMousePress.y())) - delta) return if self.pressed: self.pressed = False self.scrolling = True self.webViewScrolled.emit(True) return if self.hoveCheck(self.mapPosFromEvent(mouseEvent)): QApplication.setOverrideCursor( QtCore.Qt.CursorShape.PointingHandCursor) else: QApplication.setOverrideCursor(QtCore.Qt.CursorShape.ArrowCursor) return
def doLayout(self, rect, testOnly): x = rect.x() y = rect.y() lineHeight = 0 for item in self.itemList: wid = item.widget() spaceX = self.spacing() + wid.style().layoutSpacing( QSizePolicy.ControlType.PushButton, QSizePolicy.ControlType.PushButton, Qt.Orientation.Horizontal, ) spaceY = self.spacing() + wid.style().layoutSpacing( QSizePolicy.ControlType.PushButton, QSizePolicy.ControlType.PushButton, Qt.Orientation.Vertical, ) nextX = x + item.sizeHint().width() + spaceX if nextX - spaceX > rect.right() and lineHeight > 0: x = rect.x() y = y + lineHeight + spaceY nextX = x + item.sizeHint().width() + spaceX lineHeight = 0 if not testOnly: item.setGeometry(QRect( QPoint(x, y), item.sizeHint(), )) x = nextX lineHeight = max(lineHeight, item.sizeHint().height()) return y + lineHeight - rect.y()
def draw_item(self, painter, style, option): text_rect = style.subElementRect(QStyle.SubElement.SE_ItemViewItemText, option, None) y = text_rect.y() y += int(text_rect.height() - self.text.size().height()) // 2 painter.drawStaticText(QPoint(int(text_rect.x()), y), self.text)
def updatePaintNode(self, paint_node, update_data): if paint_node is None: paint_node = QSGGeometryNode() geometry = QSGGeometry(QSGGeometry.defaultAttributes_Point2D(), 7, 9) geometry.setDrawingMode(QSGGeometry.DrawingMode.DrawTriangles) vertex_data = geometry.vertexDataAsPoint2D() vertex_data[0].set(0, 0) vertex_data[1].set(0, self.height()) vertex_data[2].set(self.width(), self.height()) vertex_data[3].set(self.width(), 0) # no arrow by default vertex_data[4].set(0, 0) vertex_data[5].set(0, 0) vertex_data[6].set(0, 0) target_offset = self._target - QPoint(round(self.x()), round(self.y())) arrow_on_side = -1 # no arrow arrow_size = 0 arrow_offset = 0 if target_offset.x() >= 0 and target_offset.x() <= self.width(): arrow_size = min(self._arrow_size, self.width() / 2) arrow_offset = max(arrow_size, min(self.width() - arrow_size, target_offset.x())) if target_offset.y() < 0: # top vertex_data[4].set(arrow_offset - arrow_size, 0) vertex_data[5].set(arrow_offset, - arrow_size) vertex_data[6].set(arrow_offset + arrow_size, 0) arrow_on_side = 0 elif target_offset.y() > self.height(): # bottom vertex_data[4].set(arrow_offset - arrow_size, self.height()) vertex_data[5].set(arrow_offset, self.height() + arrow_size) vertex_data[6].set(arrow_offset + arrow_size, self.height()) arrow_on_side = 2 elif target_offset.y() >= 0 and target_offset.y() <= self.height(): arrow_size = min(self._arrow_size, self.height() / 2) arrow_offset = max(arrow_size, min(self.height() - arrow_size, target_offset.y())) if target_offset.x() < 0: # left vertex_data[4].set(0, arrow_offset - arrow_size) vertex_data[5].set(-arrow_size, arrow_offset) vertex_data[6].set(0, arrow_offset + arrow_size) arrow_on_side = 3 elif target_offset.x() > self.width(): # right vertex_data[4].set(self.width(), arrow_offset - arrow_size) vertex_data[5].set(self.width() + arrow_size, arrow_offset) vertex_data[6].set(self.width(), arrow_offset + arrow_size) arrow_on_side = 1 index_data = geometry.indexDataAsUShort() index_data[0] = 0 index_data[1] = 1 index_data[2] = 2 index_data[3] = 0 index_data[4] = 2 index_data[5] = 3 index_data[6] = 4 index_data[7] = 5 index_data[8] = 6 paint_node.setGeometry(geometry) material = QSGFlatColorMaterial() material.setColor(self._color) paint_node.setMaterial(material) if self._border_width > 0: if paint_node.childCount() == 0: border_node = QSGGeometryNode() else: border_node = paint_node.firstChild() border_vertices = [] border_vertices.append((0, 0)) if arrow_on_side == 0: border_vertices.append((arrow_offset - arrow_size, 0)) border_vertices.append((arrow_offset, - arrow_size)) border_vertices.append((arrow_offset + arrow_size, 0)) border_vertices.append((self.width(), 0)) if arrow_on_side == 1: border_vertices.append((self.width(), arrow_offset - arrow_size)) border_vertices.append((self.width() + arrow_size, arrow_offset)) border_vertices.append((self.width(), arrow_offset + arrow_size)) border_vertices.append((self.width(), self.height())) if arrow_on_side == 2: border_vertices.append((arrow_offset + arrow_size, self.height())) border_vertices.append((arrow_offset, self.height() + arrow_size)) border_vertices.append((arrow_offset - arrow_size, self.height())) border_vertices.append((0,self.height())) if arrow_on_side == 3: border_vertices.append((0, arrow_offset + arrow_size)) border_vertices.append((- arrow_size, arrow_offset)) border_vertices.append((0, arrow_offset - arrow_size)) border_geometry = QSGGeometry(QSGGeometry.defaultAttributes_Point2D(), 2 * len(border_vertices), 0) border_geometry.setDrawingMode(QSGGeometry.DrawingMode.DrawLines) border_geometry.setLineWidth(self._border_width) border_vertex_data = border_geometry.vertexDataAsPoint2D() for index in range(len(border_vertices)): start_vertex = border_vertices[index] end_vertex = border_vertices[index + 1] if index < len(border_vertices) -1 else border_vertices[0] border_vertex_data[2 * index].set(start_vertex[0], start_vertex[1]) border_vertex_data[2 * index + 1].set(end_vertex[0], end_vertex[1]) border_node.setGeometry(border_geometry) border_material = QSGFlatColorMaterial() border_material.setColor(self._border_color) border_node.setMaterial(border_material) if paint_node.childCount() == 0: paint_node.appendChildNode(border_node) else: border_node = None border_geometry = None border_material = None paint_node.removeAllChildNodes() # For PyQt 5.4, I need to store these otherwise they will be garbage collected before rendering # and never show up, but otherwise never crash. self._node = paint_node self._geometry = geometry self._material = material self._border_node = border_node self._border_geometry = border_geometry self._border_material = border_material return paint_node
def initUI(self): self.setWindowTitle("关于 lanzou-gui") about = f'本项目使用PyQt6实现图形界面,可以完成蓝奏云的大部分功能<br/> \ 得益于 <a href="{self._api_url}">API</a> 的功能,可以间接突破单文件最大 100MB 的限制,同时增加了批量上传/下载的功能<br/> \ Python 依赖见<a href="{self._github }/blob/master/requirements.txt">requirements.txt</a>,\ <a href="{self._github}/releases">releases</a> 有打包好了的 Windows 可执行程序,但可能不是最新的' project_url = f'<a href="{self._home_page}">主页</a> | <a href="{self._github}">repo</a> | \ <a href="{self._gitee}">mirror repo</a>' self.logo = QLabel() # logo self.logo.setPixmap(QPixmap(SRC_DIR + "logo2.gif")) self.logo.setStyleSheet("background-color:rgb(255,255,255);") self.logo.setAlignment(Qt.AlignmentFlag.AlignCenter) self.lb_qt_ver = QLabel("依赖") # QT 版本 self.lb_qt_text = QLabel( f"QT: {QT_VERSION_STR}, PyQt: {PYQT_VERSION_STR}") # QT 版本 self.lb_name = QLabel("版本") # 版本 self.lb_name_text = QPushButton("") # 版本 self.lb_name_text.setToolTip("点击检查更新") ver_style = "QPushButton {border:none; background:transparent;font-weight:bold;color:blue;}" self.lb_name_text.setStyleSheet(ver_style) self.lb_name_text.clicked.connect( lambda: self.check_update.emit(self._ver, True)) self.lb_about = QLabel("关于") # about self.lb_about_text = QLabel() self.lb_about_text.setText(about) self.lb_about_text.setOpenExternalLinks(True) self.lb_author = QLabel("作者") # author self.lb_author_mail = QLabel( "<a href='mailto:[email protected]'>rachpt</a>") self.lb_author_mail.setOpenExternalLinks(True) self.lb_update = QLabel("项目") # 更新 self.lb_update_url = QLabel(project_url) self.lb_update_url.setOpenExternalLinks(True) self.buttonBox = QDialogButtonBox() self.buttonBox.setOrientation(Qt.Orientation.Horizontal) self.buttonBox.setStandardButtons( QDialogButtonBox.StandardButton.Close) self.buttonBox.button( QDialogButtonBox.StandardButton.Close).setText("关闭") self.buttonBox.rejected.connect(self.reject) self.buttonBox.setStyleSheet(btn_style) self.recommend = QLabel( "<br />大文件推荐使用 <a href='https://github.com/Aruelius/cloud189'>cloud189-cli</a>" ) self.recommend.setOpenExternalLinks(True) self.line = QLine(QPoint(), QPoint(550, 0)) self.lb_line = QLabel('<html><hr /></html>') vbox = QVBoxLayout() vbox.addWidget(self.logo) vbox.addStretch(1) self.form = QFormLayout() self.form.setLabelAlignment(Qt.AlignmentFlag.AlignRight) self.form.setFormAlignment(Qt.AlignmentFlag.AlignLeft) self.form.setHorizontalSpacing(40) self.form.setVerticalSpacing(15) self.form.addRow(self.lb_qt_ver, self.lb_qt_text) self.form.addRow(self.lb_name, self.lb_name_text) self.form.addRow(self.lb_update, self.lb_update_url) self.form.addRow(self.lb_author, self.lb_author_mail) self.form.addRow(self.lb_about, self.lb_about_text) self.form.setFieldGrowthPolicy(QFormLayout.FieldGrowthPolicy. AllNonFixedFieldsGrow) # 覆盖MacOS的默认样式 vbox.addLayout(self.form) vbox.addStretch(1) vbox.addWidget(self.recommend) vbox.addWidget(self.lb_line) donate = QLabel() donate.setText("<b>捐助我</b> 如果你愿意") donate.setAlignment(Qt.AlignmentFlag.AlignCenter) hbox = QHBoxLayout() hbox.addStretch(2) for it in ["wechat", "alipay", "qqpay"]: lb = QLabel() lb.setPixmap(QPixmap(SRC_DIR + f"{it}.jpg")) hbox.addWidget(lb) hbox.addStretch(1) hbox.addWidget(self.buttonBox) vbox.addWidget(donate) vbox.addLayout(hbox) self.setLayout(vbox) self.setMinimumWidth(720)
# Ensure that the value got set assert getattr(model, data["attribute"]) == data["value"] # Attempt to set the value again getattr(model, "set" + attribute)(data["value"]) # The signal should not fire again assert signal.emit.call_count == 1 @pytest.mark.parametrize( "width,height,target,result_points", [ (0, 0, None, [(0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0)]), (100, 20, None, [(0, 0), (0, 20), (100, 20), (100, 0), (0, 0), (0, 0), (0, 0)]), (100, 20, QPoint(300, 10), [(0, 0), (0, 20), (100, 20), (100, 0), (100, 0), (110, 10), (100, 20)]), # Arrow on the right (100, 20, QPoint(100, 100), [(0, 0), (0, 20), (100, 20), (100, 0), (80, 20), (90, 30), (100, 20)]), # Arrow on bottom (100, 20, QPoint(100, -2), [(0, 0), (0, 20), (100, 20), (100, 0), (80, 0), (90, -10), (100, 0)]), # Arrow on top (100, 20, QPoint(-1, 0), [(0, 0), (0, 20), (100, 20), (100, 0), (0, 0), (-10, 10), (0, 20)]) # Arrow on left ]) def test_updatePaintNode(width, height, target, result_points): item = PointingRectangle() item.setWidth(width)