PyQt5 seg fault when importing QQuickImageProvider - pyqt5

i've encountered a very weird behavior which led to a seg fault when working on my app.
can someone please explain why it crashes ?
system:
ubuntu 18.04
PyQt 5.9.2
python 3.6
conditions:
have a QApplication based class
create QQmlApplicationEngine (even if its not used)
import- from PyQt5.QtQuick import QQuickImageProvider (even if its not used)
have a signal/slot that send/recieve a list type and send a [None]
emit the signal only after the engine is instantiated
** it doesnt matter if the slot has a #pyqtslot decorator or not
** if i change the signal signature to object instead of list everything is fine
** if you remove even one of the conditions you wont get the seg fault.
example:
import sys
from PyQt5.QtCore import QObject, pyqtSignal
from PyQt5.QtWidgets import QApplication
from PyQt5.QtQml import QQmlApplicationEngine
from PyQt5.QtQuick import QQuickImageProvider # if you comment out it wont crash
APP = None
class SomeCrashingClass(QObject):
sig = pyqtSignal(list)
def __init__(self):
QObject.__init__(self)
self.sig.connect(self.my_func)
self.sig.emit([None]) # if you send a [] it wont crash
def my_func(self):
print(f"-------------everything is fineeeeeeeeeeeeeeeeeeee-----------------")
class CrashingApp(QApplication):
def __init__(self):
super(CrashingApp, self).__init__(sys.argv)
self._engine = QQmlApplicationEngine() # if you comment out it wont crash
bla = SomeCrashingClass()
def run(self):
print(f"---------------------running the app ------------------")
exit_status = self.exec_()
print(f"----------exit status {exit_status}")
def run():
global APP
APP = CrashingApp()
sys.exit(APP.run())
if __name__ == "__main__":
run()
EDIT:
changing sig = pyqtSignal(object) solves the issue

Related

PyQt6 QWebEngineView can't load PPAPI flash player

I want to make a custom client for an online flash game
I am on Linux Manjaro KDE
I installed PPAPI using sudo pamac install pepper-flash
the result of this code
from PyQt6.QtCore import QUrl
from PyQt6.QtWidgets import *
from PyQt6.QtGui import *
from PyQt6.QtWebEngineWidgets import *
from PyQt6.QtWebEngineCore import QWebEngineSettings
import sys
sys.argv += ['--webEngineArgs',
"--register-pepper-plugins=/usr/lib/PepperFlash/libpepflashplayer.so;application/x-shockwave-flash",
"--ppapi-flash-path=/usr/lib/PepperFlash/libpepflashplayer.so", '--ppapi-flash-version=32.21.0.153']
class MainWindow(QMainWindow):
def __init__(self, *args, **kwargs):
super(MainWindow,self).__init__(*args, **kwargs)
self.browser = QWebEngineView()
self.setCentralWidget(self.browser)
self.browser.settings().setAttribute(QWebEngineSettings.WebAttribute.PluginsEnabled, True)
self.browser.settings().setAttribute(QWebEngineSettings.WebAttribute.JavascriptEnabled, True)
self.browser.setUrl(QUrl("https://webbrowsertools.com/test-flash-player/"))
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec())
is "This plugin is not supported"
What am I missing ???
once, I managed to run flash on PyQt5 QWebEngineView
but now the web page on PyQt5 is not even rendering. it is blank. I don't know why, it is the same code that worked before.
EDIT:
I managed to get PyQt5 QWebEngineView working again.
see https://stackoverflow.com/a/74325318/10701585

How to track pyqt5 crash errors?

I use QWebEngineView to log in to the telegram web.
I would like to be able to save the session in the profile.
When I try to load a profile with an authorized session, my application abruptly terminates.
Is there anything I can do to track the errors that occurred during startup?
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtWebEngineWidgets import *
from PyQt5.QtCore import *
class Window(QMainWindow):
def __init__(self):
super(Window,self).__init__()
self.browser = QWebEngineView()
profile = QWebEngineProfile(f"profile", self.browser)
webpage = QWebEnginePage(profile, self.browser)
self.browser.setPage(webpage)
self.browser.load(QUrl('https://web.telegram.org/z'))
self.browser.show()
if __name__ == "__main__":
MyApp = QApplication(sys.argv)
window = Window()
MyApp.exec_()

How do I prevent the QPushButton.clicked from the widget from executing when I'm in MainWindow pyqt5?

I set the printInWidget clicked method for the btnprint button in widget1. But I want to replace that command in MainWindow with command printInMain by code: self.wid.btnprint.clicked.connect(self.printInMain). I don't know why it does both commands in MainWindow. Please help me make the command printInWidget not execute when running MainWidow.
Sorry everyone (English is not my native language and I only approached pyqt5 for a few months by teaching myself).
when I click button "printText"
my code:
mainwindow.py
from PyQt5 import QtWidgets
from PyQt5.QtWidgets import QMainWindow, QApplication, QPushButton, QTextEdit, QGridLayout, QVBoxLayout, QFileDialog,QHBoxLayout,QSpacerItem,QSizePolicy
from PyQt5 import uic, QtCore
import sys
from widget1 import *
class UI(QMainWindow):
def __init__(self):
super(UI, self).__init__()
uic.loadUi("MainWindow.ui", self)
self.wid = widget1()
self.verticalLayout.addWidget(self.wid)
self.wid.btnprint.clicked.connect(self.printInMain)
# I want to override method of button printText
def printInMain(self):
self.wid.labelB.setText('New text (method in Main)')
if __name__ == '__main__':
app = QApplication(sys.argv)
window = UI()
window.show()
app.exec_()
widget1.py
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QMainWindow
from PyQt5.QtGui import QIcon
from PyQt5 import uic
class widget1(QWidget):
def __init__(self):
super().__init__()
uic.loadUi('widget1.ui',self)
self.btnprint.clicked.connect(self.printInwidget)
def printInwidget(self):
self.labelA.setText('Hello World (Method in Widget)')
if __name__ == '__main__':
app = QApplication(sys.argv)
Main = QMainWindow()
widget = widget1()
widget.show()
sys.exit(app.exec_())
You need to disconnect. If you want to use the initial behaviour again you need to connect the signal to the slot again. I would suggest creating a reconnect() function that will do that for you if you decide to do the whole thing many times.
Here is an example.
More info can be found in the official QObject documentation (look for bool QObject::disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)).
Also try to provide full code or at least a minimal working example. What you have posted right now cannot work due to missing dependencies and a UI file.

Numpy to QImage Crashing

The following code crashes on clicking the button or after a few clicks when the signal is emitted from thread and caught in the main gui.
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtGui import QPixmap, QImage
from PyQt5.QtCore import pyqtSignal, pyqtSlot, Qt, QThread
import numpy as np
import time
from PyQt5.QtWidgets import QApplication, QDialog, QPushButton, QVBoxLayout
def convert_np_qimage(cv_img , width, height):
h, w, ch = cv_img.shape
bytes_per_line = ch * w
qim = QtGui.QImage(cv_img.data, w, h, bytes_per_line, QtGui.QImage.Format_RGB888)
print(qim.size())
return qim
class VideoThread(QThread):
change_qimage_signal = pyqtSignal(QImage)
def __init__(self):
super().__init__()
def run(self):
print("run")
width = 1280
height = 1280
cv_img = np.zeros([height,width,3],dtype=np.uint8)
cv_img.fill(255)
print("image shape: ", cv_img.shape)
qimg = convert_np_qimage(cv_img, width, height)
self.change_qimage_signal.emit(qimg)
print("emitted")
def stop(self):
self.wait()
import sys
class Dialog(QDialog):
def __init__(self):
super(Dialog, self).__init__()
Dialog.resize(self, 640, 480)
button=QPushButton("Click")
button.clicked.connect(self.startThread)
mainLayout = QVBoxLayout()
mainLayout.addWidget(button)
self.setLayout(mainLayout)
self.setWindowTitle("QImage Example")
def startThread(self):
self.thread = VideoThread()
self.thread.change_qimage_signal.connect(self.getPixmap)
self.thread.start()
def getPixmap(self, qimg):
print("got qimage")
qpixmap = QPixmap.fromImage(qimg)
if __name__ == '__main__':
app = QApplication(sys.argv)
dialog = Dialog()
sys.exit(dialog.exec_())
The program doesn't crash if height and width are set to small number say 3.
The program also doesn't crash if we convert qimage to qpixmap before emitting and change the signal
type to QPixmap.
The program was originally written to get images from webcam using opencv. The numpy array created
by opencv crashes too for big image sizes.
The OS used is Windows10, pyqt version is 5.12.3
Any idea what might be the reason for the crash?
In Linux with PyQt5 5.15 I do not reproduce the problem, but that error is common and occurs because passing "data" does not copy the information but rather the data is shared, so at some point cv_img and all associated objects are destroyed including to "data" so when transmitting it through the signal and setting it in the QLabel that "data" is read but it no longer has reserved memory. The solution in this case is to copy "data":
qim = QtGui.QImage(
cv_img.data.tobytes(), w, h, bytes_per_line, QtGui.QImage.Format_RGB888
)
or copy the QImage.
return qim.copy()

How to embed an URxvt terminal in a Pyqt5 GUI?

I have constructed a GUI in QtChooser and the code for it is written in PyQt5. I have a total of 7 tabs in the GUI, each of which are defined in the QMainWindow class of my code. These definitions contain the codes for each TextEdit, LineEdit, PushButtons, RadioButtons, etc.
However, in one the the tabs, I want to embed an external terminal which will open when a particular PushButton is clicked within that tab. I was able to open the Urxvt terminal when the RadioButton is toggled. The issue I'm facing now is to open the terminal specifically in the area of the TextEdit. This is how the original GUI (built in the QtDesigner looks like. I need the terminal to open in the TextEdit below the Output label. But, this is how the terminal opens in the GUI when the code is run
This is a part of the updated code:
from PyQt5 import QtCore, QtGui, QtWidgets, uic
from PyQt5.QtGui import QPixmap
from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel, QPushButton, QMessageBox, QAction
from PyQt5.QtCore import QDate, QTime, QDateTime, Qt
import sys
import platform
import os
import subprocess
import time
import re
import textwrap
class EmbTerminal(QtWidgets.QWidget):
def __init__(self, parent=None):
super(EmbTerminal, self).__init__()
self.process = QtCore.QProcess(self)
self.terminal = QtWidgets.QWidget(self)
layout = QtWidgets.QVBoxLayout(self)
layout.addWidget(self.terminal)
# Works also with urxvt:
self.process.start('urxvt',['-embed', str(int(self.winId())), '-bg', '#000000', '-fg', '#ffffff'])
self.setFixedSize(539, 308)
class Ui_Dialog(QtWidgets.QMainWindow):
def __init__(self):
super(Ui_Dialog, self).__init__()
#Load GUI from QT5 Designer
uic.loadUi("S1_mainwindow.ui", self)
def openTerminalCheckBox (self):
if self.openTerminalRMachineRadioButton.isChecked():
status = True
self.commandLineRemoteCommandRMachineLineEdit.setDisabled(True)
self.commandlineRemoteCommandRMachineLabel.setDisabled(True)
self.executeRemoteCommandRMachinePushButton.setDisabled(True)
self.remoteMachineOutputLabel.setText("Terminal")
self.outputRMachineTextEdit = QtWidgets.QTabWidget()
self.gridLayout_6.addWidget(self.outputRMachineTextEdit)
self.outputRMachineTextEdit.addTab(EmbTerminal(), "EmbTerminal")
else:
status = False
app = QtWidgets.QApplication(sys.argv) # Create an instance of QtWidgets.QApplication
window = Ui_Dialog()
main = mainWindow()
main.show() # Create an instance of our class
app.exec_()
I need to open the terminal specifically in the QTextEdit which is already been defined in that tab. Do you guys have any suggestions/input?