I have database include BLOB Column named (IMG)
What I need that when search by code, the item image displayed , but the result always be like that
(caV\xd6\xf7\xd0\xec]c\x1b\x95\xe2\xa4\x00\xe3\xd3\x82L\xc9L\xa2W8H\xaf\xe4\xe0\x9f\xcb\x7f\xb5\xbautm]\x94\'\xb6\xb7p\xa7{\xbffU\xb7Q\xd5\x8d\xe3\xe1\xb....etc)
import io
import base64
from PyQt5 import QtGui
from ui import Ui_MainWindow
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
import ast
import sqlite3
import sys
class HmcProject ( QMainWindow, Ui_MainWindow ): # ,FORM_CLASS
def __init__(self):
QMainWindow.__init__ ( self )
super ( HmcProject, self ).__init__ ()
self.setupUi ( self )
self.Handle_Buttons ()
self.Db_Connect ()
self.Image_Retrive()
def Db_Connect(self):
self.connection = sqlite3.connect ( 'deals_db.db' )
cursor = self.connection.cursor ()
def Handle_Buttons(self):
self.pushButton.clicked.connect(self.Image_Retrive)
def Image_Retrive(self):
try:
cursor = self.connection.cursor ()
itemsearch = self.lineEdit_Item_NameS_3.text ()
sql = ('''
SELECT IMG FROM deals_data
WHERE ITEM_CODE= ?
''')
cursor.execute ( sql,[(itemsearch)])
data = cursor.fetchone ()
print ( data [0])
pix= QPixmap.loadFromData(data[0])
self.label.setPixmap(pix)
except:
pass
def main():
app = QApplication ( sys.argv )
window = HmcProject ()
window.show ()
app.exec_ ()
if __name__ == '__main__':
main ()
You're trying to load the pixmap using loadFromData() as a static function, but it's not.
Also, that function returns a bool, reporting if the loading has been successful.
You have to create a new QPixmap instance first, then load the data, and finally show it in the label if it has been loaded:
pix = QPixmap()
if pix.loadFromData(data[0]):
self.label.setPixmap(pix)
PS: avoid space characters around parentheses, they are unnecessary and distracting; also, don't confuse and mix calls on the base classes, in python3 it's enough to call super().__init__() just once,
even for multiple inheritance classes
Related
Hello I am trying to create a PyQt6 widget that animates over a set of images, but at a precise frame rate that varies as a function of realtime parameters. I insert QPixmaps into the cache within a for loop, and am able to find the QPixmap objects through QPixmap.find() within the same for loop, but outside the loop .find() returns None.
Below is the script. I can include the image series if needed. Appreciate any help.
import sys
from PyQt6.QtWidgets import (
QApplication,
QMainWindow,
QLabel
)
from PyQt6.QtCore import Qt
from PyQt6.QtGui import QPixmap, QPixmapCache
from pathlib import Path
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.animating_label = QLabel('animation here')
self.animating_label.setAlignment(Qt.AlignmentFlag.AlignHCenter | Qt.AlignmentFlag.AlignVCenter)
self.animating_label.pixmap().size().setWidth(200)
self.animating_label.pixmap().size().setHeight(200)
self.setCentralWidget(self.animating_label)
parent_path = Path(__file__).parent
self.images_path = parent_path / 'images/animation_set/'
self.animating_label.setPixmap(QPixmap(self.images_path.__str__() + "/clock01.png"))
self.pixmapcache_keys: [str] = []
self.load_images()
test = QPixmapCache.find("clock02")
try:
self.animating_label.setPixmap(test)
except:
if test == None:
print("Failure: QPixMapCache.find() returned", test)
def load_images(self):
image_suffixes = ['.jpg', '.png', '.gif', '.bmp']
imgs_found_count = 0
for filepath in self.images_path.iterdir():
if filepath.suffix in image_suffixes:
imgs_found_count += 1
cache_key = filepath.stem
self.pixmapcache_keys.append(cache_key)
if not QPixmapCache.find(cache_key):
pixmap = QPixmap(filepath.__str__())
QPixmapCache.insert(cache_key, pixmap)
print("pixmap %s" % cache_key, QPixmapCache.find(cache_key))
print(imgs_found_count, "image(s) found in animation_set directory.", len(self.pixmapcache_keys),
"keys loaded into QPixmapCache")
app = QApplication(sys.argv)
window = MainWindow()
window.show()
# start Qt event loop
app.exec()
print("Script complete.")
sys.exit(1)
Here is the output:
pixmap clock04 <PyQt6.QtGui.QPixmap object at 0x101c84b30>
pixmap clock10 <PyQt6.QtGui.QPixmap object at 0x101c84970>
pixmap clock11 <PyQt6.QtGui.QPixmap object at 0x101c84b30>
pixmap clock05 <PyQt6.QtGui.QPixmap object at 0x101c84970>
...
24 image(s) found in animation_set directory. 24 keys loaded into QPixmapCache
Failure: QPixMapCache.find() returned None
Script complete.
I was able to get the animation working using a list of QPixmaps instead of QPixmapCache, but I am not sure if this is the optimal approach.
Generating Qpixmap list from files:
for filepath in sorted(self.images_path.iterdir()):
if filepath.suffix in image_suffixes:
qpixmap = QPixmap(filepath.__str__())
self.pixmaps.append(qpixmap)
called elsewhere on a timer
def advance(self):
if self.pixmap_current_index >= len(self.pixmaps) - 1:
self.pixmap_current_index = 0
else:
self.pixmap_current_index += 1
self.animating_label.setPixmap(self.pixmaps[self.pixmap_current_index])
self.timer.start(self.refresh_interval)
I have a simple form where I have a function/method which calls a QFileDialog to choose a file. This form stores the information in a Postgresql database and uses QDataWidgetMapper to map the form fields to database fields. When I add a new row to the model and edit some fields, when I call the QFileDialog, it seems the mappings get removed. All the edited fields on the form go blank. If I go back to a record which was retrieved from the database, I have no problems adding the image as the data persists on the form.
It seems to be related to the submit = self.c_mapper.submit() line of code. When I comment this out, the data persists in the form but I also can’t get the query().LastInsertId().
When stepping through the code, the form field data disappears when if dlg.exec_() == QDialog.Accepted: line is reached.
The desired behaviour is to be able to call the function which selects the image file and continue editing the same record with the correct data in the fields.
See the animation:
See the code:
import sys
import os
from pathlib import Path
import shutil
#PyQt stuff
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtSql import *
from PyQt5.QtWidgets import *
#form modules
from form import *
class Contact(QMainWindow):
def __init__(self, cont_id, parent=None):
QMainWindow.__init__(self)
self.cont_id = cont_id
self.ui = Ui_contact_form()
self.ui.setupUi(self)
self.c_model = QSqlTableModel(self)
self.c_model.setTable("contacts")
self.c_model.select()
self.row = self.c_model.rowCount()
self.c_model.insertRow(self.row)
self.setWindowTitle('New contact')
self.c_mapper = QDataWidgetMapper(self)
self.c_mapper.setSubmitPolicy(QDataWidgetMapper.ManualSubmit)
self.c_mapper.setModel(self.c_model)
#self.c_mapper.setItemDelegate(QSqlRelationalDelegate(self))
self.c_mapper.addMapping(self.ui.title, self.c_model.fieldIndex("title"))
self.c_mapper.addMapping(self.ui.first_name, self.c_model.fieldIndex("first_name"))
self.c_mapper.addMapping(self.ui.last_name, self.c_model.fieldIndex("last_name"))
self.c_mapper.addMapping(self.ui.nickname, self.c_model.fieldIndex("nickname"))
self.c_mapper.addMapping(self.ui.job_title, self.c_model.fieldIndex("job_title"))
self.c_mapper.addMapping(self.ui.birth_date, self.c_model.fieldIndex("birth_date"))
self.c_mapper.addMapping(self.ui.website, self.c_model.fieldIndex("website"))
self.c_mapper.addMapping(self.ui.comments, self.c_model.fieldIndex("comments"))
self.c_mapper.addMapping(self.ui.users, self.c_model.fieldIndex("user_name"))
self.c_mapper.addMapping(self.ui.tags, self.c_model.fieldIndex("tags"))
self.c_mapper.setCurrentIndex(self.row)
self.ui.get_image_file.clicked.connect(self.get_profile_image)
def get_profile_image(self):
submit = self.c_mapper.submit()
self.cont_id = self.c_model.query().lastInsertId()
data_loc = Path('/home/dave/hd/Nextcloud/crm_data/')
database = 'crm'
dlg = QFileDialog(self)
dlg.setFileMode(QFileDialog.AnyFile)
home = os.path.expanduser('~') + "/Downloads"
dlg.setDirectory(home)
if dlg.exec_() == QDialog.Accepted:
selected_file = dlg.selectedFiles()[0]
else:
return
selected_file = Path(selected_file)
ext = selected_file.suffix
ext = ext.lower()
target_loc = data_loc / database / "contacts/images"
target_file = str(self.cont_id) + ext
target_dest = target_loc / target_file
shutil.move(str(selected_file), str(target_dest))
self.ui.image.setPixmap(QPixmap(str(target_dest)).scaled(self.ui.image.size(),Qt.KeepAspectRatio))
if __name__=="__main__":
app=QApplication(sys.argv)
db = QSqlDatabase.addDatabase("QPSQL");
db.setHostName('hostname')
db.setDatabaseName('crm')
db.setUserName('usr')
db.setPassword('pw')
if (db.open()==False):
QMessageBox.critical(None, "Database Error", db.lastError().text())
myapp = Contact('')
myapp.show()
sys.exit(app.exec_())
Please be kind. This is my first question. I have included a minimum listing that illustrates the problem.
from PyQt5 import QtWidgets, QtCore, QtGui, uic, QtSql
from PyQt5.QtCore import Qt
qtCreatorFile = "QuotesGui.ui"
Ui_MainWindow, QtBaseClass = uic.loadUiType(qtCreatorFile)
class QuotesUI(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self, model):
QtWidgets.QMainWindow.__init__(self)
uic.loadUi(qtCreatorFile,self)
self.setupUi(self)
self.model = model # View owns the model
self.tableView.setModel(self.model._formModel)
self.setWidgetMapping() # Map model to view widgets
authorSRD = QtSql.QSqlRelationalDelegate(self.authorComboBox)
self.authorComboBox.setModel(self.model._authorModel)
self.authorComboBox.setItemDelegate(authorSRD)
self.authorComboBox.setModelColumn(
self.model._formModel.fieldIndex("authorName"))
citationSRD = QtSql.QSqlRelationalDelegate(self.citationComboBox)
self.citationComboBox.setModel(self.model._citationModel)
self.citationComboBox.setItemDelegate(citationSRD)
self.citationComboBox.setModelColumn(
self.model._formModel.fieldIndex("citationText"))
self.mainMapper.toFirst()
self._updateButtons(0) # To disable the previous button at start up
self.saveBtn.setEnabled(False) # Since we can't edit, we can't save
self._connectSignals(self.model)
def setWidgetMapping(self):
self.mainMapper = QtWidgets.QDataWidgetMapper(self)
self.mainMapper.setModel(self.model._formModel)
self.mainMapper.setItemDelegate(QtSql.QSqlRelationalDelegate(self))
self.mainMapper.addMapping(self.authorComboBox,
self.model._formModel.fieldIndex("authorName"))
self.mainMapper.addMapping(self.citationComboBox,
self.model._formModel.fieldIndex("citationText"))
self.mainMapper.addMapping(self.quoteText,
self.model._formModel.fieldIndex("quoteText"))
def _connectSignals(self, model):
self.lastBtn.clicked.connect(self.mainMapper.toLast)
self.nextBtn.clicked.connect(self.mainMapper.toNext)
self.prevBtn.clicked.connect(self.mainMapper.toPrevious)
self.firstBtn.clicked.connect(self.mainMapper.toFirst)
self.mainMapper.currentIndexChanged.connect(
self._updateButtons)
def _updateButtons(self, row):
self.firstBtn.setEnabled(row > 0)
self.prevBtn.setEnabled(row > 0)
self.nextBtn.setEnabled(row < self.model._formModel.rowCount() - 1)
self.lastBtn.setEnabled(row < self.model._formModel.rowCount() - 1)
class QuoteModel():
def __init__(self, data):
# Make a database connection
self.db = self.createConnection(data)
# set models
self._setFormModel()
self._setAuthorComboTableLink()
self._setCitationComboTableLink()
# Connect signals
self._connectSignals()
# Define a model for the form
def _setFormModel(self):
self._formModel = QtSql.QSqlRelationalTableModel(
parent = None, db = self.db)
self._formModel.setEditStrategy(
QtSql.QSqlTableModel.OnManualSubmit)
self._formModel.setTable("Quote")
authorIdx = self._formModel.fieldIndex("authorId")
citationIdx = self._formModel.fieldIndex("citationId")
self._formModel.setJoinMode(1) # Left Join
self._formModel.setRelation(authorIdx, QtSql.QSqlRelation(
"Author", "authorId", "authorName"))
self._formModel.setRelation(citationIdx, QtSql.QSqlRelation(
"Citation", "citationId", "citationText"))
self._formModel.select()
# Define models and link tables for the two comboboxes
def _setAuthorComboTableLink(self):
self._authorModel = QtSql.QSqlTableModel(
parent = None, db = self.db)
self._authorModel.setTable("Author")
self._authorModel.setEditStrategy(
QtSql.QSqlTableModel.OnManualSubmit)
self._authorModel.select()
self._authorModel.sort(1,Qt.AscendingOrder)
def _setCitationComboTableLink(self):
self._citationModel = QtSql.QSqlTableModel(
parent = None, db = self.db)
self._citationModel.setTable("Citation")
self._citationModel.setEditStrategy(
QtSql.QSqlTableModel.OnManualSubmit)
self._citationModel.select()
self._citationModel.sort(1,Qt.AscendingOrder)
def _newData(self):
print('in _newData')
def _connectSignals(self):
self._authorModel.rowsInserted.connect(self._newData)
#######################################################
# A function to connect to a named database
def createConnection(self,dbfile):
db = QtSql.QSqlDatabase.addDatabase('QSQLITE')
db.setDatabaseName(dbfile)
db.open()
if not db.open():
QtWidgets.QMessageBox.critical(
None, QtWidgets.qApp.tr("Cannot open database"),
QtWidgets.qApp.tr("Unable to establish a database connection.\n"),
QtWidgets.QMessageBox.Cancel,
)
return False
return db
dbFile = "Quotations.db"
if __name__=='__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
m = QuoteModel(dbFile)
w = QuotesUI(m)
w.show()
sys.exit(app.exec_())
Still requires the upload of a 8kb .ui file and a 70kb sample database to run. So far I haven't been able to figure out how to do that....
When this is run, incorporating the rest of the necessary code, the author combobox works as expected, i.e.: the dropdown shows all the values in the author table and when I step the the records in the model, the correct author is displayed in the combobox.
The citation combobox does NOT function. As written here it neither shows values from the citation table, nor is it connected to the quotes table. Basically it shows nothing.
I think I need, somehow, a second delegate on the model. But I don't know how.
Any ideas how to get this functioning??
To make this work I had to change:
self.authorComboBox.setModel(self.model._authorModel)
to:
authorRel = self.model._formModel.relationModel(self.model.authorIdx)
self.authorComboBox.setModel(authorRel)
The QSqlRelationalTableModel has a virtual function "relationModel" that returns a QSqlTableModel. When you use this model as the model for the QComboBox, everything works.
I have two python files, the first one is to handle database related stuff and the second one imports that file so I can use it with PyQt.
The problem is if I want to change the label in the first file it doesn't work the application just crashes.
The reason I want the first file to be able to change the label is if an error occurs when trying to connect to the DB.
Here is a short view of my code:
First file.
from mysql.connector import (connection)
from datetime import *
from RPI1_ui import Ui_Form
'''Handling of database related stuff'''
class DatabaseUtility(Ui_Form):
def __init__(self):
#DB Connection
self.cnx = None
self.cursor = None
def mysql_connect(self):
# Database connection
try:
self.cnx = connection.MySQLConnection(user='root', password='', host='127.0.0.1', database='spicadb')
self.cursor = self.cnx.cursor()
except connection.errors.InterfaceError as e:
self.lblShowInfo.setText(str(e)) # -> Try to change label
def get_table(self):
return self.run_command("SELECT * FROM tblseal")
def get_columns(self):
return self.run_command("SHOW COLUMNS FROM tblseal")
Second file.
from PyQt5.QtWidgets import QApplication, QWidget, QDialog
from datetime import *
from bs4 import BeautifulSoup as bs
import os
import sys
import DatabaseHandling
'''Convert UI file to Python'''
os.chdir("C:\\Users\Gianni Declercq\AppData\Local\Programs\Python\Python36-32\Scripts")
os.system("pyuic5.exe H:\QtProjects\\RPI1.ui -o H:\QtProjects\\RPI1_ui.py")
from RPI1_ui import Ui_Form # import after recreation of py file
from RPI1_Sec import SecondWindow
'''Main program'''
class MainWindow(QWidget, Ui_Form):
def __init__(self):
super(MainWindow, self).__init__()
# Initialize variables
self.dbu = DatabaseHandling.DatabaseUtility()
self.spica_reference = None
self.barcode = None
self.msl = None
self.package_body = None
self.window2 = None
# Get UI elements + resize window
self.setupUi(self)
self.resize(800, 480)
# Define what should happen on button click
self.btnQuit.clicked.connect(lambda: app.exit())
self.btnInsert.clicked.connect(lambda: self.get_entry())
self.btnTable.clicked.connect(lambda: self.new_window())
# Style buttons
self.btnQuit.setStyleSheet("background-color: red")
self.btnInsert.setStyleSheet("background-color: green")
self.btnTable.setStyleSheet("background-color: orange")
def get_entry(self):
try:
self.spica_reference = self.txtReferentie.text()
self.barcode = self.txtBarcode.text()
self.msl = self.txtMsl.text()
self.package_body = float(self.txtBodyPackage.text())
except ValueError:
self.lblShowInfo.setText("Please insert the correct values")
self.lblShowInfo.setStyleSheet('color: red')
else:
self.dbu.mysql_connect()
if self.dbu.cursor and self.dbu.cnx is not None:
self.dbu.add_entry(self.spica_reference, self.barcode, self.msl, self.package_body, self.calc_floor_life)
Give a "hook function" to the DatabaseUtility when initializing.
class MainWindow(QWidget, Ui_Form):
def __init__():
def ch_lab(text):
self.lblShowInfo.setText(text)
self.dbu = DatabaseHandling.DatabaseUtility(ch_lab)
class DatabaseUtility(Ui_Form):
def __init__(cb):
self.error_warn = cb
#.. error happening
self.error_warn('error')
I want the following code to get the request url starting with http://down.51en.com:88 during the web loading process , and then do other processing with the response object of the url .
In my program, once targetUrl is assigned a value , I want the function targetUrlGetter(url) to return it to the caller, however , the problem is that QApplication::exec() enters the main event loop so cannot execute code at the end of thetargetUrlGetter() function after the exec() call , thus the function cannot return , I have tried with qApp.quit() in interceptRequest(self, info) in order to tell the application to exit so that targetUrlGetter(url) can return , but the function still cannot return and the program even crashes on exit(tested on Win7 32bit), so how can I return the targetUrl to the caller program ?
The difficulties here are how to exit the Qt event loop without crash and return the request url to the caller.
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtWebEngineWidgets import *
from PyQt5.QtWebEngineCore import *
from PyQt5.QtCore import *
class WebEngineUrlRequestInterceptor(QWebEngineUrlRequestInterceptor):
def __init__(self, parent=None):
super().__init__(parent)
self.page = parent
def interceptRequest(self, info):
if info.requestUrl().toString().startswith('http://down.51en.com:88'):
self.targetUrl = info.requestUrl().toString()
print('----------------------------------------------', self.targetUrl)
qApp.quit()
# self.page.load(QUrl(''))
def targetUrlGetter(url=None):
app = QApplication(sys.argv)
page = QWebEnginePage()
globalSettings = page.settings().globalSettings()
globalSettings.setAttribute(
QWebEngineSettings.PluginsEnabled, True)
globalSettings.setAttribute(
QWebEngineSettings.AutoLoadImages, False)
profile = page.profile()
webEngineUrlRequestInterceptor = WebEngineUrlRequestInterceptor(page)
profile.setRequestInterceptor(webEngineUrlRequestInterceptor)
page.load(QUrl(url))
# view = QWebEngineView()
# view.setPage(page)
# view.show()
app.exec_()
return webEngineUrlRequestInterceptor.targetUrl
url = "http://www.51en.com/news/sci/everything-there-is-20160513.html"
# url = "http://www.51en.com/news/sci/obese-dad-s-sperm-may-influence-offsprin.html"
# url = "http://www.51en.com/news/sci/mars-surface-glass-could-hold-ancient-fo.html"
targetUrl = targetUrlGetter(url)
print(targetUrl)
You should always initialize QApplication at the beginning of the program, and always call the QApplication::exec function at the end of the program.
Another thing is that QWebEngineUrlRequestInterceptor.interceptRequest is a callback function which is called asynchronously. Since info.requestUrl().toString() is called inside the callback function, there is no way to return the result it synchronously.
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtWebEngineWidgets import *
from PyQt5.QtWebEngineCore import *
from PyQt5.QtCore import *
class WebEngineUrlRequestInterceptor(QWebEngineUrlRequestInterceptor):
def __init__(self, parent=None):
super().__init__(parent)
self.page = parent
def interceptRequest(self, info):
if info.requestUrl().toString().startswith('http://down.51en.com:88'):
self.targetUrl = info.requestUrl().toString()
print('----------------------------------------------', self.targetUrl)
# Don't do thatDo you really want to exit the whole program?
# qApp.quit()
# Do something here, rather than return it.
# It must be run asynchronously
# self.page.load(QUrl(''))
def targetUrlGetter(url=None):
page = QWebEnginePage()
globalSettings = page.settings().globalSettings()
globalSettings.setAttribute(
QWebEngineSettings.PluginsEnabled, True)
globalSettings.setAttribute(
QWebEngineSettings.AutoLoadImages, False)
profile = page.profile()
webEngineUrlRequestInterceptor = WebEngineUrlRequestInterceptor(page)
profile.setRequestInterceptor(webEngineUrlRequestInterceptor)
page.load(QUrl(url))
# view = QWebEngineView()
# view.setPage(page)
# view.show()
# Don't return this. It cannot be called synchronously. It must be called asynchronously.
# return webEngineUrlRequestInterceptor.targetUrl
app = QApplication(sys.argv) # always initialize QApplication at the beginning of the program
url = "http://www.51en.com/news/sci/everything-there-is-20160513.html"
# url = "http://www.51en.com/news/sci/obese-dad-s-sperm-may-influence-offsprin.html"
# url = "http://www.51en.com/news/sci/mars-surface-glass-could-hold-ancient-fo.html"
targetUrl = targetUrlGetter(url)
print(targetUrl)
app.exec_() # always call the QApplication::exec at the end of the program