SEGV_MAPERR 对于 PyQt5 对象
SEGV_MAPERR for PyQt5 object
为什么下面的演示代码会产生一个SEGV_MAPERR?如何解决它?
提示:一旦删除了“#ref1”注释的行,就不会产生错误。这在从问题中抽象出来的生产代码中不容易完成。
from PyQt5 import QtCore, QtGui, QtWidgets, QtWebChannel
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
self.webView = QtWebEngineWidgets.QWebEngineView(self.centralwidget)
self.webView.setHtml("")
self.gridLayout.addWidget(self.webView, 0, 0, 1, 1)
MainWindow.setCentralWidget(self.centralwidget)
page = self.webView.page() # REF1
for i in range(2):
self.init_page()
def init_page(self):
class EditObject(QtCore.QObject):
@QtCore.pyqtSlot(str)
def edit(self, s):
print("test")
editObject = EditObject(self.webView.page())
poChannel = self.webView.page().webChannel()
print(1)
if poChannel is None:
poChannel = QtWebChannel.QWebChannel()
self.webView.page().setWebChannel(poChannel)
print(2)
objects = poChannel.registeredObjects()
print(objects)
poChannel.registerObject("editObject", editObject)
self.webView.setHtml("")
from PyQt5 import QtWebEngineWidgets
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
这类似于Issues with PyQt5==5.10 on Ubuntu 18, but with example code. For the example code, https://gist.github.com/gioditalia/03c9fd5d793aeccbe065fea45d842431改编。
问题是poChannel
是一个局部变量,执行完init_page就会被删除,所以在第二次迭代中poChannel
引用会指向一个不正确的内存地址。所以解决方案是将它的周期扩展到视图的周期,所以我们利用 Qt 属性 并将其作为父级传递给 self.webView
.
poChannel = QtWebChannel.QWebChannel(self.webView)
虽然 PyQt 在 the docs 和生成的文件中指出:# WARNING! All changes made in this file will be lost!
,但修改 .ui 生成的 class 并不方便,而是您必须创建另一个 class 从适当的小部件继承并使用 Qt Designer 提供的界面。
from PyQt5 import QtCore, QtGui, QtWidgets, QtWebEngineWidgets, QtWebChannel
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
self.webView = QtWebEngineWidgets.QWebEngineView(self.centralwidget)
self.gridLayout.addWidget(self.webView, 0, 0, 1, 1)
MainWindow.setCentralWidget(self.centralwidget)
class EditObject(QtCore.QObject):
@QtCore.pyqtSlot(str)
def edit(self, s):
print("test")
class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.setupUi(self)
for i in range(2):
self.init_page()
def init_page(self):
editObject = EditObject(self.webView.page())
poChannel = self.webView.page().webChannel()
if poChannel is None:
poChannel = QtWebChannel.QWebChannel(self)
self.webView.page().setWebChannel(poChannel)
objects = poChannel.registeredObjects()
poChannel.registerObject("editObject", editObject)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
为什么下面的演示代码会产生一个SEGV_MAPERR?如何解决它?
提示:一旦删除了“#ref1”注释的行,就不会产生错误。这在从问题中抽象出来的生产代码中不容易完成。
from PyQt5 import QtCore, QtGui, QtWidgets, QtWebChannel
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
self.webView = QtWebEngineWidgets.QWebEngineView(self.centralwidget)
self.webView.setHtml("")
self.gridLayout.addWidget(self.webView, 0, 0, 1, 1)
MainWindow.setCentralWidget(self.centralwidget)
page = self.webView.page() # REF1
for i in range(2):
self.init_page()
def init_page(self):
class EditObject(QtCore.QObject):
@QtCore.pyqtSlot(str)
def edit(self, s):
print("test")
editObject = EditObject(self.webView.page())
poChannel = self.webView.page().webChannel()
print(1)
if poChannel is None:
poChannel = QtWebChannel.QWebChannel()
self.webView.page().setWebChannel(poChannel)
print(2)
objects = poChannel.registeredObjects()
print(objects)
poChannel.registerObject("editObject", editObject)
self.webView.setHtml("")
from PyQt5 import QtWebEngineWidgets
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
这类似于Issues with PyQt5==5.10 on Ubuntu 18, but with example code. For the example code, https://gist.github.com/gioditalia/03c9fd5d793aeccbe065fea45d842431改编。
问题是poChannel
是一个局部变量,执行完init_page就会被删除,所以在第二次迭代中poChannel
引用会指向一个不正确的内存地址。所以解决方案是将它的周期扩展到视图的周期,所以我们利用 Qt 属性 并将其作为父级传递给 self.webView
.
poChannel = QtWebChannel.QWebChannel(self.webView)
虽然 PyQt 在 the docs 和生成的文件中指出:# WARNING! All changes made in this file will be lost!
,但修改 .ui 生成的 class 并不方便,而是您必须创建另一个 class 从适当的小部件继承并使用 Qt Designer 提供的界面。
from PyQt5 import QtCore, QtGui, QtWidgets, QtWebEngineWidgets, QtWebChannel
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
self.webView = QtWebEngineWidgets.QWebEngineView(self.centralwidget)
self.gridLayout.addWidget(self.webView, 0, 0, 1, 1)
MainWindow.setCentralWidget(self.centralwidget)
class EditObject(QtCore.QObject):
@QtCore.pyqtSlot(str)
def edit(self, s):
print("test")
class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.setupUi(self)
for i in range(2):
self.init_page()
def init_page(self):
editObject = EditObject(self.webView.page())
poChannel = self.webView.page().webChannel()
if poChannel is None:
poChannel = QtWebChannel.QWebChannel(self)
self.webView.page().setWebChannel(poChannel)
objects = poChannel.registeredObjects()
poChannel.registerObject("editObject", editObject)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())