Copy Pillow Gif to windows Clipboard - python

I have created a gif using pillow from some images and I am trying to copy this gif stored as a BytesIO object to the clipboard to save onto a presentation as a gif image. code below; where imageList = [] is a list of image file names.
any method of copying a gif to the clipboard from python would be helpful?! thanks
def copyGif(self):
imageList = []
gif = BytesIO()
imageList[0].save(gif, format='GIF', save_all=True, append_images=imageList[1:], optimize=False, duration=1000,
loop=0)
win32clipboard.OpenClipboard()
win32clipboard.EmptyClipboard()
win32clipboard.SetClipboardData(win32clipboard.CF_DIB, gif.getvalue())
win32clipboard.CloseClipboard()

Try it:
import sys
from PyQt5.Qt import *
class MainWindow(QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.setGeometry(50, 50, 600, 600)
# Create a URL.
url1 = QUrl.fromLocalFile('Loader.gif')
url2 = QUrl.fromLocalFile('animated-dancing-image-0028.gif')
# Create MIME data with URL.
mime_data = QMimeData()
mime_data.setUrls([url1, url2])
self.labelList = [ i for i in range(len([url1, url2]))]
# Copy the MIME data to the clipboard.
clipboard = QApplication.clipboard()
clipboard.setMimeData(mime_data)
cm = clipboard.mimeData()
for i, m in enumerate(cm.urls()):
self.labelList[i] = QMovie(m.toLocalFile())
self.labelList[i].frameChanged.connect(self.repaint)
self.labelList[i].start()
def paintEvent(self, event):
currentFrame1 = self.labelList[0].currentPixmap()
currentFrame2 = self.labelList[1].currentPixmap()
frameRect2 = currentFrame2.rect()
frameRect2.moveCenter(self.rect().center())
if frameRect2.intersects(event.rect()):
painter = QPainter(self)
painter.drawPixmap(frameRect2.left(), frameRect2.top(), currentFrame2)
frameRect1 = currentFrame1.rect()
frameRect1.moveCenter(self.rect().center())
if frameRect1.intersects(event.rect()):
painter.drawPixmap(frameRect1.left(), frameRect1.top(), currentFrame1)
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = MainWindow()
ex.show()
QTimer.singleShot(10000, app.quit)
sys.exit(app.exec_())

Related

Save two or more images from a frame as a single Image to file

I am new to QT. I have a frame on which both A4Size and extra are. Each one of them is a Qlabel and I set images to them. Now, I want to save everything found on the frame (A4Size and extra) but I find no way that works through the research I've done (saving everything from the frame to file). Is there a way to save both images (or even more) on the frame as a single image?
class Picture(QMainWindow):
def __init__(self, parent=None):
QMainWindow.__init__(self)
self.ui = Ui_Picture()
self.ui.setupUi(self)
self.setFixedSize(1430, 1000)
def show_image(self):
if self.ui.A4_sheet.isChecked():
self.ui.A4Size.setPixmap("all.png")
self.ui.extra.setPixmap("new.png")
print("A4")
def download(self):
fname, filter = QFileDialog.getSaveFileName(self, 'Save Image')
self.ui.A4Size.pixmap().save(fname + ".png", "PNG", -1)
print("saved")
if __name__ == "__main__":
app = QApplication(sys.argv)
widget = QtWidgets.QStackedWidget()
home_screen = MainWindow()
picture_screen = Picture()
widget.show()
widget.addWidget(home_screen)
widget.addWidget(picture_screen)
sys.exit(app.exec_())
My code above only saves A4Size even though extra is right on it.
Thank You.
You need to draw the two pixmaps into one with QPainter and then save it.
I am a C++ programmer, but I will try to write Python code now, I hope it will work for you.
source1 = QPixmap("all.png")
source2 = QPixmap("new.png")
# we will put the pixmaps next to each other horizontally
width = source1.width() + source2.width()
height = max(source1.height(), source2.height())
pixmap = QPixmap(width, height)
painter = QPainter(pixmap)
painter.drawPixmap(0, 0, source1)
painter.drawPixmap(source1.width(), 0, source2)
pixmap.save(fname + ".png")

Changing QThread variable from a sub window

I am writing a WebCam Gui, which is supposed to take pictures and manipulate with WebCam parameters. After the video stream is activated on the main GUI window, an additional window can be opened to change the WebCamera parameters Screenshot 1, Screenshot 2.
I am using Qthread to stream on QLabel. Also, I was able to set the initial camera parameters on the camera properties' changing window. My problem is changing the Exposure parameter by using a slider on the sub-window and seeing results in real-time on the main window.
Please see the code.
import sys
from PyQt5.QtWidgets import *
from PyQt5 import uic
from PyQt5.QtCore import *
from PyQt5.QtGui import *
import cv2
class MainFrame(QMainWindow):
def __init__(self):
super(MainFrame, self).__init__()
# Loading UI
uic.loadUi("MainFrame.ui", self)
# Remove maximize button to prevent crushing
self.setWindowFlags(Qt.WindowCloseButtonHint | Qt.WindowMinimizeButtonHint)
# Define Widgets
self.Video_Feed = self.findChild(QLabel, 'Video_Feed')
self.Case_Name = self.findChild(QLineEdit, "Case_Name")
self.Pictures_List = self.findChild(QListWidget, "Pictures_List")
self.Start_Video = self.findChild(QAction, 'actionStart_Video')
self.Start_Video.setShortcut('Shift+S')
self.Stop_Video = self.findChild(QAction, 'actionStop_Video')
self.Stop_Video.setShortcut('Shift+F')
self.Take_a_Picture = self.findChild(QAction, 'actionTake_a_picture')
self.Take_a_Timed_Picture = self.findChild(QAction, 'actionTake_a_timed_picture')
self.Camera_Properties = self.findChild(QAction, 'actionProperties')
# Initializing Video
self.Start_Video.triggered.connect(self.Start_Video_Clicked)
self.Stop_Video.triggered.connect(self.Stop_Video_Clicked)
self.Camera_Properties.triggered.connect(self.Camera_Properties_Clicked)
def Video_Feed_Update(self, Image):
self.Video_Feed.setPixmap(QPixmap.fromImage(Image))
def Start_Video_Clicked(self):
self.Video_Feed_is_Running = True
self.thread = QThread()
self.Video_Thread = Worker()
self.Video_Thread.moveToThread(self.thread)
self.Video_Thread.ImageUpdate.connect(self.Video_Feed_Update)
self.thread.started.connect(self.Video_Thread.run)
self.thread.start()
def Stop_Video_Clicked(self):
self.Video_Thread.stop_video()
self.Video_Feed.setText("Your video starts here")
def Camera_Properties_Clicked(self):
self.CP = CameraParameters()
Initial_Exposure = self.Video_Thread.Camera_Initial_Parameters()
self.CP.Setup_Exposure(int(Initial_Exposure))
self.CP.Exposure_Calibration.connect(self.Video_Thread.Exposure_update)
self.CP.show()
class Worker(QObject):
ImageUpdate = pyqtSignal(QImage)
def run(self):
self.ThreadActive = True
self.Capture = cv2.VideoCapture(1, cv2.CAP_DSHOW)
self.Capture.set(3, 1920)
self.Capture.set(4, 1080)
while self.ThreadActive:
ret, frame = self.Capture.read()
if ret:
image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
# Converting Video into QT5 readable format
qt_video_format = QImage(image.data, image.shape[1], image.shape[0], QImage.Format_RGB888)
qt_picture = qt_video_format.scaled(1280, 720, Qt.KeepAspectRatio)
self.ImageUpdate.emit(qt_picture)
def stop_video(self):
self.ThreadActive = False
self.Capture.release()
def Camera_Initial_Parameters(self):
return self.Capture.get(cv2.CAP_PROP_EXPOSURE)
def Exposure_update(self, value):
self.Capture.set(cv2.CAP_PROP_EXPOSURE, value)
class CameraParameters(QDialog):
Exposure_Calibration = pyqtSignal(int)
def __init__(self):
super().__init__()
uic.loadUi('Cam_Parameters.ui', self)
# Sliders
self.Exposure_Slider = self.findChild(QSlider, 'ExposureSlider')
self.Exposure_Slider.setRange(-10, 10)
self.White_Balance_Slider = self.findChild(QSlider, 'WBSlider')
self.White_Balance_Slider.setMinimum(-10)
self.White_Balance_Slider.setMaximum(10)
self.Brightness_Slider = self.findChild(QSlider, 'BrightnessSlider')
self.Brightness_Slider.setMinimum(0)
self.Brightness_Slider.setMaximum(300)
self.Saturation_Slider = self.findChild(QSlider, 'SaturationSlider')
self.Saturation_Slider.setMinimum(0)
self.Saturation_Slider.setMaximum(300)
self.Contrast_Slider = self.findChild(QSlider, 'ContrastSlider')
self.Contrast_Slider.setMinimum(-10)
self.Contrast_Slider.setMaximum(10)
self.Gamma_Slider = self.findChild(QSlider, 'GammaSlider')
self.Gamma_Slider.setMinimum(-10)
self.Gamma_Slider.setMaximum(10)
self.Sharpness_Slider = self.findChild(QSlider, 'SharpnessSlider')
self.Sharpness_Slider.setMinimum(0)
self.Sharpness_Slider.setMaximum(100)
# Sliders values
self.Exposure_Value = self.findChild(QLabel, 'Exposure_Value')
self.White_Balance_Value = self.findChild(QLabel, 'WB_value')
self.Brightness_Value = self.findChild(QLabel, 'Brightness_value')
self.Saturation_Value = self.findChild(QLabel, 'Saturation_value')
self.Contrast_Value = self.findChild(QLabel, 'Contrast_value')
self.Gamma_Value = self.findChild(QLabel, 'Gamma_value')
self.Sharpness_Value = self.findChild(QLabel, 'Sharpness_value')
# Connections
self.Exposure_Slider.valueChanged.connect(self.Exposure_sliding)
def Setup_Exposure(self, value):
self.Exposure_Slider.setValue(value)
self.Exposure_Value.setText(str(value))
def Exposure_sliding(self, value):
self.Exposure_Value.setText(str(value))
self.Exposure_Calibration.emit(value)
if __name__ == "__main__":
App = QApplication(sys.argv)
Root = MainFrame()
Root.show()
sys.exit(App.exec())
Cam_Parameters.ui, MainFrame.ui for the GUI
I admit I don't know why this worked, but changing the connect to a lambda function did the trick.
self.CP.Exposure_Calibration.connect(lambda x: self.Video_Thread.Exposure_update(x))

QLabel not displaying in QWidget window

I have the below piece of code which gives the below picture.
import os
import numpy as np
from PyQt5 import QtCore, QtWidgets
import sqlite3
class Ui_Form():
def __init__(self):
#Checking if the loading database is in place
if not os.path.exists("loading_database.db"):
QtWidgets.QMessageBox.information(None,'Loading database missing','Loading database has not been found. Creation of a new one will be attempted')
self.loadingDatabaseCreator()
QtWidgets.QMessageBox.information(None,'Successful','Loading database succesfully created')
#Asking the user for the input file to be parsed and the number of componenets determined
filePath, _ = QtWidgets.QFileDialog.getOpenFileName(None, "Select input model","","Input deck (*.inp)","*.inp")
filePath = str(filePath)
self.pleaseWait = waitWindow()
self.pleaseWait.show()
#If no file has been inputted the script will exit
if not filePath:
exit()
else:
#If a file has been inputted now it will be opened and a list containing all the lines will be created
readInputFile(filePath)
#Searching in the file for all the valid components. We disregards collectors containing RBE3 elements
#as they don't require fatigue analysis
self.pleaseWait.close()
for line in model_file:
if "*ELEMENT," in line and "DCOUP3D" not in line:
#If a valid collector is found it will be added to the array of type numpy.
try:
#Checks if the collector has already been recorded as different element types partaining of the same component
#will be specified in different collectors win the input deck
if not line.split("ELSET=")[1][:-1] in self.collector_array:
self.collector_array = np.concatenate((self.collector_array,np.array([line.split("ELSET=")[1][:-1]])),axis=0)
except:
self.collector_array = np.array([line.split("ELSET=")[1][:-1]])
#model_file_obj.close
#Testing to see if the array has been created indicating the presence of at least one entity
#This will be useful if the user loads a load deck instead of a model as they have the same .inp extension
try:
self.collector_array
except:
QtWidgets.QMessageBox.information(None,'Error','File contains no element collectors')
#Creating the initial Window
self.mainWidget = QtWidgets.QWidget()
self.mainWidget.resize(500, 500)
self.mainWidget.setWindowFlags(self.mainWidget.windowFlags() | QtCore.Qt.MSWindowsFixedSizeDialogHint)
self.mainWidget.setWindowTitle("nCode analysis set-up")
#Creating the top level grid layout
self.mainGrid = QtWidgets.QGridLayout(self.mainWidget)
#Creating the boxes which will describe the analysis to be written in the .dcl file
self.analysis_type_label = QtWidgets.QLabel(self.mainWidget)
self.analysis_type_label.setText("Type of analysis")
self.mainGrid.addWidget(self.analysis_type_label,0,0)
self.analysis_type_combo = QtWidgets.QComboBox(self.mainWidget)
self.analysis_type_combo.addItems(["Fatigue","Proof plus fatigue"])
self.mainGrid.addWidget(self.analysis_type_combo,0,1,1,2)
self.load_deck_type_label = QtWidgets.QLabel(self.mainWidget)
self.load_deck_type_label.setText("Type of fatigue deck")
self.mainGrid.addWidget(self.load_deck_type_label,1,0)
self.load_deck_type_combo = QtWidgets.QComboBox(self.mainWidget)
self.load_deck_type_combo.addItems(["Regen braking","No regen braking"])
self.mainGrid.addWidget(self.load_deck_type_combo,1,1,1,2)
self.analysis_engine_type_label = QtWidgets.QLabel(self.mainWidget)
self.analysis_engine_type_label.setText("Analysis Engine")
self.mainGrid.addWidget(self.analysis_engine_type_label,2,0)
self.analysis_engine_type_combo = QtWidgets.QComboBox(self.mainWidget)
self.analysis_engine_type_combo.addItems(["EN analysis","SN analysis"])
self.mainGrid.addWidget(self.analysis_engine_type_combo,2,1,1,2)
#Creating a scrolable area to accommodate for a large number of components with possible lenghty names
self.scrollArea = QtWidgets.QScrollArea(self.mainWidget)
#The line below is absolutely required to make the scrollable area work.
self.scrollArea.setWidgetResizable(True)
self.mainGrid.addWidget(self.scrollArea,3,0,1,3)
self.secondaryWidget = QtWidgets.QWidget()
self.scrollArea.setWidget(self.secondaryWidget)
self.secondaryGrid = QtWidgets.QGridLayout(self.secondaryWidget)
#This bit creates the necessary object for every componenet that was found in the input deck.
#The globals method is used to dynamically assign objects to variables for subsequent manipulation.
for i in range(0, self.collector_array.shape[0]):
globals()["self.materialLabel"+str(i)] = QtWidgets.QLabel(self.secondaryWidget)
globals()["self.materialLabel"+str(i)].setText(self.collector_array[i]+" material")
self.secondaryGrid.addWidget(globals()["self.materialLabel"+str(i)],2+i,0)
globals()["self.materialName"+str(i)] = QtWidgets.QLineEdit(self.secondaryWidget)
globals()["self.materialName"+str(i)].setPlaceholderText("Drop material name here")
globals()["self.materialName"+str(i)].setFixedWidth(150)
self.secondaryGrid.addWidget(globals()["self.materialName"+str(i)],2+i,1)
globals()["self.materialPickingButton"+str(i)] = QtWidgets.QPushButton(self.secondaryWidget)
globals()["self.materialPickingButton"+str(i)].setText("Pick material")
globals()["self.materialPickingButton"+str(i)].clicked.connect(self.material_lookup)
self.secondaryGrid.addWidget(globals()["self.materialPickingButton"+str(i)],2+i,2)
#Creates the button that connects to the DLC_writer function
self.createDCL = QtWidgets.QPushButton(self.mainWidget)
self.createDCL.setText("Create DCL")
self.mainGrid.addWidget(self.createDCL,4,0,1,3)
self.createDCL.clicked.connect(self.DCL_guide)
self.mainWidget.show()
class waitWindow(QtWidgets.QDialog):
def __init__(self):
super().__init__()
self.setWindowTitle("Info")
self.resize(600,200)
self.VLayout = QtWidgets.QVBoxLayout(self)
self.message = QtWidgets.QLabel(self)
self.message.setFixedWidth(550)
self.message.setText("Please wait while input file is being read")
self.VLayout.addWidget(self.message)
class readInputFile():
def __init__(self,filePath):
model_file_obj = open(filePath, "r")
globals()['model_file'] = model_file_obj.readlines()
model_file_obj.close
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
ui = Ui_Form()
sys.exit(app.exec_())
The problem is my text label is missing from this window. I made it so big in case the label did not have enough space to fully display but in that case I think it would have displayed what it had space for. Hopefully someone knows why.
Edit: I have included the entire init function of Ui_Form. All my problems are caused in this bit the rest working ok.
The window you are viewing is not pleaseWait window but the mainWidget window.
The above is explained assuming that:
The file that is read is small, so the pleaseWait window will open and close instantly, so that being that synchronous action Qt will not have time to do it and for the user the window will never have been shown. For this case the solution is to give a reasonable time for the user to see the window.
The file is very large, the reading will take a long time blocking the eventloop, which will cause tasks such as displaying a window to not be performed, to avoid blocking the task must be executed in another thread.
Combining both solutions we obtain the following code:
import os
from functools import partial
from PyQt5 import QtCore, QtWidgets
class Worker(QtCore.QObject):
finished = QtCore.pyqtSignal()
contentChanged = QtCore.pyqtSignal(list)
#QtCore.pyqtSlot(str)
def read_file(self, fileName):
with open(fileName, "r") as model_file_obj:
model_file = model_file_obj.readlines()
print(model_file)
self.contentChanged.emit(model_file)
self.finished.emit()
class MainWidget(QtWidgets.QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.resize(500, 500)
self.setWindowFlags(
self.windowFlags() | QtCore.Qt.MSWindowsFixedSizeDialogHint
)
self.setWindowTitle("nCode analysis set-up")
mainGrid = QtWidgets.QGridLayout(self)
thread = QtCore.QThread(self)
thread.start()
self.m_worker = Worker()
self.m_worker.moveToThread(thread)
self.m_worker.contentChanged.connect(self.get_content)
def launch_task(self):
if not os.path.exists("loading_database.db"):
QtWidgets.QMessageBox.information(
None,
"Loading database missing",
"Loading database has not been found. Creation of a new one will be attempted",
)
# self.loadingDatabaseCreator()
QtWidgets.QMessageBox.information(
None, "Successful", "Loading database succesfully created"
)
fileName, _ = QtWidgets.QFileDialog.getOpenFileName(
None, "Select input model", "", "Input deck (*.inp)", "*.inp"
)
self.pleaseWait = WaitWindow()
self.pleaseWait.show()
self.m_worker.finished.connect(self.pleaseWait.close)
wrapper = partial(self.m_worker.read_file, fileName)
# Launch the task in a reasonable time for the window to show
QtCore.QTimer.singleShot(100, wrapper) #
#QtCore.pyqtSlot(list)
def get_content(self, lines):
print(lines)
class WaitWindow(QtWidgets.QDialog):
def __init__(self):
super().__init__()
self.setWindowTitle("Info")
self.resize(600, 200)
layout = QtWidgets.QVBoxLayout(self)
self.message = QtWidgets.QLabel(self)
self.message.setFixedWidth(550)
self.message.setText("Please wait while input file is being read")
layout.addWidget(self.message)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWidget()
w.show()
w.launch_task()
sys.exit(app.exec_())
Update:
import os
from functools import partial
import numpy as np
from PyQt5 import QtCore, QtWidgets
class MainWidget(QtWidgets.QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.resize(500, 500)
self.setWindowFlags(
self.windowFlags() | QtCore.Qt.MSWindowsFixedSizeDialogHint
)
self.setWindowTitle("nCode analysis set-up")
self.wait_window = WaitWindow()
thread = QtCore.QThread(self)
thread.start()
self.m_worker = Worker()
self.m_worker.moveToThread(thread)
self.m_worker.new_content_signal.connect(self.get_content)
# Creating the top level grid layout
mainGrid = QtWidgets.QGridLayout(self)
self.analysis_type_label = QtWidgets.QLabel(self)
self.analysis_type_label.setText("Type of analysis")
mainGrid.addWidget(self.analysis_type_label, 0, 0)
self.analysis_type_combo = QtWidgets.QComboBox(self)
self.analysis_type_combo.addItems(["Fatigue", "Proof plus fatigue"])
mainGrid.addWidget(self.analysis_type_combo, 0, 1, 1, 2)
self.load_deck_type_label = QtWidgets.QLabel(self)
self.load_deck_type_label.setText("Type of fatigue deck")
mainGrid.addWidget(self.load_deck_type_label, 1, 0)
self.load_deck_type_combo = QtWidgets.QComboBox(self)
self.load_deck_type_combo.addItems(
["Regen braking", "No regen braking"]
)
mainGrid.addWidget(self.load_deck_type_combo, 1, 1, 1, 2)
self.analysis_engine_type_label = QtWidgets.QLabel(self)
self.analysis_engine_type_label.setText("Analysis Engine")
mainGrid.addWidget(self.analysis_engine_type_label, 2, 0)
self.analysis_engine_type_combo = QtWidgets.QComboBox(self)
self.analysis_engine_type_combo.addItems(["EN analysis", "SN analysis"])
mainGrid.addWidget(self.analysis_engine_type_combo, 2, 1, 1, 2)
# Creating a scrolable area to accommodate for a large number of components with possible lenghty names
self.scrollArea = QtWidgets.QScrollArea(self)
# The line below is absolutely required to make the scrollable area work.
self.scrollArea.setWidgetResizable(True)
mainGrid.addWidget(self.scrollArea, 3, 0, 1, 3)
self.secondaryWidget = QtWidgets.QWidget()
self.scrollArea.setWidget(self.secondaryWidget)
self.secondaryGrid = QtWidgets.QGridLayout(self.secondaryWidget)
self.createDCL = QtWidgets.QPushButton(self)
self.createDCL.setText("Create DCL")
mainGrid.addWidget(self.createDCL, 4, 0, 1, 3)
def start_task(self):
if not os.path.exists("loading_database.db"):
QtWidgets.QMessageBox.information(
None,
"Loading database missing",
"Loading database has not been found. Creation of a new one will be attempted",
)
# self.loadingDatabaseCreator()
QtWidgets.QMessageBox.information(
None, "Successful", "Loading database succesfully created"
)
filePath, _ = QtWidgets.QFileDialog.getOpenFileName(
None, "Select input model", "", "Input deck (*.inp)", "*.inp"
)
if filePath:
self.wait_window.show()
self.m_worker.finished.connect(self.wait_window.close)
wrapper = partial(self.m_worker.read_file, filePath)
# Launch the task in a reasonable time for the window to show
QtCore.QTimer.singleShot(100, wrapper)
#QtCore.pyqtSlot(int, str)
def get_content(self, i, content):
label = QtWidgets.QLabel("{} material".format(content))
linedit = QtWidgets.QLineEdit(placeholderText="Drop material name here")
linedit.setFixedWidth(150)
button = QtWidgets.QPushButton("Pick material")
self.secondaryGrid.addWidget(label, 2 + i, 0)
self.secondaryGrid.addWidget(linedit, 2 + i, 1)
self.secondaryGrid.addWidget(button, 2 + i, 2)
class WaitWindow(QtWidgets.QDialog):
def __init__(self):
super().__init__()
self.setWindowTitle("Info")
self.resize(600, 200)
layout = QtWidgets.QVBoxLayout(self)
self.message = QtWidgets.QLabel()
self.message.setFixedWidth(550)
self.message.setText("Please wait while input file is being read")
layout.addWidget(self.message)
class Worker(QtCore.QObject):
finished = QtCore.pyqtSignal()
new_content_signal = QtCore.pyqtSignal(int, str)
#QtCore.pyqtSlot(str)
def read_file(self, fileName):
i = 0
collector_array = []
with open(fileName, "r") as model_file_obj:
for line in model_file_obj.readlines():
if "*ELEMENT," in line and "DCOUP3D" not in line:
t = line.split("ELSET=")[1][:-1]
if t not in collector_array:
self.new_content_signal.emit(i, t)
QtCore.QThread.msleep(10)
collector_array.append(t)
i += 1
self.finished.emit()
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWidget()
w.show()
w.start_task()
sys.exit(app.exec_())
This code works perfectly for me:
import sys
from PyQt5 import QtWidgets
from PyQt5.Qt import QApplication
class waitWindow(QtWidgets.QDialog):
def __init__(self):
super().__init__()
self.setWindowTitle("Info")
self.resize(600,200)
self.VLayout = QtWidgets.QVBoxLayout(self)
self.message = QtWidgets.QLabel(self)
self.message.setFixedWidth(550)
self.message.setText("Please wait while input file is being read")
self.VLayout.addWidget(self.message)
self.show()
def closeWindow(self):
self.close()
app = QApplication(sys.argv)
w = waitWindow()
w.exec_()
Okay took your code and gutted all the unessential stuff to analyze the actual issue I have included the gutted version so you can see what is necessary in the future to see what is wrong.
In short the issue is that you need to add the following line as the last line in your waitWindow function >> self.exec() by adding that I got your label to display (see code below)
Now with that said you do have another issue and that is the QDialog box will not allow the program to continue until it has been closed (aka it stops the process flow until you release it by closing the window or use a different means). My question is why not use your "main window" to display that message then repopulate with the rest of that data. Also curious why are you not using QMainWindow?
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
class Ui_Form():
def __init__(self):
self.pleaseWait = waitWindow()
self.pleaseWait.show()
self.pleaseWait.close()
sys.exit()
class waitWindow(QDialog):
def __init__(self):
super(waitWindow, self).__init__()
self.setWindowTitle("Info")
self.resize(600,200)
self.message = QLabel(self)
self.message.setFixedWidth(550)
self.message.setText("Please wait while input file is being read")
self.VLayout = QVBoxLayout(self)
self.VLayout.addWidget(self.message)
self.setLayout(self.VLayout)
self.exec_()
if __name__ == "__main__":
app = QApplication(sys.argv)
ui = Ui_Form()
sys.exit(app.exec_())

How to use BytesIO with matplotlib and pyqt5?

I made a graph in matplotlib, and wanted to make it in to an image and use it in my pyqt5 application. Someone suggested I use BytesIO for this. This is my code so far:
Drawing my graph:
...
plt.axis('equal')
buff = io.BytesIO()
plt.savefig(buff, format="png")
print(buff)
return buff
This is then called in another script:
def minionRatioGraphSetup(self, recentMinionRatioAvg):
image = minionRatioGraph(recentMinionRatioAvg)
label = QtWidgets.QLabel()
pixmap = QtGui.QPixmap(image)
label.setPixmap(pixmap)
label.setGeometry(QtCore.QRect(0,0,200,200))
It stops working at pixmap = QtGui.QPixmap(image) and I'm unsure why. Also: How could I place this in my MainWindow? because I doubt the code there will work lol
I'm sure there is a solution using a buffer. However, it seems rather complicated to get the byte format correct. So an alternative is to save the image to disk, and then load it from there.
import sys
from PyQt4 import QtGui
import matplotlib.pyplot as plt
import numpy as np
def minionRatioGraph():
plt.plot([1,3,2])
plt.savefig(__file__+".png", format="png")
class App(QtGui.QWidget):
def __init__(self):
super(App, self).__init__()
self.setGeometry(300, 300, 250, 150)
self.setLayout(QtGui.QVBoxLayout())
label = QtGui.QLabel()
label2 = QtGui.QLabel("Some other text label")
minionRatioGraph()
qimg = QtGui.QImage(__file__+".png")
pixmap = QtGui.QPixmap(qimg)
label.setPixmap(pixmap)
self.layout().addWidget(label)
self.layout().addWidget(label2)
self.show()
if __name__ == '__main__':
app = QtGui.QApplication([])
ex = App()
sys.exit(app.exec_())
a snippet using pillow, might help avoiding file io
im = PIL.Image.open("filename")
with BytesIO() as f:
im.save(f, format='png')
f.seek(0)
image_data = f.read()
qimg = QImage.fromData(image_data)
patch_qt = QPixmap.fromImage(qimg)
Here's a solution that only uses the buffer, you need to use PIL to create an ImageQT and then load it to the QPixap
import matplotlib.pyplot as plt
import io
from PIL.ImageQt import ImageQt
from PIL import Image
...
buff = io.BytesIO()
plt.savefig(buff, format="png")
img = Image.open(buff)
img_qt = ImageQt(img)
return img_qt
Then, in your GUI setup, you call your function to return the ImageQT and generate the QPixmap using QPixmap.fromImage()
def minionRatioGraphSetup(self, recentMinionRatioAvg):
image = minionRatioGraph(recentMinionRatioAvg)
label = QtWidgets.QLabel()
pixmap = QtGui.QPixmap.fromImage(image)
label.setPixmap(pixmap)
label.setGeometry(QtCore.QRect(0,0,200,200))

Take a screenshot of an iFrame using pyside

I have an issue taking screenshots of a Google-translated page. The below script is working fine (takes a screenshot) without Google translate:
class Render(QWebPage):
def __init__(self, url):
self.web_page = QWebPage()
self.finished = False
s = self.web_page.settings()
s.setAttribute(QWebSettings.JavascriptCanOpenWindows, False)
s.setAttribute(QWebSettings.PluginsEnabled, True)
self.web_page.mainFrame().setScrollBarPolicy(Qt.Horizontal, Qt.ScrollBarAlwaysOff)
self.web_page.loadFinished.connect(self._loadFinished)
self.web_page.mainFrame().load(QUrl(url))
def _loadFinished(self, result):
frame = self.web_page.mainFrame()
size = frame.contentsSize()
size.setWidth(1000)
self.web_page.setViewportSize(size)
image = QImage(self.web_page.viewportSize(), QImage.Format_ARGB32)
painter = QPainter(image)
frame.render(painter)
painter.end()
self.filepath="screenshot_name.jpg"
image.save(self.filepath)
self.finished = True
def run(url):
app=QApplication.instance()
if not app:
app = QApplication(sys.argv)
r = Render(url)
while not r.finished:
app.processEvents()
time.sleep(0.01)
return r.filepath
news_url="http://arabic-media.com/arabicnews.htm"
news_url_google_translate = "http://translate.google.com/translate?hl=en&sl=auto&tl=en&u="+news_url
run(news_url_google_translate)
But I need to take a screenshot of the translated page. Google translated page creates iframes. So I used the following to take a screenshot of the inner frame (name=c):
frame = self.web_page.mainFrame().childFrames()[0]
Unfortunately, my script is still taking black screenshots.
See if this example works for you. The finished signal of the network manager is connected to a slot that checks the url that has finished downloading, and triggers the screenshot if it finds urlRequest in it:
#!/usr/bin/env python
#-*- coding:utf-8 -*-
import sip
sip.setapi('QString', 2)
sip.setapi('QVariant', 2)
from PyQt4 import QtCore, QtGui, QtWebKit, QtNetwork
urlTranslate = "http://translate.google.com/translate?hl=en&sl=auto&tl=en&u=http://arabic-media.com/arabicnews.htm"
urlRequest = "http://www.google.com/cse/intl/ar/images/google_custom_search_watermark.gif"
class myWindow(QtWebKit.QWebView):
def __init__(self, parent=None):
super(myWindow, self).__init__(parent)
self.page().mainFrame().setScrollBarPolicy(QtCore.Qt.Horizontal, QtCore.Qt.ScrollBarAlwaysOff)
self.page().mainFrame().setScrollBarPolicy(QtCore.Qt.Vertical, QtCore.Qt.ScrollBarAlwaysOff)
self.page().networkAccessManager().finished.connect(self.on_networkAccessManager_loadFinished)
self.load(QtCore.QUrl(urlTranslate))
#QtCore.pyqtSlot(QtNetwork.QNetworkReply)
def on_networkAccessManager_loadFinished(self, reply):
if urlRequest in reply.url().toString():
self.takeScreenshot()
def takeScreenshot(self):
fileName = self.title() + ".png"
self.page().setViewportSize(QtCore.QSize(1000, 2000))
image = QtGui.QImage(self.page().viewportSize(), QtGui.QImage.Format_ARGB32)
painter = QtGui.QPainter(image)
self.page().mainFrame().render(painter)
painter.end()
if not image.isNull():
image.save(fileName)
print "Succesfully saved '{0}'".format(fileName)
else:
print "Failed to save '{0}'".format(fileName)
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
app.setApplicationName('myWindow')
main = myWindow()
main.show()
sys.exit(app.exec_())
i have fixed that full page load issue using below piece of code. now this code will stop after 30 seconds and it will take screenshot.
self.web_page.networkAccessManager().finished.connect(self.on_networkAccessManager_loadFinished)
self._error = None
request = QNetworkRequest()
request.setUrl(QUrl(url))
self.timeout_timer = QTimer()
self.timeout_timer.timeout.connect(self._request_timed_out)
self.timeout_timer.start(30 * 1000) #30 seconds
self.web_page.mainFrame().load(request)
def _request_timed_out(self):
self._error = 'Custom request timeout value exceeded.'
print self._error
self.timeout_timer.stop()
self.web_page.killTimer(0)
self.web_page.loadFinished.emit(False)
self.takeScreenshot()

Categories

Resources