class ImageLabel(QtWidgets.QLabel): ResizeSignal = QtCore.Signal(int) def __init__(self, parent): super(ImageLabel, self).__init__(parent) self.setSizePolicy(QtWidgets.QSizePolicy.Ignored, QtWidgets.QSizePolicy.Ignored) self.setText("") self.pix = QPixmap() self.setPixmap(self.pix) self.ResizeSignal.connect(self.resizeEvent) self.installEventFilter(self) def eventFilter(self, watched: QtCore.QObject, event: QtCore.QEvent) -> bool: if (event.type() == QtCore.QEvent.Resize): if not self.pix.isNull(): pixmap = self.pix.scaled( self.width(), self.height(), QtCore.Qt.AspectRatioMode.KeepAspectRatio, QtCore.Qt.TransformationMode.SmoothTransformation) if pixmap.width() != self.width() or pixmap.height( ) != self.height(): self.ResizeSignal.emit(0) return super().eventFilter(watched, event) def resizeEvent(self, _): if not self.pix.isNull(): size = self.size() self.setPixmap( self.pix.scaled( size, QtCore.Qt.AspectRatioMode.KeepAspectRatio, QtCore.Qt.TransformationMode.SmoothTransformation)) #Paint event that is currently not needed # def paintEvent(self, event): # if not self.pix.isNull(): # size = self.size() # painter = QPainter() # point = QtCore.QPoint(0, 0) # scaledPix = self.setPixmap(self.pix.scaled(size, QtCore.Qt.AspectRatioMode.KeepAspectRatio, QtCore.Qt.TransformationMode.SmoothTransformation)) # point.setX((size.width() - scaledPix.width() / 2)) # point.setY((size.height() - scaledPix.height() / 2)) # painter.drawPixmap(point, scaledPix) def changePixmap(self, img): self.pix = img self.repaint() self.ResizeSignal.emit(1) def clearPixmap(self): self.pix = QPixmap() self.setPixmap(self.pix) self.repaint()
def paint(self, painter, option, index): super(Delegate, self).paint(painter, option, index) # HOVER if option.state & QStyle.State_MouseOver: painter.fillRect(option.rect, QColor("#F1F1F1")) else: painter.fillRect(option.rect, Qt.transparent) # SELECTED if option.state & QStyle.State_Selected: painter.fillRect(option.rect, QColor("#F1F1F1")) # DRAW ICON icon = QPixmap() icon.load(index.data()[1]) icon = icon.scaled(24, 24, Qt.IgnoreAspectRatio, Qt.SmoothTransformation) left = 24 # margin left icon_pos = QRect(left, ((self._height - icon.height()) / 2) + option.rect.y(), icon.width(), icon.height()) painter.setRenderHint(QPainter.Antialiasing) painter.setRenderHint(QPainter.SmoothPixmapTransform) painter.drawPixmap(icon_pos, icon) # DRAW TEXT font = QFont("Roboto Black", 12) text_pos = QRect((left * 2) + icon.width(), option.rect.y(), option.rect.width(), option.rect.height()) painter.setFont(font) painter.setPen(Qt.black) painter.drawText(text_pos, Qt.AlignVCenter, index.data()[0])
def PreviewWindow(self): self.statusBar().showMessage('Tablecloth preview generated.') self.statusBar().removeWidget(self.progress_bar) # Now you can go back to rigging self.ChangeAppStatus(True) self.preview_wid = QWidget() self.preview_wid.resize(600, 600) self.preview_wid.setWindowTitle("Tablecloth preview") tablecloth = QPixmap(tempfile.gettempdir()+"\\Table_Dif.jpg") tablecloth_preview_title = QLabel(self) tablecloth_preview_title.setText("Tablecloth preview (1/4 scale)") tablecloth_preview = QLabel(self) tablecloth_preview.setPixmap(tablecloth.scaled(512,512)) confirm = QPushButton(self) confirm.setText("Confirm") confirm.clicked.connect(self.GenerateImage) confirm.clicked.connect(self.preview_wid.close) vbox = QVBoxLayout() vbox.setAlignment(QtCore.Qt.AlignCenter) vbox.addWidget(tablecloth_preview_title) vbox.addWidget(tablecloth_preview) vbox.addWidget(confirm) self.preview_wid.setLayout(vbox) self.preview_wid.setWindowModality(QtCore.Qt.ApplicationModal) self.preview_wid.activateWindow() self.preview_wid.raise_() self.preview_wid.show()
def update(self): for i, fact in enumerate(self.game.factories): img = QPixmap('pictures/factory1.png') self.money[i].setText(str(fact.money)) if i == self.game.cur_factory: self.money[i].setFont(QFont('Times', 24, QFont.Bold)) img = img.scaled(280, 280, QtCore.Qt.KeepAspectRatio) else: self.money[i].setFont(QFont('Times', 14)) img = img.scaled(200, 200, QtCore.Qt.KeepAspectRatio) self.pictures[i].setPixmap(img) self.level.setText(f'Уровень: {self.game.cur_level}') self.river.setText( f'Процент загрязнения реки: {self.game.river.mud_level}%')
def paintEvent(self, event): super(Profile, self).paintEvent(event) # DRAW BACKGROUND IMAGE p = QPainter(self) p.setRenderHint(QPainter.Antialiasing) image = QPixmap() image.load("res/img/back.jpg") image = image.scaled(self.width(), self.height(), Qt.IgnoreAspectRatio, Qt.SmoothTransformation) p.drawPixmap(self.rect(), image)
def __chose_image(self): dir = os.getcwd() path = QFileDialog.getOpenFileName( self, 'Open Image', dir, "Image Files (*.png *.jpg *.bmp *.jpeg)") if path[0] != '': self.image = path[0].split( '/')[-1] if path[0] != '' else self.image im = cv2.imread(self.image, 0) ret, trash = cv2.threshold(im, 240, 255, cv2.THRESH_BINARY) self.image_bw = self.image.split('.')[0] + '_binary.jpg' cv2.imwrite(self.image_bw, trash) image = QPixmap(self.image_bw) new_image = image.scaled(540, 249, Qt.KeepAspectRatio, Qt.FastTransformation) self.put_image(widget=self.ui.sourceLabel, image=new_image)
def browser(self): """Slot function to initialize image thumbnails for the 'browse mode.'""" while self.h_box2.itemAt(0): self.h_box2.takeAt(0).widget().deleteLater() index = (self.index + (len(self.files) - 2)) % len(self.files) for i, file in enumerate(self.files): file = self.dir_now + '/' + self.files[index] label = ClickableLabel(self, file) self.h_box2.addWidget(label) pix = QPixmap(file) if (pix.size().width() > self.browse_bar.width() / 5 or pix.size().height() > 100): pix = pix.scaled(self.browse_bar.width() / 5, 100, Qt.KeepAspectRatio) label.setPixmap(pix) index = (index + 1) % len(self.files) if i == 4: break
def paintAvatar(self): # DRAW PROFILE IMAGE image = QPixmap() image.load("res/img/icons/user.png") image = image.scaled(54, 54, Qt.IgnoreAspectRatio, Qt.SmoothTransformation) _margin = 16 _margin_text = 24 self.avatar = QLabel(self) self.avatar.setCursor(Qt.PointingHandCursor) self.avatar.setAttribute(Qt.WA_TranslucentBackground) self.avatar.setPixmap(image) self.avatar.move(self.rect().x() + _margin, self.rect().y() + _margin) self.username = QLabel(self) self.username.setStyleSheet("color: white;") self.username.setFont(QFont("Roboto Light", 14)) self.username.setCursor(Qt.PointingHandCursor) self.username.setAttribute(Qt.WA_TranslucentBackground) self.username.setText("dryerem19") self.username.move(self.rect().x() + _margin_text, self.height() - 50)
def generate_pixmap_from_temp(width, height, ext) -> QPixmap: pixmap = QPixmap(f'{settings.TEMP_DIR}/{ext}') pixmap = pixmap.scaled(calculate_image_width(width), calculate_image_height(height), aspectMode=Qt.KeepAspectRatio) return pixmap
def scale_pixmap(pixmap: QPixmap, width: int, height: int): scaled_pixmap = pixmap.scaled(width, height, Qt.KeepAspectRatio, Qt.SmoothTransformation) return scaled_pixmap
def __init__(self, game): super().__init__() self.game = game self.level = QLabel(f'Уровень: {self.game.cur_level}') self.river = QLabel( f'Процент загрязнения реки: {self.game.river.mud_level}%') self.level.setFont(QFont('Times', 28)) self.river.setFont(QFont('Times', 24)) self.money = [] self.pictures = [] for i, fact in enumerate(game.factories): label = QLabel() img = QPixmap('pictures/factory1.png') self.money.append(QLabel(str(fact.money))) if i == self.game.cur_factory: self.money[i].setFont(QFont('Times', 24, QFont.Bold)) img = img.scaled(280, 280, QtCore.Qt.KeepAspectRatio) else: self.money[i].setFont(QFont('Times', 14)) img = img.scaled(200, 200, QtCore.Qt.KeepAspectRatio) label.setPixmap(img) self.pictures.append(label) self.button_work = QPushButton('Работать') self.button_work_and_clean = QPushButton('Работать и очистить реку') self.button_do_nothing = QPushButton('Простаивать') self.main_layout = QtWidgets.QVBoxLayout(self) self.main_layout.addWidget(self.level) self.main_layout.addWidget(self.river) self.factories_layout = QtWidgets.QHBoxLayout() for picture in self.pictures: self.factories_layout.addWidget(picture) picture.setAlignment(QtCore.Qt.AlignCenter) self.money_layout = QtWidgets.QHBoxLayout() for money in self.money: self.money_layout.addWidget(money) money.setAlignment(QtCore.Qt.AlignCenter) self.main_layout.addLayout(self.factories_layout) self.main_layout.addLayout(self.money_layout) self.main_layout.addWidget(self.button_work) self.main_layout.addWidget(self.button_work_and_clean) self.main_layout.addWidget(self.button_do_nothing) self.button_work_and_clean.clicked.connect(self.work_and_clean) self.button_work.clicked.connect(self.work) self.button_do_nothing.clicked.connect(self.do_nothing) with open('style.css') as f: style = f.read() self.level.setStyleSheet(style) self.button_work.setStyleSheet(style) self.button_work_and_clean.setStyleSheet(style) self.button_do_nothing.setStyleSheet(style)
def draw_grid(self, art: QPixmap, painter: typing.Optional[QPainter] = None): rows = self.rows columns = self.cols if self.row_clues: x_filled_portion = 0.97 * rows / (rows + 1) y_filled_portion = 0.97 * columns / (columns + 1) scaled_art = art.scaled(self.rect.width() * x_filled_portion, self.rect.height() * y_filled_portion, Qt.AspectRatioMode.KeepAspectRatio) else: filled_portion = 0.84 scaled_art = art.scaled(self.rect.width() * filled_portion, self.rect.height() * filled_portion, Qt.AspectRatioMode.KeepAspectRatio) cell_height = scaled_art.height() / rows cell_width = scaled_art.width() / columns if self.row_clues: left_clue_border = round( (self.rect.width() - scaled_art.width() - cell_width) / 3) top_clue_border = round( (self.rect.height() - scaled_art.height() - cell_height) / 3) min_border = min(left_clue_border, top_clue_border) left_clue_border = round((3 * left_clue_border - min_border) / 2) top_clue_border = round((3 * top_clue_border - min_border) / 2) left_border = left_clue_border + cell_width + min_border top_border = top_clue_border + cell_height + min_border else: left_border = int((self.rect.width() - scaled_art.width()) / 2) top_border = int((self.rect.height() - scaled_art.height()) / 2) left_clue_border = top_clue_border = None if painter is None: painter = QPainter(self.target) if self.background: painter.fillRect(self.rect, self.background) painter.translate(0, self.rect.top()) if not self.row_clues: self.draw_letters(cell_width, cell_height, left_border, top_border, painter) is_grid_filled = (self.selected_row is not None or self.selected_column is not None) self.row_clue_rects.clear() for i, clue in enumerate(self.row_clues): clue_rect = QRect(left_clue_border, round(top_border + i * cell_height), round(cell_width), round(cell_height)) self.row_clue_rects.append(clue_rect) painter.drawPixmap(clue_rect, clue) if is_grid_filled: for j in range(self.cols): painter.drawPixmap(round(left_border + j * cell_width), round(top_border + i * cell_height), round(cell_width), round(cell_height), clue) self.column_clue_rects.clear() for j, clue in enumerate(self.column_clues): clue_rect = QRect(round(left_border + j * cell_width), top_clue_border, round(cell_width), round(cell_height)) self.column_clue_rects.append(clue_rect) painter.drawPixmap(clue_rect, clue) if is_grid_filled: for i in range(self.rows): y = round(top_border + i * cell_height) painter.drawPixmap(round(left_border + j * cell_width), y, round(cell_width), round(cell_height), clue) if is_grid_filled: painter.drawPixmap(left_border, top_border, round(self.cols * cell_width), round(self.rows * cell_height), scaled_art) painter.setPen(QPen(QColor('lightgrey'), round(cell_width / 50))) if self.row_clues: painter.drawRect(left_clue_border, top_border, round(cell_width), round(cell_height * rows)) painter.drawRect(left_border, top_clue_border, round(cell_width * columns), round(cell_height)) painter.drawRect(left_border, top_border, round(cell_width * columns), round(cell_height * rows)) for i in range(1, rows): y = round(top_border + i * cell_height) painter.drawLine(left_border, y, round(left_border + cell_width * columns), y) if self.row_clues: painter.drawLine(left_clue_border, y, round(left_clue_border + cell_width), y) for j in range(1, columns): x = round(left_border + j * cell_width) painter.drawLine(x, top_border, x, round(top_border + cell_height * rows)) if self.row_clues: painter.drawLine(x, top_clue_border, x, round(top_clue_border + cell_height)) painter.setPen(QPen(QColor('blue'), round(cell_width / 25))) if self.selected_row is not None: painter.drawRect( left_clue_border, round(top_border + cell_height * self.selected_row), round(cell_width), round(cell_height)) if self.selected_column is not None: painter.drawRect( round(left_border + cell_width * self.selected_column), top_clue_border, round(cell_width), round(cell_height)) painter.translate(0, -self.rect.top())
class ItemInfoBox(QWidget): def __init__(self, item: Item): super().__init__() layout = QGridLayout(self) meta = item.meta # infobox spans one row and two columns. SPAN = (1, 2) # wikipedia-style info box at the side title = TitleLabel(f"<h2><i>{meta.title}</i></h2>") layout.addWidget(title, 0, 0, *SPAN) self.cover = QPixmap() try: manga_path = CACHE.root / meta.hash cover_path = next(manga_path.glob("cover.*")) except StopIteration: self.cover.load(":/missing.jpg") else: self.cover.load(str(cover_path)) self.cover = self.cover.scaled( int(self.width() / 2), self.height(), Qt.KeepAspectRatio, Qt.SmoothTransformation, ) self.cover_label = QLabel() self.cover_label.setScaledContents(True) self.cover_label.setPixmap(self.cover) layout.addWidget(self.cover_label, 1, 0, *SPAN) if meta.alt_titles is not None: _alt_titles = "<br>".join(f"<i>{t}</i>" if _is_ascii(t) else t for t in meta.alt_titles) else: _alt_titles = "(empty)" alt_titles = TitleLabel(_alt_titles) alt_titles.setStyleSheet("background-color: #DDDDFF; color: black;") layout.addWidget(alt_titles, 2, 0, *SPAN) genre_header = SubtitleLabel("Genre") layout.addWidget(genre_header, 3, 0) if meta.genres is not None: _genres = "<br>".join(_normalize(g) for g in meta.genres) else: _genres = "(empty)" genres = QLabel(_genres) layout.addWidget(genres, 3, 1) manga_header = TitleLabel("<b>Manga</b>") layout.addWidget(manga_header, 4, 0, *SPAN) author_header = SubtitleLabel("Authored by") layout.addWidget(author_header, 5, 0) if meta.authors is not None: _authors = "<br>".join(a for a in meta.authors) else: _authors = "(empty)" authors = QLabel(_authors) layout.addWidget(authors, 5, 1) source_header = SubtitleLabel("Source") layout.addWidget(source_header, 6, 0) source = QLabel(f'<a href="{meta.url}">{meta.url}</b>') source.setWordWrap(True) source.setOpenExternalLinks(True) layout.addWidget(source, 6, 1) langs_header = SubtitleLabel("Languages") layout.addWidget(langs_header, 7, 0) manga = CACHE[meta.hash] langs_set = set() for chapter in manga["chapters"].values(): langs_set.update(chapter.keys()) langs = QLabel("<br>".join(common.describe_langs(list(langs_set)))) layout.addWidget(langs, 7, 1)
def test_board_size_2(pixmap_differ: PixmapDiffer): actual: QPainter expected: QPainter with pixmap_differ.create_painters(240, 240, 'margo_board_size_2') as (actual, expected): expected_scene = QGraphicsScene(0, 0, 240, 240) full_board = MargoDisplay.load_pixmap('board-1.png') width = full_board.width() height = full_board.height() top_height = round(height * 0.28) left_width = round(width * 0.28) right_width = round(width * 0.279) bottom_height = round(height * 0.29) assembled_board = QPixmap(left_width + right_width, top_height + bottom_height) assembled_board.fill(Qt.transparent) assembled_painter = QPainter(assembled_board) # top left assembled_painter.drawPixmap(0, 0, left_width, top_height, full_board, 0, 0, left_width, top_height) # top right assembled_painter.drawPixmap(left_width, 0, right_width, top_height, full_board, width - right_width, 0, right_width, top_height) # bottom left assembled_painter.drawPixmap(0, top_height, left_width, bottom_height, full_board, 0, height - bottom_height, left_width, bottom_height) # bottom right assembled_painter.drawPixmap(left_width, top_height, right_width, bottom_height, full_board, width - right_width, height - bottom_height, right_width, bottom_height) assembled_painter.end() scaled_board = assembled_board.scaled(232, 240, Qt.KeepAspectRatio, Qt.SmoothTransformation) board_item = expected_scene.addPixmap(scaled_board) board_item.setPos(4, 0) white_ball = MargoDisplay.load_pixmap('ball-w-shadow-1.png', QSize(103, 103)) black_ball = MargoDisplay.load_pixmap('ball-b-shadow-1.png', QSize(103, 103)) expected_scene.addPixmap(white_ball).setPos(23, 108) expected_scene.addPixmap(black_ball).setPos(113, 18) expected_scene.render(expected) display = MargoDisplay(size=2) trigger_resize(display, 292, 240) display.resize(348, 264) board_text = """\ A C 3 . B 3 1 W . 1 A C >B """ display.update_board(SpargoState(board_text, size=2)) render_display(display, actual)
def __init__(self): super().__init__() # Declare Widgets self.homepage_label = QLabel('Home') self.search_label = QLabel('Find an Image!') self.srch_box = QLineEdit() # input field for search self.srch_btn = QPushButton("Search") # Create U.I. Layout mbox = QVBoxLayout() # Main layout vbox = QVBoxLayout() # Layout for search feature vbox.addWidget(self.homepage_label) vbox.addWidget(self.search_label) vbox.addWidget(self.srch_box) vbox.addWidget(self.srch_btn) gbox1 = QGroupBox() # Set group for search feature layout gbox1.setLayout(vbox) mbox.addWidget(gbox1) # Home Images images = [] images = self.getHomepageImages() # Create layout for images vbox2 = QHBoxLayout() # horizontal layout i = 0 for img in images: # iterate through images list self.label = QLabel() pixmap1 = QPixmap(img) # set image pixmap1 = pixmap1.scaled(300, 300, Qt.KeepAspectRatio) self.label.setPixmap(pixmap1) temp_vbox = QVBoxLayout() temp_vbox.addWidget(self.label) gbox2 = QGroupBox() # group box for current image gbox2.setLayout(temp_vbox) gbox2.setStyleSheet("background-color: grey") vbox2.addWidget(gbox2) i += 1 gbox3 = QGroupBox() # main group box for images gbox3.setLayout(vbox2) mbox.addWidget(gbox3) self.setLayout(mbox) # Styling self.setStyleSheet(""" color: orange; font-family: Comfortaa; """) self.srch_btn.setStyleSheet(":hover { background-color:cyan }") gbox1.setStyleSheet(""" font-size: 18px """) # Listeners self.srch_btn.clicked.connect(self.find_images)
class MainWindow(QMainWindow): def __init__(self): super(MainWindow, self).__init__() self.ui = Ui_MainWindow() self.ui.setupUi(self) self.art_scene = QGraphicsScene(self) self.art_scene.addText('Open an image file.') self.ui.art_view.setScene(self.art_scene) self.symbols_scene = QGraphicsScene(self) self.ui.symbols_view.setScene(self.symbols_scene) self.ui.action_exit.triggered.connect(self.close) self.ui.action_open_art.triggered.connect(self.open_image) self.ui.action_open_words.triggered.connect(self.open_words) self.ui.action_save.triggered.connect(self.save_pdf) self.ui.action_save_png.triggered.connect(self.save_png) self.ui.action_shuffle.triggered.connect(self.shuffle) self.ui.action_sort.triggered.connect(self.sort) self.ui.rows.valueChanged.connect(self.on_options_changed) self.ui.columns.valueChanged.connect(self.on_options_changed) self.ui.word_clues_radio.toggled.connect(self.on_options_changed) self.ui.symbol_clues_radio.toggled.connect(self.on_options_changed) self.word_layout = QGridLayout(self.ui.word_content) self.ui.word_scroll.setWidgetResizable(True) self.word_labels: typing.Dict[str, QLabel] = {} self.word_shuffler = WordShuffler([]) self.clues = None self.pixmap = self.scaled_pixmap = self.mini_pixmap = None self.sliced_pixmap_item: typing.Optional[QGraphicsPixmapItem] = None self.sliced_image: typing.Optional[QImage] = None self.selection_grid: typing.Optional[SelectionGrid] = None self.cells = [] self.art_shuffler: typing.Optional[ArtShuffler] = None self.symbols_source_pixmap_item: typing.Optional[ QGraphicsPixmapItem] = None self.symbols_pixmap_item: typing.Optional[QGraphicsPixmapItem] = None self.symbols_image: typing.Optional[QImage] = None self.symbols_shuffler: typing.Optional[ArtShuffler] = None self.selected_row: typing.Optional[int] = None self.selected_column: typing.Optional[int] = None self.settings = QSettings() self.image_path: typing.Optional[str] = self.settings.value( 'image_path') self.words_path: typing.Optional[str] = self.settings.value( 'words_path') self.dirty_letters = set() self.timer = QTimer() self.timer.setInterval(500) self.timer.setSingleShot(True) # noinspection PyUnresolvedReferences self.timer.timeout.connect(self.on_dirty) self.row_count = self.column_count = 0 self.clue_type = ClueType.words self.ui.rows.setValue(self.settings.value('row_count', 6, int)) self.ui.columns.setValue(self.settings.value('column_count', 4, int)) clue_type_name = self.settings.value('clue_type', ClueType.words.name) try: clue_type = ClueType[clue_type_name] except KeyError: clue_type = ClueType.words if clue_type == ClueType.words: self.ui.word_clues_radio.setChecked(True) else: self.ui.symbol_clues_radio.setChecked(True) self.row_clues: typing.List[QPixmap] = [] self.column_clues: typing.List[QPixmap] = [] self.on_options_changed() def on_dirty(self): for letter in self.dirty_letters: self.word_labels[letter].setText( self.word_shuffler.make_display(letter)) self.settings.setValue(f'word_{letter}', self.word_shuffler[letter]) if self.dirty_letters: self.clues = self.word_shuffler.make_clues() self.art_shuffler.clues = dict(self.clues) self.dirty_letters.clear() self.on_selection_moved() if self.pixmap is not None: x, y, width, height = self.get_selected_fraction() self.settings.setValue('x', x) self.settings.setValue('y', y) self.settings.setValue('width', width) self.settings.setValue('height', height) new_rows = self.ui.rows.value() new_columns = self.ui.columns.value() if self.ui.word_clues_radio.isChecked(): new_clue_type = ClueType.words else: new_clue_type = ClueType.symbols if (new_rows, new_columns, new_clue_type) == (self.row_count, self.column_count, self.clue_type): return self.settings.setValue('row_count', new_rows) self.settings.setValue('column_count', new_columns) self.settings.setValue('clue_type', new_clue_type.name) self.row_count, self.column_count = new_rows, new_columns self.clue_type = new_clue_type word_count = (self.row_count * self.column_count) while self.word_layout.count(): layout_item = self.word_layout.takeAt(0) layout_item.widget().deleteLater() self.word_labels.clear() self.row_clues.clear() self.column_clues.clear() if self.image_path is not None: self.load_image(self.image_path) if self.words_path is not None: self.load_words(self.words_path) letters = [chr(65 + i) for i in range(word_count)] if self.word_shuffler.needs_blank: letters.insert(0, '') word_fields = {} for i, letter in enumerate(letters): word_field = QLineEdit() self.word_layout.addWidget(word_field, i, 0) # noinspection PyUnresolvedReferences word_field.textEdited.connect(partial(self.on_word_edited, letter)) word_label = QLabel() self.word_layout.addWidget(word_label, i, 1) self.word_labels[letter] = word_label word_fields[letter] = word_field for i, letter in enumerate(letters): word = self.settings.value(f'word_{letter}', '') self.word_shuffler[letter] = word self.dirty_letters.add(letter) word_fields[letter].setText(word) def on_options_changed(self, *_): self.timer.start() def shuffle(self): self.clues = self.word_shuffler.make_clues() if self.art_shuffler is not None: self.art_shuffler.shuffle() self.on_selection_moved() def sort(self): if self.art_shuffler is not None: self.art_shuffler.sort() self.on_selection_moved() def open_words(self): word_filter = 'Text files (*.txt)' if self.words_path is None: words_folder = None else: words_folder = str(Path(self.words_path).parent) file_name, _ = QFileDialog.getOpenFileName(self, "Open a words file.", dir=words_folder, filter=word_filter) if not file_name: return self.settings.setValue('words_path', file_name) self.load_words(file_name) def load_words(self, words_path): with open(words_path) as f: choice = 0 if choice == 0: self.word_shuffler = WordShuffler(f) else: self.word_shuffler = WordStripper(f) def open_image(self): formats = QImageReader.supportedImageFormats() patterns = (f'*.{fmt.data().decode()}' for fmt in formats) image_filter = f'Images ({" ".join(patterns)})' if self.image_path is None: image_folder = None else: image_folder = str(Path(self.image_path).parent) file_name, _ = QFileDialog.getOpenFileName(self, "Open an image file.", dir=image_folder, filter=image_filter) if not file_name: return self.settings.setValue('image_path', file_name) self.load_image(file_name) def load_image(self, image_path): self.pixmap = QPixmap(image_path) if self.pixmap.isNull(): self.pixmap = None self.image_path = image_path self.scale_image() def scale_image(self): if self.pixmap is None: return if self.selection_grid is None: x = self.settings.value('x', 0.0, float) y = self.settings.value('y', 0.0, float) width = self.settings.value('width', 1.0, float) height = self.settings.value('height', 1.0, float) else: x, y, width, height = self.get_selected_fraction() self.art_scene.clear() self.cells.clear() view_size = self.ui.art_view.maximumViewportSize() if view_size.width() == 0: return self.art_scene.setSceneRect(0, 0, view_size.width(), view_size.height()) display_size = QSize(view_size.width() * 0.99 / 2, view_size.height() * 0.99) self.scaled_pixmap = self.pixmap.scaled( display_size, aspectMode=Qt.AspectRatioMode.KeepAspectRatio) self.art_scene.addPixmap(self.scaled_pixmap) scaled_size = self.scaled_pixmap.size() self.selection_grid = SelectionGrid(scaled_size.width() * x, scaled_size.height() * y, scaled_size.width() * width, scaled_size.height() * height, row_count=self.row_count, column_count=self.column_count) self.selection_grid.on_moved = self.on_selection_moved self.art_scene.addItem(self.selection_grid) self.sliced_image = QImage(display_size, QImage.Format.Format_ARGB32_Premultiplied) self.check_clues() self.art_shuffler = ArtShuffler(self.selection_grid.row_count, self.selection_grid.column_count, self.sliced_image, QRect(0, 0, display_size.width(), display_size.height()), clues=self.clues, row_clues=self.row_clues, column_clues=self.column_clues) self.sliced_pixmap_item = self.art_scene.addPixmap( QPixmap.fromImage(self.sliced_image)) self.sliced_pixmap_item.setPos(display_size.width(), 0) self.symbols_scene.clear() self.symbols_source_pixmap_item = self.symbols_scene.addPixmap( self.scaled_pixmap) self.symbols_image = QImage(display_size, QImage.Format.Format_ARGB32_Premultiplied) if self.symbols_shuffler is not None: selected_row = self.symbols_shuffler.selected_row selected_column = self.symbols_shuffler.selected_column else: selected_row = 0 selected_column = None self.symbols_shuffler = ArtShuffler(self.selection_grid.row_count, self.selection_grid.column_count, self.symbols_image, QRect(0, 0, display_size.width(), display_size.height()), row_clues=self.row_clues, column_clues=self.column_clues) self.symbols_shuffler.selected_row = selected_row self.symbols_shuffler.selected_column = selected_column self.symbols_pixmap_item = ClickablePixmapItem( QPixmap.fromImage(self.symbols_image)) self.symbols_pixmap_item.on_click = self.on_symbols_clicked self.symbols_scene.addItem(self.symbols_pixmap_item) self.symbols_pixmap_item.setPos(display_size.width(), 0) self.on_selection_moved() def on_symbols_clicked(self, event: QGraphicsSceneMouseEvent): self.symbols_scene.clearSelection() self.symbols_shuffler.select_clue(event.pos().toPoint()) self.on_selection_moved() def on_word_edited(self, letter, word): self.word_shuffler[letter] = word self.dirty_letters.add(letter) self.timer.start() def get_selected_fraction(self): selection_rect = self.selection_grid.rect() selection_pos = self.selection_grid.pos() size = self.scaled_pixmap.size() x = (selection_pos.x() + selection_rect.x()) / size.width() width = selection_rect.width() / size.width() y = (selection_pos.y() + selection_rect.y()) / size.height() height = selection_rect.height() / size.height() return x, y, width, height def on_selection_moved(self): selected_pixmap = self.get_selected_pixmap() self.art_shuffler.draw(selected_pixmap) self.sliced_pixmap_item.setPixmap(QPixmap.fromImage(self.sliced_image)) selected_pixmap = self.get_selected_pixmap() cell_width = (selected_pixmap.width() / self.selection_grid.column_count) cell_height = (selected_pixmap.height() / self.selection_grid.row_count) self.row_clues.clear() self.column_clues.clear() for i in range(self.selection_grid.row_count): clue_image = selected_pixmap.copy(0, i * cell_height, cell_width, cell_height) self.row_clues.append(clue_image) for j in range(self.selection_grid.column_count): clue_image = selected_pixmap.copy(j * cell_width, 0, cell_width, cell_height) self.column_clues.append(clue_image) self.symbols_shuffler.row_clues = self.row_clues self.symbols_shuffler.column_clues = self.column_clues self.symbols_shuffler.draw_grid(selected_pixmap) self.symbols_pixmap_item.setPixmap( QPixmap.fromImage(self.symbols_image)) self.timer.start() def get_selected_pixmap(self) -> QPixmap: x, y, width, height = self.get_selected_fraction() original_size = self.pixmap.size() selected_pixmap = self.pixmap.copy(x * original_size.width(), y * original_size.height(), width * original_size.width(), height * original_size.height()) return selected_pixmap def resizeEvent(self, event: QResizeEvent): super().resizeEvent(event) self.scale_image() def save_pdf(self): pdf_folder = self.settings.value('pdf_folder') file_name, _ = QFileDialog.getSaveFileName(self, "Save a PDF file.", dir=pdf_folder, filter='Documents (*.pdf)') if not file_name: return self.settings.setValue('pdf_folder', os.path.dirname(file_name)) writer = QPdfWriter(file_name) writer.setPageSize(QPageSize(QPageSize.Letter)) writer.setTitle('Sliced Art Puzzle') writer.setCreator('Don Kirkby') self.paint_puzzle(writer) def save_png(self): pdf_folder = self.settings.value('pdf_folder') file_name, _ = QFileDialog.getSaveFileName(self, "Save an image file.", dir=pdf_folder, filter='Images (*.png)') if not file_name: return writer = QPixmap(1000, 2000) self.paint_puzzle(writer) writer.save(file_name) self.settings.setValue('pdf_folder', os.path.dirname(file_name)) def paint_puzzle(self, writer: QPaintDevice): self.check_clues() painter = QPainter(writer) try: print_shuffler = ArtShuffler(self.art_shuffler.rows, self.art_shuffler.cols, writer, QRect(0, 0, writer.width(), round(writer.height() / 2)), clues=self.clues, row_clues=self.row_clues, column_clues=self.column_clues) print_shuffler.cells = self.art_shuffler.cells[:] print_shuffler.is_shuffled = self.art_shuffler.is_shuffled selected_pixmap = self.get_selected_pixmap() print_shuffler.draw(selected_pixmap, painter) print_shuffler.rect.moveTop(writer.height() / 2) print_shuffler.draw_grid(selected_pixmap, painter) finally: painter.end() def check_clues(self): if self.clue_type == ClueType.words: if self.clues is None: self.clues = self.word_shuffler.make_clues() self.row_clues.clear() self.column_clues.clear() else: self.clues = None
def test_board_size_3(pixmap_differ: PixmapDiffer): actual: QPainter expected: QPainter with pixmap_differ.create_painters(240, 240, 'margo_board_size_3') as (actual, expected): expected_scene = QGraphicsScene(0, 0, 240, 240) full_board = MargoDisplay.load_pixmap('board-1.png') width = full_board.width() height = full_board.height() top_height = round(height * 0.28) mid_height = round(height * 0.21) bottom_height = round(height * 0.29) left_width = round(width * 0.28) mid_width = round(width * 0.22) right_width = round(width * 0.279) assembled_board = QPixmap(left_width + mid_width + right_width, top_height + mid_height + bottom_height) assembled_board.fill(Qt.transparent) assembled_painter = QPainter(assembled_board) # top left assembled_painter.drawPixmap(0, 0, left_width, top_height, full_board, 0, 0, left_width, top_height) # top middle assembled_painter.drawPixmap(left_width, 0, mid_width, top_height, full_board, left_width, 0, mid_width, top_height) # top right assembled_painter.drawPixmap(left_width + mid_width, 0, right_width, top_height, full_board, width - right_width, 0, right_width, top_height) # left middle assembled_painter.drawPixmap(0, top_height, left_width, mid_height, full_board, 0, top_height, left_width, mid_height) # middle middle assembled_painter.drawPixmap(left_width, top_height, mid_width, mid_height, full_board, left_width, top_height, mid_width, mid_height) # right middle assembled_painter.drawPixmap(left_width + mid_width, top_height, right_width, mid_height, full_board, width - right_width, top_height, right_width, mid_height) # bottom left assembled_painter.drawPixmap(0, top_height + mid_height, left_width, bottom_height, full_board, 0, height - bottom_height, left_width, bottom_height) # bottom middle assembled_painter.drawPixmap(left_width, top_height + mid_height, mid_width, bottom_height, full_board, left_width, height - bottom_height, mid_width, bottom_height) # bottom right assembled_painter.drawPixmap(left_width + mid_width, top_height + mid_height, right_width, bottom_height, full_board, width - right_width, height - bottom_height, right_width, bottom_height) assembled_painter.end() scaled_board = assembled_board.scaled(240, 240, Qt.KeepAspectRatio, Qt.SmoothTransformation) board_item = expected_scene.addPixmap(scaled_board) board_item.setPos(2, 0) white_ball = MargoDisplay.load_pixmap('ball-w-shadow-1.png', QSize(76, 76)) black_ball = MargoDisplay.load_pixmap('ball-b-shadow-1.png', QSize(76, 76)) expected_scene.addPixmap(white_ball).setPos(15, 145) expected_scene.addPixmap(black_ball).setPos(81, 79) expected_scene.render(expected) display = MargoDisplay(size=3) display.resize(348, 264) board_text = """\ A C E 5 . . . 5 3 . B . 3 1 W . . 1 A C E >B """ display.update_board(SpargoState(board_text, size=3)) render_display(display, actual)
def __init__(self): super().__init__() # Declare Widgets self.homepage_label = QLabel('Home') self.search_label = QLabel('Find an Image!') self.srch_box = QLineEdit() # input field for search self.srch_btn = QPushButton("Search") # Create U.I. Layout mbox = QVBoxLayout() vbox = QVBoxLayout() vbox.addWidget(self.homepage_label) vbox.addWidget(self.search_label) vbox.addWidget(self.srch_box) vbox.addWidget(self.srch_btn) gbox1 = QGroupBox() gbox1.setLayout(vbox) mbox.addWidget(gbox1) # Homes Images Layout images = [] images = self.getHomepageImages() # Create layout for images vbox2 = QHBoxLayout() i = 0 for img in images: self.label = QLabel() # pic = Image.open(requests.get(img['urls']['thumb'], stream=True).raw) pixmap1 = QPixmap(img) pixmap1 = pixmap1.scaled(300, 300, Qt.KeepAspectRatio) self.label.setPixmap(pixmap1) temp_vbox = QVBoxLayout() temp_vbox.addWidget(self.label) gbox2 = QGroupBox() gbox2.setLayout(temp_vbox) gbox2.setStyleSheet("background-color: grey") vbox2.addWidget(gbox2) i += 1 gbox3 = QGroupBox() gbox3.setLayout(vbox2) mbox.addWidget(gbox3) self.setLayout(mbox) # Styling self.setStyleSheet(""" color: orange; font-family: Comfortaa; """) self.srch_btn.setStyleSheet(":hover { background-color:cyan }") gbox1.setStyleSheet(""" font-size: 18px """) # Listeners self.srch_btn.clicked.connect(self.find_images)
def draw(self, art: QPixmap, painter: typing.Optional[QPainter] = None): filled_portion = 0.6 if self.is_shuffled and not self.row_clues else 0.9 scaled_art = art.scaled(self.rect.width() * filled_portion, self.rect.height() * filled_portion, Qt.AspectRatioMode.KeepAspectRatio) if painter is None: painter = QPainter(self.target) painter.fillRect(self.rect, QColor('white')) cell_height = round(scaled_art.height() / self.rows) vertical_padding = self.rect.height() - self.rows * cell_height row_padding = vertical_padding / self.rows cell_width = round(scaled_art.width() / self.cols) horizontal_padding = self.rect.width() - self.cols * cell_width col_padding = horizontal_padding / self.cols padding = min(row_padding, col_padding) left_border = self.cols * (col_padding - padding) / 2 top_border = self.rows * (row_padding - padding) / 2 font = painter.font() font.setPixelSize(padding / 2.6) painter.setFont(font) old_pen = painter.pen() grey_pen = QPen(QColor('lightgrey')) width = max(cell_width / 35, 2) grey_pen.setWidth(round(width)) y = top_border cell_index = 0 for i in range(self.rows): x = left_border for j in range(self.cols): si, sj, label = self.cells[cell_index] clue = self.clues.get(label.lower(), label) sx = sj * cell_width sy = si * cell_height painter.setPen(grey_pen) painter.drawRect(x + padding / 2, y, cell_width, cell_height) painter.setPen(old_pen) if self.is_shuffled: original_size = new_size = font.pixelSize() while True: # noinspection PyTypeChecker rect = painter.boundingRect(0, 0, cell_width, padding, Qt.AlignmentFlag.AlignLeft, clue) if (rect.width() <= cell_width + padding and rect.height() <= padding): break new_size *= 0.9 font.setPixelSize(new_size) painter.setFont(font) if not self.row_clues: painter.drawText(x, y + cell_height, cell_width + padding, padding, Qt.AlignmentFlag.AlignHCenter, clue) else: painter.drawPixmap(x + padding / 2, y, cell_width, cell_height, self.row_clues[si], 0, 0, 0, 0) painter.drawPixmap(x + padding / 2, y, cell_width, cell_height, self.column_clues[sj], 0, 0, 0, 0) font.setPixelSize(original_size) painter.setFont(font) painter.drawPixmap(x + padding / 2, y, cell_width, cell_height, scaled_art, sx, sy, cell_width, cell_height) x += cell_width + padding cell_index += 1 y += cell_height + padding