def pixmap(self, size): """returns a background pixmap or None for isPlain""" self.__pmap = QBrush() if not self.isPlain: width = size.width() height = size.height() if self.tiled: width = self.imageWidth height = self.imageHeight cachekey = '{name}W{width}H{height}'.format(name=self.name, width=width, height=height) self.__pmap = QPixmapCache.find(cachekey) if not self.__pmap: renderer = QSvgRenderer(self.graphicsPath) if not renderer.isValid(): logException( i18n( 'file <filename>%1</filename> contains no valid SVG', self.graphicsPath)) self.__pmap = QPixmap(width, height) self.__pmap.fill(Qt.transparent) painter = QPainter(self.__pmap) renderer.render(painter) QPixmapCache.insert(cachekey, self.__pmap) return self.__pmap
def __init__(self, board, parent=None): super(BoardWidget, self).__init__(parent) self.board = board self._selected_field = None # (x_field, y_field) or None self._available_moves = [] # [(x_field, y_field), ...] or None self._painter = QPainter() self._background_brush = QBrush(Qt.gray) self._white_field_brush = QBrush(Qt.white) self._black_field_brush = QBrush(Qt.black) self._white_checker_brush = QBrush(Qt.white) self._white_king_checker_brush = QBrush(Qt.white) self._selected_field_brush = QBrush(Qt.blue) self._available_move_field_brush = QBrush(Qt.green) self._black_checker_brush = QBrush(Qt.black) self._black_king_checker_brush = QBrush(Qt.black) self._white_checker_pen = QPen(QBrush(Qt.gray), 5, j=Qt.RoundJoin) self._black_checker_pen = QPen(QBrush(Qt.gray), 5, j=Qt.RoundJoin) self._white_king_checker_pen = QPen(QBrush(Qt.red), 5, j=Qt.RoundJoin) self._black_king_checker_pen = QPen(QBrush(Qt.red), 5, j=Qt.RoundJoin) self._border_brush = QBrush(QColor.fromRgb(205, 127, 50)) self._field_size = None self._border_size = None
def pot_square_resize(img, maximum=None): """Resize image to power of two square :type img: QImage :param img: input image :type maximum: int or None :param maximum: maximum size (must be 2**n) :return: resized image """ resized = pot_resize(img, maximum=maximum) w, h = resized.width(), resized.height() base = max(w, h) #pad = base - min(w, h) new_img = QImage(base, base, img.format()) new_img.fill(QColor(0, 0, 0)) painter = QPainter(new_img) painter.drawImage(0, 0, resized) return new_img, w / base, h / base
def __fillLastMeldComboWith(self, winnerMelds, indexedMeld, lastTile): """fill last meld combo with prepared content""" winner = self.game.winner faceWidth = winner.handBoard.tileset.faceSize.width() * 0.5 faceHeight = winner.handBoard.tileset.faceSize.height() * 0.5 restoredIdx = None for meld in winnerMelds: pixMap = QPixmap(faceWidth * len(meld), faceHeight) pixMap.fill(Qt.transparent) self.__meldPixMaps.append(pixMap) painter = QPainter(pixMap) for element in meld: painter.drawPixmap( 0, 0, winner.handBoard.tilesByElement(element)[0].pixmapFromSvg( QSize(faceWidth, faceHeight), withBorders=False ), ) painter.translate(QPointF(faceWidth, 0.0)) self.cbLastMeld.addItem(QIcon(pixMap), "", toQVariant(str(meld))) if indexedMeld == str(meld): restoredIdx = self.cbLastMeld.count() - 1 if not restoredIdx and indexedMeld: # try again, maybe the meld changed between concealed and exposed indexedMeld = indexedMeld.lower() for idx in range(self.cbLastMeld.count()): meldContent = str(variantValue(self.cbLastMeld.itemData(idx))) if indexedMeld == meldContent.lower(): restoredIdx = idx if lastTile not in meldContent: lastTile = lastTile.swapped assert lastTile in meldContent with BlockSignals(self.cbLastTile): # we want to continue right here idx = self.cbLastTile.findData(toQVariant(lastTile)) self.cbLastTile.setCurrentIndex(idx) break if not restoredIdx: restoredIdx = 0 self.cbLastMeld.setCurrentIndex(restoredIdx) self.cbLastMeld.setIconSize(QSize(faceWidth * 3, faceHeight))
def pixmapFromSvg(self, pmapSize=None, withBorders=None): """returns a pixmap with default size as given in SVG and optional borders/shadows""" if withBorders is None: withBorders = Internal.Preferences.showShadows if withBorders: wantSize = self.tileset.tileSize.toSize() else: wantSize = self.tileset.faceSize.toSize() if not pmapSize: pmapSize = wantSize result = QPixmap(pmapSize) result.fill(Qt.transparent) painter = QPainter(result) if not painter.isActive(): logException( 'painter is not active. Wanted size: %s' % str(pmapSize)) try: xScale = float(pmapSize.width()) / wantSize.width() yScale = float(pmapSize.height()) / wantSize.height() except ZeroDivisionError: xScale = 1 yScale = 1 if not withBorders: painter.scale(*self.tileset.tileFaceRelation()) painter.translate(-self.facePos()) renderer = self.tileset.renderer() renderer.render(painter, self.__elementId()) painter.resetTransform() self._drawDarkness(painter) if self.showFace(): faceSize = self.tileset.faceSize.toSize() faceSize = QSize( faceSize.width() * xScale, faceSize.height() * yScale) painter.translate(self.facePos()) renderer.render(painter, self.tileset.svgName[self.tile.exposed], QRectF(QPointF(), QSizeF(faceSize))) return result
def genWindPixmap(self): """prepare wind tiles""" pwind = PlayerWind(self.__wind) pwind.prevailing = self.__wind == Wind.all4[min(self.__roundsFinished, 3)] pMap = QPixmap(40, 40) pMap.fill(Qt.transparent) painter = QPainter(pMap) painter.setRenderHint(QPainter.Antialiasing) painter.scale(0.40, 0.40) pwind.paint(painter, QStyleOptionGraphicsItem()) for child in pwind.childItems(): if isinstance(child, QGraphicsSvgItem): with Painter(painter): painter.translate(child.mapToParent(0.0, 0.0)) child.paint(painter, QStyleOptionGraphicsItem()) return pMap
def genWINDPIXMAPS(): """prepare wind tiles""" tileset = Tileset(Internal.Preferences.windTilesetName) for wind in Wind.all4: for prevailing in False, True: pwind = PlayerWind(wind, tileset, prevailing) pMap = QPixmap(40, 40) pMap.fill(Qt.transparent) painter = QPainter(pMap) painter.setRenderHint(QPainter.Antialiasing) painter.scale(0.40, 0.40) pwind.paint(painter, QStyleOptionGraphicsItem()) for child in pwind.childItems(): if isinstance(child, QGraphicsSvgItem): with Painter(painter): painter.translate(child.mapToParent(0.0, 0.0)) child.paint(painter, QStyleOptionGraphicsItem()) WINDPIXMAPS[(wind, prevailing)] = pMap
def __fillLastMeldComboWith(self, winnerMelds, indexedMeld, lastTile): """fill last meld combo with prepared content""" winner = self.game.winner faceWidth = winner.handBoard.tileset.faceSize.width() * 0.5 faceHeight = winner.handBoard.tileset.faceSize.height() * 0.5 restoredIdx = None for meld in winnerMelds: pixMap = QPixmap(faceWidth * len(meld), faceHeight) pixMap.fill(Qt.transparent) self.__meldPixMaps.append(pixMap) painter = QPainter(pixMap) for element in meld: painter.drawPixmap( 0, 0, winner.handBoard.tilesByElement(element)[0].pixmapFromSvg( QSize(faceWidth, faceHeight), withBorders=False)) painter.translate(QPointF(faceWidth, 0.0)) self.cbLastMeld.addItem(QIcon(pixMap), '', str(meld)) if indexedMeld == str(meld): restoredIdx = self.cbLastMeld.count() - 1 if not restoredIdx and indexedMeld: # try again, maybe the meld changed between concealed and exposed indexedMeld = indexedMeld.lower() for idx in range(self.cbLastMeld.count()): meldContent = str(self.cbLastMeld.itemData(idx)) if indexedMeld == meldContent.lower(): restoredIdx = idx if lastTile not in meldContent: lastTile = lastTile.swapped assert lastTile in meldContent with BlockSignals(self.cbLastTile ): # we want to continue right here idx = self.cbLastTile.findData(lastTile) self.cbLastTile.setCurrentIndex(idx) break if not restoredIdx: restoredIdx = 0 self.cbLastMeld.setCurrentIndex(restoredIdx) self.cbLastMeld.setIconSize(QSize(faceWidth * 3, faceHeight))
class BoardWidget(QWidget): CHECKER_SIZE_TO_FIELD = 0.6 BORDER_SIZE_TO_FIELD = 0.5 field_clicked = Signal(int, int, int) # button, x, y def __init__(self, board, parent=None): super(BoardWidget, self).__init__(parent) self.board = board self._selected_field = None # (x_field, y_field) or None self._available_moves = [] # [(x_field, y_field), ...] or None self._painter = QPainter() self._background_brush = QBrush(Qt.gray) self._white_field_brush = QBrush(Qt.white) self._black_field_brush = QBrush(Qt.black) self._white_checker_brush = QBrush(Qt.white) self._white_king_checker_brush = QBrush(Qt.white) self._selected_field_brush = QBrush(Qt.blue) self._available_move_field_brush = QBrush(Qt.green) self._black_checker_brush = QBrush(Qt.black) self._black_king_checker_brush = QBrush(Qt.black) self._white_checker_pen = QPen(QBrush(Qt.gray), 5, j=Qt.RoundJoin) self._black_checker_pen = QPen(QBrush(Qt.gray), 5, j=Qt.RoundJoin) self._white_king_checker_pen = QPen(QBrush(Qt.red), 5, j=Qt.RoundJoin) self._black_king_checker_pen = QPen(QBrush(Qt.red), 5, j=Qt.RoundJoin) self._border_brush = QBrush(QColor.fromRgb(205, 127, 50)) self._field_size = None self._border_size = None def set_selected_field(self, field): assert field is None or len(field) == 2 self._selected_field = field def set_available_moves(self, fields): assert all(len(field) == 2 for field in fields) or fields is None if not fields: self._available_moves = [] self._available_moves = fields def board_rect(self): rect = self.rect() size = min([rect.width(), rect.height()]) - self._border_size * 2 return QRectF(self._border_size, self._border_size, size, size) def field_rect(self, x_field, y_field): return QRectF(self._border_size + x_field * self._field_size, self._border_size + (self.board.SIZE - 1 - y_field) * self._field_size, self._field_size, self._field_size) def get_field_by_point(self, point): x_field = (point.x() - self._border_size) / self._field_size y_field = self.board.SIZE - (point.y() - self._border_size) / self._field_size if 0 <= x_field < self.board.SIZE and 0 <= y_field < self.board.SIZE: return int(x_field), int(y_field) return None def resizeEvent(self, event): rect = self.rect() outer_size = min([rect.width(), rect.height()]) self._field_size = outer_size / float(self.board.SIZE + 2 * self.BORDER_SIZE_TO_FIELD) self._border_size = self._field_size * self.BORDER_SIZE_TO_FIELD def mousePressEvent(self, event): clicked_field = self.get_field_by_point(event.pos()) if clicked_field: self.field_clicked.emit(int(event.button()), clicked_field[0], clicked_field[1]) return super(BoardWidget, self).mousePressEvent(event) def paintEvent(self, event): self._painter.begin(self) self.draw_background() self.draw_border() self.draw_fields() self.draw_checkers() self._painter.end() def draw_background(self): self._painter.fillRect(self.rect(), self._background_brush) def draw_border(self): rect = self.rect() outer_size = min([rect.width(), rect.height()]) outer_rect = QRectF(0, 0, outer_size, outer_size) inner_rect = self.board_rect() self._painter.fillRect(outer_rect, self._border_brush) self._painter.setPen(QPen(QBrush(Qt.black), 3)) self._painter.drawRect(inner_rect) labels = 'ABCDEFGHIJ' for i in xrange(self.board.SIZE): # bottom labels left = self._border_size + i * self._field_size top = outer_rect.bottom() - self._border_size text_rect = QRectF(left, top, self._field_size, self._border_size) self._painter.drawText(text_rect, Qt.AlignCenter, labels[i]) # left labels top = self._border_size + (self.board.SIZE - i - 1) * self._field_size text_rect = QRectF(0, top, self._border_size, self._field_size) self._painter.drawText(text_rect, Qt.AlignCenter, str(i + 1)) def draw_fields(self): for x_field in xrange(self.board.SIZE): for y_field in xrange(self.board.SIZE): if (x_field, y_field) == self._selected_field: brush = self._selected_field_brush elif (x_field, y_field) in self._available_moves: brush = self._available_move_field_brush elif self.board.is_black_field(x_field, y_field): brush = self._black_field_brush else: brush = self._white_field_brush self.draw_field(x_field, y_field, brush) def draw_field(self, x_field, y_field, brush): self._painter.fillRect(self.field_rect(x_field, y_field), brush) def draw_checkers(self): for checker in self.board.checkers: if checker.color == Checker.BLACK: if checker.is_king: brush = self._black_king_checker_brush pen = self._black_king_checker_pen else: brush = self._black_checker_brush pen = self._black_checker_pen else: if checker.is_king: brush = self._white_king_checker_brush pen = self._white_king_checker_pen else: brush = self._white_checker_brush pen = self._white_checker_pen self._painter.setBrush(brush) self._painter.setPen(pen) field_rect = self.field_rect(checker.x, checker.y) radius = self._field_size / 2.0 * self.CHECKER_SIZE_TO_FIELD self._painter.drawEllipse(field_rect.center(), radius, radius)
def paintEvent(self, e): """ Draw the border. """ if self.drawBorder: p = QPainter(self) if self.roundCorners: # draw quarter-circles for borders p.drawArc(0, 0, self.cornerRadius, self.cornerRadius, 1440, 1440) p.drawArc(0, self.height() - self.cornerRadius, self.cornerRadius, self.cornerRadius, 2880, 1440) p.drawArc(self.width() - self.cornerRadius, self.height() - self.cornerRadius, self.cornerRadius, self.cornerRadius, 4320, 1440) p.drawArc(self.width() - self.cornerRadius, 0, self.cornerRadius, self.cornerRadius, 5760, 1440) corner = self.cornerRadius / 2 p.drawLine(corner, 0, self.width() - corner, 0) p.drawLine(0, corner, 0, self.height() - corner) p.drawLine(corner, self.height()-1, self.width() - corner, self.height()-1) p.drawLine(self.width()-1, corner, self.width()-1, self.height() - corner) else: p.drawRect(0, 0, self.width(), self.height()) QWidget.paintEvent(self, e)