Как показать изображения с исходным соотношением размеров в ячейках таблицы - pyqt? - PullRequest
0 голосов
/ 06 августа 2020

Я создал таблицу с определенным столбцом, в котором содержатся изображения, и заставил ячейки растягиваться до размера содержимого с помощью кода фрагмента:

headerh.setSectionResizeMode(QtWidgets.QHeaderView.ResizeToContents)
headerv.setSectionResizeMode(QtWidgets.QHeaderView.ResizeToContents)

, чтобы ширина и высота ячеек корректировались в соответствии с содержимым Ячейки проблемы, с которыми я столкнулся, заключается в том, что ширина и высота всех ячеек настроены на максимальную ширину и высоту, а не на то, что я хочу, который настраивает каждую ячейку для своего собственного содержимого, чтобы все изображения отображались правильно без чрезмерного растяжения, которое разрушает соотношение размеров изображения, и вот изображение показывает, с чем я столкнулся: введите описание изображения здесь

i wi sh есть способ заставить первую ячейку не растягивать свое изображение таким образом! и вот полный код, который я пишу без базы данных!:



from PyQt5.QtWidgets import (QApplication, QComboBox, QDialog,
QDialogButtonBox, QFormLayout, QGridLayout, QGroupBox, QHBoxLayout,
QLabel, QLineEdit, QMenu, QMenuBar, QPushButton, QSpinBox, QTextEdit,
QVBoxLayout)

import sqlite3
import random


class Main(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setWindowTitle('Arabic Math Project')
        self.setContentsMargins(20,20,20,20)
        # create table:
        self.setStyleSheet("""QTableView::item { border: 0px; padding: 10px;}QTableView{font-size:20px;}QPushButton{width:200px;height:30px}QLineEdit {width:200px;height:50px;}""")
        layout = QVBoxLayout()

        self.btn = QtWidgets.QPushButton("click it")
        self.searchBar = QtWidgets.QLineEdit()
        self.searchBar.setAlignment(QtCore.Qt.AlignCenter)
        self.searchBar.setStyleSheet("font-size:35px;")
        self.searchBar.setPlaceholderText("search")
        self.searchBar.textChanged.connect(self.startSearchThreading) #editingFinished()
        self.table = QtWidgets.QTableWidget()
        
        #cells auto-resizing 
        headerh = self.table.horizontalHeader() 
        headerh.setSectionResizeMode(QtWidgets.QHeaderView.ResizeToContents)
        headerv = self.table.verticalHeader()
        headerv.setSectionResizeMode(QtWidgets.QHeaderView.ResizeToContents)

        
        
        
        

        conn = sqlite3.connect("math.db")
        conn.text_factory = bytes
        self.cur = conn.cursor()


        data = self.cur.execute("select * from problems;").fetchall();conn.close()
        self.dims = (lambda x: (len(x), len(x[0])))(data) #(rows number, col number)

        [self.table.insertRow(i) for i in [i for i in range(self.dims[0])]]
        [self.table.insertColumn(i) for i in [i for i in range(self.dims[1]+1)]]

        #changing h-header names .
        self.table.setHorizontalHeaderLabels(["Unique", "Image", "Test", "Year", "Lesson", "Comment", "Options", "Options-advanced"])

        for c in range(self.dims[1]):
            for r in range(self.dims[0]):
                if c!=1:self.table.setItem(r, c, QtWidgets.QTableWidgetItem(data[r][c].decode("utf-8"))) 
                else:self.table.setCellWidget(r, c, self.getImage(data[r][c]))

        for r in range(self.dims[0]):self.table.setCellWidget(r, self.dims[1], Options(ops=[data[r][self.dims[1]-1].decode("utf-8")]))

        # connect table signals:
        #self.table.cellChanged.connect(self.cell_changed)
        #self.table.itemChanged.connect(self.item_changed)

        
        
        layout.addWidget(self.searchBar)
        layout.addWidget(self.btn)
        layout.addWidget(self.table)
        self.setLayout(layout)

        
        

    def getImage(self, image):
        imageLabel = QLabel()
        imageLabel.setText('')
        imageLabel.setScaledContents(True)
        pixmap = QtGui.QPixmap()
        pixmap.loadFromData(image, "jpg")
        imageLabel.setPixmap(pixmap)
        return imageLabel

    def startSearchThreading(self):
        self.table.setRowCount(0)
        self.update = updateTable(data= self.searchBar.text())
        self.update.new_signal.connect(self.Search)
        self.update.start()

    def create(self):
        self.createFormGroupBox()
        return self.formGroupBox

    @QtCore.pyqtSlot(int, int, bytes, bool, bytes)
    def Search(self, r, c, d, newRowOrder, ops):
        #print(r, c, d.decode("utf-8"))

        if newRowOrder:self.table.insertRow(self.table.rowCount()) # create new row.        
        if c!=1:self.table.setItem(r, c, QtWidgets.QTableWidgetItem(d.decode("utf-8"))) 
        else:self.table.setCellWidget(r, c, self.getImage(d))

        for r in range(self.dims[1]):self.table.setCellWidget(r, self.dims[1], Options(ops=[ops]))


class updateTable(QtCore.QThread):
    def __init__(self, parent=None, data=True):
        super(QtCore.QThread, self).__init__()
        self.data = data

    new_signal = QtCore.pyqtSignal(int, int, bytes, bool, bytes)

    def run(self):
        currRow = 0
        conn = sqlite3.connect("math.db")
        conn.text_factory = bytes
        self.cur = conn.cursor()
        searched = self.cur.execute(" SELECT * FROM problems WHERE text LIKE ('%' || ? || '%') ", (self.data,)).fetchall()
        dims = (lambda x: (len(x), len(x[0])))(searched) if searched!=[] else (0, 0)
        print(dims)
        for r in range(dims[0]):
            for c in range(dims[1]):
                self.new_signal.emit(r, c, searched[r][c], True if c==0 else False, searched[r][dims[1]-1])
                #if c!=1:self.table.setItem(r, c, QtWidgets.QTableWidgetItem(searched[r][c].decode("utf-8"))) 
                #else:self.table.setCellWidget(r, c, self.getImage(searched[r][c]))

            #self.new_signal.emit(1, 2, searched)



class Options(QtWidgets.QWidget):
    def __init__(self, parent=None, ops=[]):
        super(Options, self).__init__(parent)
        self.setStyleSheet("""QTableView::item { border: 0px; padding: 10px;}QTableView{font-size:20px;}QPushButton{width:200px;height:30px}QLineEdit {width:200px;height:50px;}""")
        self.i = random.randint(1, 100)
        layout = QFormLayout()
        layout.addRow(QLabel("Name:"), QLineEdit())
        layout.addRow(QLabel("Country:"), QComboBox())
        layout.addRow(QLabel("Age:"), QSpinBox())
        self.btn = QtWidgets.QPushButton("click")
        self.btn.clicked.connect(self.do)
        layout.addWidget(self.btn)
        self.setLayout(layout)
        print(ops)
    def do(self):
        print(f"clicked {self.i}")
if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    main = Main()
    main.resize(600,600)
    main.show()
    app.exec_()

1 Ответ

0 голосов
/ 06 августа 2020

Если вы используете QLabel с setScaledContents, он всегда будет пытаться масштабировать содержимое, а игнорирует соотношение сторон.

Вы можете использовать подкласс QLabel, который отменяет поведение рисования по умолчанию всякий раз, когда существует QPixmap и текущее соотношение размеров отличается от соотношения размеров растрового изображения.

class ScaledPixmapLabel(QtWidgets.QLabel):
    def __init__(self):
        super().__init__()
        self.setScaledContents(True)

    def paintEvent(self, event):
        if self.pixmap():
            pm = self.pixmap()
            originalRatio = pm.width() / pm.height()
            currentRatio = self.width() / self.height()
            if originalRatio != currentRatio:
                qp = QtGui.QPainter(self)
                pm = self.pixmap().scaled(self.size(), QtCore.Qt.KeepAspectRatio, QtCore.Qt.SmoothTransformation)
                rect = QtCore.QRect(0, 0, pm.width(), pm.height())
                rect.moveCenter(self.rect().center())
                qp.drawPixmap(rect, pm)
                return
        super().paintEvent(event)


class Main(QtWidgets.QWidget):
    # ...
    def getImage(self, image):
        imageLabel = ScaledPixmapLabel()
        pixmap = QtGui.QPixmap()
        pixmap.loadFromData(image, "jpg")
        imageLabel.setPixmap(pixmap)
        return imageLabel

PS: Вам не нужно использовать setText('') на новом QLabel, он уже имеет нет текста.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...