PyQt Сохранить изображение из QTableView в БД SQLite с помощью Delegate - PullRequest
1 голос
/ 18 апреля 2020

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

Вот делегат, которым я сейчас пользуюсь

class ImageDelegate(qtw.QStyledItemDelegate): 

    # def createEditor(self, parent, option, proxyModelIndex):
    def createEditor(self, parent, option, index):

        self.lbText = qtw.QLabel(parent)
        self.lbText.setAlignment(qtc.Qt.AlignCenter)
        self.printFileLoc = qtw.QFileDialog.getOpenFileName(parent,  caption = 'Open Print', filter = '*.jpg')
        self.lbPixmap = qtg.QPixmap(self.printFileLoc[0]) #[0] brings back path to image
        self.lbText.setPixmap(self.lbPixmap.scaled(70,100, qtc.Qt.KeepAspectRatio))

        return self.lbText


    def setModelData(self, editor, model, index):

        self.plants_model = qts.QSqlRelationalTableModel()
        self.plants_model.setTable('plant_list')
        self.plants_model.setData(index, self.lbText, qtc.Qt.EditRole)

А вот где я использую экземпляр класса делегата

    self.imageDelegate = ImageDelegate()
        self.plant_list.setItemDelegateForColumn(
            self.plants_model.fieldIndex('photo'),
            self.imageDelegate) 

Есть идеи?

**** Минимальный воспроизводимый код по запросу:

import sys, csv
from PyQt5 import QtWidgets as qtw
from PyQt5 import QtCore as qtc
from PyQt5 import QtGui as qtg
from PyQt5 import QtSql as qts
from PyQt5.QtPrintSupport import QPrintDialog, QPrinter, QPrintPreviewDialog
from PyQt5.Qt import QFileInfo
import sqlite3
from datetime import date
from PyQt5.QtGui import QPixmap


class DateDelegate(qtw.QStyledItemDelegate):

    def createEditor(self, parent, option, proxyModelIndex):
        date_inp = qtw.QDateEdit(parent, calendarPopup=True)
        return date_inp


class ImageDelegate(qtw.QStyledItemDelegate): 

    def createEditor(self, parent, option, proxyModelIndex):

        self.lbText = qtw.QLabel(parent)
        self.lbText.setAlignment(qtc.Qt.AlignCenter)
        self.printFileLoc = qtw.QFileDialog.getOpenFileName(parent,  caption = 'Open Print', filter = '*.jpg')
        self.lbPixmap = qtg.QPixmap(self.printFileLoc[0]) #[0] brings back path to image
        self.lbText.setPixmap(self.lbPixmap.scaled(70,100, qtc.Qt.KeepAspectRatio))

        return self.lbText


    def setModelData(self, editor, model, index):

        self.plants_model = qts.QSqlRelationalTableModel()
        self.plants_model.setTable('plant_list')
        self.plants_model.setData(index, self.lbText, qtc.Qt.EditRole)


class MainWindow(qtw.QMainWindow):

    def __init__(self):
        super().__init__()

        self.gridLayout = qtw.QGridLayout()
        self.mainW = qtw.QWidget()
        self.mainW.setLayout(self.gridLayout) 
        self.setCentralWidget(self.mainW)

        # Connect to the database
        db = qts.QSqlDatabase.addDatabase('QSQLITE')
        db.setDatabaseName('plants.db')
        if not db.open():
            qtw.QMessageBox.critical(
                None, 'DB Connection Error',
                'Could not open database file: '
                f'{db.lastError().text()}')
            sys.exit(1)


        #CREATE MODELS FOR EACH SQL TABLE
        self.zone_model = qts.QSqlTableModel()
        self.zone_model.setTable('zones') 

        self.loc_model = qts.QSqlTableModel()
        self.loc_model.setTable('loc_rec') 

        self.indoor_seed_model = qts.QSqlTableModel()
        self.indoor_seed_model.setTable('indoor_seed')

        self.soil_rec_model = qts.QSqlTableModel()
        self.soil_rec_model.setTable('soil_rec') 

        self.plant_type_model = qts.QSqlTableModel()
        self.plant_type_model.setTable('plant_type')

        self.nick_name_model = qts.QSqlTableModel()
        self.plant_type_model.setTable('nick_name')    

        self.plants_model = qts.QSqlRelationalTableModel()
        self.plants_model.setTable('plant_list')

        self.plants_model.setRelation(
            self.plants_model.fieldIndex('nickname_id'),
            qts.QSqlRelation('nick_name', 'id', 'veggies')
        )

        self.plants_model.setRelation(
            self.plants_model.fieldIndex('ans_id'),
            qts.QSqlRelation('indoor_seed', 'id', 'ans')
        )
        self.plants_model.setRelation(
            self.plants_model.fieldIndex('zone_id'),
            qts.QSqlRelation('zones', 'id', 'code')
        )
        self.plants_model.setRelation(
            self.plants_model.fieldIndex('soil_id'),
            qts.QSqlRelation('soil_rec', 'id', 'soil_type')
        )
        self.plants_model.setRelation(
            self.plants_model.fieldIndex('p_type_id'),
            qts.QSqlRelation('plant_type', 'id', 'p_type')
        )
        self.plants_model.setRelation(
            self.plants_model.fieldIndex('location_id'),
            qts.QSqlRelation('loc_rec', 'id', 'loc')
        )

        self.UIComps() # call the UI components method

    def UIComps(self):
        # set headers for main table
        fieldnames = ['ID', "Year Planted", "Real Name", "Nick Name", "Description",
        "Seed Plant Rec","Garden Plant Rec", "Plant Notes", "Comments",
        "Days to Germ", "Days to Harv","Reco Spring Frost","Actual Spring Frost",  "Seed Plant Rec", "Garden Plant Rec",
        "Actual Seed Plant", "Actual Garden Plant", "Harvest Date Plan", "Actual Harvest Date",
        "Photo", "Location", "Zone", "Seed Indoor?", "Soil Type", "Plant Type" ]

        c = 0
        for f in fieldnames:
            self.plants_model.setHeaderData(c, qtc.Qt.Horizontal, (fieldnames[c]))
            c += 1

        self.plants_model.setEditStrategy(qts.QSqlTableModel.OnFieldChange)
        self.plants_model.dataChanged.connect(print)

        lbl2 = qtw.QLabel("View/Edit Plants", self)   
        lbl2.setFont(qtg.QFont("Helvetica", 25, 12)) 
        self.gridLayout.layout().addWidget(lbl2, 6, 0,1,3, alignment=qtc.Qt.AlignCenter)

        #PLANT LIST TABLE
        self.plant_list = qtw.QTableView()

        self.plant_list.setModel(self.plants_model)
        self.gridLayout.layout().addWidget(self.plant_list, 7, 0, 2, 3)
        self.plant_list.horizontalHeader().setSectionsClickable(True)
        self.plant_list.horizontalHeader().setSortIndicatorShown(True)
        self.plant_list.setSortingEnabled(True) # this makes table sortable

        self.dateDelegate = DateDelegate()
        self.plant_list.setItemDelegateForColumn(
            self.plants_model.fieldIndex('seed_plant_date_reco'),
            self.dateDelegate)

        self.dateDelegate2 = DateDelegate()
        self.plant_list.setItemDelegateForColumn(
            self.plants_model.fieldIndex('garden_plant_date_reco'),
            self.dateDelegate2) 

        self.dateDelegate3 = DateDelegate()
        self.plant_list.setItemDelegateForColumn(
            self.plants_model.fieldIndex('seed_plant_date_ac'),
            self.dateDelegate3) 

        self.dateDelegate4 = DateDelegate()
        self.plant_list.setItemDelegateForColumn(
            self.plants_model.fieldIndex('garden_plant_date_ac'),
            self.dateDelegate4) 

        self.dateDelegate5 = DateDelegate()
        self.plant_list.setItemDelegateForColumn(
            self.plants_model.fieldIndex('harvest_date_plan'),
            self.dateDelegate5) 

        self.dateDelegate6 = DateDelegate()
        self.plant_list.setItemDelegateForColumn(
            self.plants_model.fieldIndex('harvest_date_ac'),
            self.dateDelegate6) 

        self.dateDelegate7 = DateDelegate()
        self.plant_list.setItemDelegateForColumn(
            self.plants_model.fieldIndex('spring_frost_reco'),
            self.dateDelegate7) 

        self.dateDelegate8 = DateDelegate()
        self.plant_list.setItemDelegateForColumn(
            self.plants_model.fieldIndex('spring_frost_ac'),
            self.dateDelegate8)  

        #IMAGE INPUT
        self.imageDelegate = ImageDelegate()
        self.plant_list.setItemDelegateForColumn(
            self.plants_model.fieldIndex('photo'),
            self.imageDelegate) 

        self.plants_model.setEditStrategy(qts.QSqlTableModel.OnFieldChange)
        self.plants_model.dataChanged.connect(print)                                  

        self.plants_model.select() 

        self.plant_list.setItemDelegate(qts.QSqlRelationalDelegate())

        #adding toolbars
        self.toolbar = self.addToolBar('Controls')
        deleteCoffee = qtw.QAction(qtg.QIcon("close.png"), "Delete Record", self)
        deleteCoffee.triggered.connect(self.delete_plant) #removes from table
        self.toolbar.addAction(deleteCoffee )

        addPlant = qtw.QAction(qtg.QIcon("add.png"), "Add A Plant", self)
        addPlant.triggered.connect(self.add_plant)
        self.toolbar.addAction(addPlant)


    # SLOTS for Toolbar buttons
    def delete_plant(self):
        selected = self.plant_list.selectedIndexes()
        for index in selected or []:
            self.plants_model.removeRow(index.row())  
        self.plants_model.select()
        self.countRecords()

    def add_plant(self):
        self.gridLayout.layout().addWidget(self.plant_list, 7, 0, 2, 3)
        self.plants_model.insertRows(0, 1) 
        self.countRecords()#calls the countRecords() function


app = qtw.QApplication(sys.argv)
app.setStyle("fusion")
mw = MainWindow()
mw.setGeometry(10, 10, 1000, 750)
mw.show()
sys.exit(app.exec())

И БД

CREATE TABLE zones (
    id INTEGER PRIMARY KEY,
    code TEXT NOT NULL UNIQUE
    )
    ;

CREATE TABLE loc_rec (
    id INTEGER PRIMARY KEY,
    loc TEXT NOT NULL UNIQUE
    )
    ;   

CREATE TABLE indoor_seed (
    id INTEGER PRIMARY KEY,
    ans TEXT 
    )
    ;

CREATE TABLE soil_rec (
    id INTEGER PRIMARY KEY,
    soil_type TEXT  
    )
    ;  

CREATE TABLE plant_type (
    id INTEGER PRIMARY KEY,
    p_type TEXT  
    )
    ;  

CREATE TABLE nick_name (
    id INTEGER PRIMARY KEY,
    veggies TEXT NOT NULL 
    )
    ;  

INSERT INTO nick_name(veggies) VALUES
    ('Artichoke'),
    ('Asparagus'),
    ('Bean Sprouts'),
    ('Brocoli'),
    ('Brussels sprouts'),
    ('Cabbage'),
    ('Cauliflower'),
    ('Celery'),
    ('Greens-Bok Choy'),
    ('Greens-Chard'),
    ('Greens-Dandelion'),
    ('Greens-Kale'),
    ('Greens-Spinach'),
    ('Herbs-Basil'),
    ('Herbs-Chamomile'),
    ('Herbs-Lavender'),
    ('Herbs-Oregano'),
    ('Herbs-Parsley'),
    ('Herbs-Rosemary'),
    ('Herbs-Sage'),
    ('Herbs-Thyme'),
    ('Lettuce-Iceberg'),
    ('Lettuce-Romaine'),
    ('Mushrooms'),
    ('Onions-Chives'),
    ('Onions-Leeks'),
    ('Onions-Onion'),
    ('Onions-Shallots'),
    ('Onions-Scallions'),
    ('Peas'),
    ('Peppers-Bell'),
    ('Peppers-Chili'),
    ('Peppers-Jalapeno'),
    ('Peppers-Habanero'),
    ('Peppers-Paprika'),
    ('Peppers-Tabasco'),
    ('Peppers-Cayenne'),
    ('Radicchio'),
    ('Root Vegatables-Beets'),
    ('Root Vegatables-Beetroot'),
    ('Root Vegatables-Carrot'),
    ('Root Vegatables-Ginger'),
    ('Root Vegatables-Parsnip'),
    ('Root Vegatables-Potato'),
    ('Root Vegatables-Rutabaga'),
    ('Root Vegatables-Radish'),
    ('Root Vegatables-Sweet Potato'),
    ('Root Vegatables-Turnip'),
    ('Sweetcorn'),
    ('Squashes-Acorn'),
    ('Squashes-Butternut'),
    ('Squashes-Banana'),
    ('Squashes-Cucumber'),
    ('Squashes-Pumpkin'),
    ('Squashes-Spaghetti'),
    ('Squashes-Zucchini'),
    ('Stevia'),
    ('Tomato'),
    ('Watercress'),
    ('Waxed Beans')
    ;      

INSERT INTO zones(code) VALUES
    ('1a'), ('1b'),
    ('2a'), ('2b'),
    ('3a'), ('3b'),
    ('4a'), ('4b'),
    ('5a'), ('5b'),
    ('6a'), ('6b'),
    ('7a'), ('7b'),
    ('8a'), ('8b'),
    ('9a'), ('9b'),
    ('10a'), ('10b'),
    ('11a'), ('11b'),
    ('12a'), ('12b'),
    ('13a'), ('13b') 
;                   

INSERT INTO loc_rec(loc) VALUES
    ('Walipini'),
    ('Garden'),
    ('Barrel'),
    ('Deck'),
    ('Office'),
    ('Kitchen')   
    ;

INSERT INTO indoor_seed(ans) VALUES
    ('Yes'),
    ('No') 
    ;

INSERT INTO soil_rec(soil_type ) VALUES
    ('Very Wet'),
    ('Wet'),
    ('Dry'),
    ('Very Dry')
    ;

INSERT INTO plant_type(p_type ) VALUES
    ('Indetermined'),
    ('Semi-Determined'),
    ('Determined')
    ;    


CREATE TABLE plant_list(
    id INTEGER PRIMARY KEY,
    plant_year INTEGER NOT NULL,
    real_name TEXT NOT NULL,
    nickname_id INTEGER REFERENCES nick_name(id) ON UPDATE CASCADE,
    fruit_desc TEXT ,
    seed_plant_rec TEXT,
    gard_plant_rec TEXT,
    plant_notes TEXT,
    comments TEXT,
    germ_days INTEGER,
    harv_days INTEGER,
    spring_frost_reco DATE DEFAULT CURRENT_DATE,
    spring_frost_ac DATE DEFAULT CURRENT_DATE,
    seed_plant_date_reco DATE DEFAULT CURRENT_DATE,
    garden_plant_date_reco DATE DEFAULT CURRENT_DATE,
    seed_plant_date_ac DATE DEFAULT CURRENT_DATE,
    garden_plant_date_ac DATE DEFAULT CURRENT_DATE,
    harvest_date_plan DATE DEFAULT CURRENT_DATE,
    harvest_date_ac DATE DEFAULT CURRENT_DATE,
    photo BLOB,
    location_id INTEGER REFERENCES location_rec(id) ON UPDATE CASCADE,
    zone_id INTEGER REFERENCES zones(id) ON UPDATE CASCADE,
    ans_id INTEGER REFERENCES indoor_seed (id) ON UPDATE CASCADE,
    soil_id INTEGER REFERENCES soil_rec (id) ON UPDATE CASCADE,
    p_type_id INTEGER REFERENCES plant_type (id) ON UPDATE CASCADE
    )
    ;

1 Ответ

0 голосов
/ 19 апреля 2020

Логика c заключается в том, что делегат показывает, что хранится в ролях, поэтому в этом случае вы должны сохранить информацию о файле (изображении) в роли, а затем использовать эту информацию, чтобы отобразить ее в виде центрированного значка. :

class ImageDelegate(qtw.QStyledItemDelegate):
    def createEditor(self, parent, option, index):
        filename, _ = qtw.QFileDialog.getOpenFileName(
            parent, caption="Open Print", filter="Image Files (*.png *.jpg *.bmp)"
        )
        if filename:
            model = index.model()
            file = qtc.QFile(filename)
            if file.open(qtc.QIODevice.ReadOnly):
                model.setData(index, file.readAll(), qtc.Qt.EditRole)

    def initStyleOption(self, option, index):
        super().initStyleOption(option, index)
        pixmap = qtg.QPixmap()
        if pixmap.loadFromData(index.data(qtc.Qt.EditRole)):
            option.features &= ~qtw.QStyleOptionViewItem.HasDisplay
            option.text = ""
            option.features |= qtw.QStyleOptionViewItem.HasDecoration
            option.icon = qtg.QIcon(pixmap)
            option.decorationSize = pixmap.size() / pixmap.devicePixelRatio()
            option.decorationAlignment = qtc.Qt.AlignCenter
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...