PyQt5 treeview and mediaplayer crash - python-3.4

this is code with player only work fine ; with treeview only also work but together the app crash immediately if i click on radio button to show the treeview.
But if i click open button and the file explorer appear than it work and i can use radiobutton without problem ; i don't know why.
import sys
from PyQt5 import QtGui, QtWidgets, QtCore, uic
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtMultimedia import *
from PyQt5.QtMultimediaWidgets import *
from PyQt5.uic import loadUi
class MyApp(QMainWindow):
def __init__(self):
super(MyApp, self).__init__()
loadUi("window.ui", self)
#########################################################################
self.model = QFileSystemModel(self)
self.model.setRootPath(self.model.myComputer())
self.treeview.setModel(self.model)
self.treeview.clicked.connect(self.on_treeView_clicked)
self.folder_open.toggled.connect(self.HideShow) # show/hide treeview
#########################################################################
self.media = QMediaPlayer()
video = QVideoWidget(self.videoShow)
video.setGeometry(QtCore.QRect(0, 0, 439, 282))
self.playButton.clicked.connect(self.playVideo)
self.openbtn.clicked.connect(self.openFile)
self.media.setVideoOutput(video)
#########################################################################
#QtCore.pyqtSlot(QtCore.QModelIndex)
def on_treeView_clicked(self, index):
indexItem = self.model.index(index.row(), 0, index.parent())
filePath = self.model.filePath(indexItem)
self.choice.setText(filePath)
def HideShow(self):
if self.folder_open.isChecked() == True:
self.showTree()
if self.folder_open.isChecked() == False:
self.hideTree()
def showTree(self):
self.list.setFixedSize(443, 310)
window.setFixedSize(1200, 320)
def hideTree(self):
self.list.setFixedSize(0, 310)
window.setFixedSize(750, 320)
###########################################################################
def openFile(self):
fileName, _ = QFileDialog.getOpenFileName(self, "Open Movie",QDir.homePath())
if fileName != '':
self.media.setMedia(QMediaContent(QUrl.fromLocalFile(fileName)))
def playVideo(self):
fileName = self.choice.text()
self.media.setMedia(QMediaContent(QUrl.fromLocalFile(fileName)))
self.media.play()
#if self.media.state() == QMediaPlayer.PlayingState:
#self.media.pause()
#else:
#self.media.play()
###########################################################################
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MyApp()
window.setFixedSize(750, 320)
window.show()
sys.exit(app.exec_())
window.ui used : download here

Related

How to overlay transparent image on qt camera?

Im trying to overlay an image with transparency on QCameraViewfinder. The following code works fine on windows, but ignores the transparency on raspberry pi.
Im using pyside2 version 5.11.2 on RPI4 and tried tranparent PNG and SVG files.
As an alternative, if Im using paintEvent to draw shapes, the viewfinder doesnt show video. My QPainter code is attached too.
from PySide2.QtMultimedia import QCamera, QCameraInfo
from PySide2.QtMultimediaWidgets import QCameraViewfinder
from PySide2 import QtCore, QtGui
from PySide2.QtWidgets import *
from PySide2.QtGui import *
from PySide2.QtCore import *
import sys
class ExampleWindow(QMainWindow):
def __init__(self, windowsize):
super().__init__()
self.windowsize = windowsize
self.initUI()
def initUI(self):
self.setFixedSize(self.windowsize)
widget = QWidget()
self.setCentralWidget(widget)
self.view_finder = QCameraViewfinder()
camerainfo = QCameraInfo.availableCameras()[0]
self.camera = QCamera(camerainfo)
self.camera.setViewfinder(self.view_finder)
self.camera.start()
layout_box = QHBoxLayout(widget)
layout_box.setContentsMargins(0, 0, 0, 0)
layout_box.addWidget(self.view_finder)
pixmap = QPixmap('crosshair3.png')
self.image = QLabel(widget)
self.image.setPixmap(pixmap)
self.image.setFixedSize(pixmap.size())
hw = pixmap.size().width()/2
hh = pixmap.size().height()/2
self.image.move(self.rect().center().x()-hw, self.rect().center().y()-hh)
if __name__ == '__main__':
app = QApplication(sys.argv)
screensize = app.desktop().availableGeometry().size()
ex = ExampleWindow(screensize)
ex.show()
sys.exit(app.exec_())
When using QPainter there is no video on the viewfinder:
class MyQCameraViewfinder(QCameraViewfinder):
def __init__(self, parent=None):
super().__init__(parent)
def paintEvent(self, event):
paint = QtGui.QPainter()
paint.begin(self)
paint.setRenderHint(QtGui.QPainter.Antialiasing)
paint.setPen(QtCore.Qt.black)
paint.setBrush(QtCore.Qt.white)
paint.drawEllipse(QtCore.QRect(17, 22, 50, 50))
paint.end()
on windows 11:
on rpi 4:

PyQt5 Qthread Create

AttributeError: type object 'QThread' has no attribute 'create'
Here is my code.
from PyQt5.QtCore import QThread
def fun(num):
print(num)
thread1 = QThread.create(fun)
thread1.start()
But Qt documentation says there is a function called create since Qt 5.10. I am using PyQt5 5.11.3. Someone please help me with this.
You can use worker objects by moving them to the thread using QObject::moveToThread().
from PyQt5.QtCore import QObject, pyqtSignal, QThread, QTimer
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QProgressBar, QPushButton
class Worker(QObject):
valueChanged = pyqtSignal(int) # Value change signal
def run(self):
print('thread id ->', int(QThread.currentThreadId()))
for i in range(1, 101):
print('value =', i)
self.valueChanged.emit(i)
QThread.msleep(100)
class Window(QWidget):
def __init__(self, *args, **kwargs):
super(Window, self).__init__(*args, **kwargs)
layout = QVBoxLayout(self)
self.progressBar = QProgressBar(self)
self.progressBar.setRange(0, 100)
layout.addWidget(self.progressBar)
layout.addWidget(QPushButton('Open thread', self, clicked=self.onStart))
# Current thread id
print('main id = ', int(QThread.currentThreadId()))
# Start thread update progress bar value
self._thread = QThread(self)
self._worker = Worker()
self._worker.moveToThread(self._thread) # Move to thread to execute
self._thread.finished.connect(self._worker.deleteLater)
self._worker.valueChanged.connect(self.progressBar.setValue)
def onStart(self):
print('main id -> ', int(QThread.currentThreadId()))
self._thread.start() # Start thread
QTimer.singleShot(1, self._worker.run)
def closeEvent(self, event):
if self._thread.isRunning():
self._thread.quit()
del self._thread
del self._worker
super(Window, self).closeEvent(event)
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
w = Window()
w.show()
w.setWindowTitle('Demo moveToThread')
sys.exit(app.exec_())

QWidget painter

I have this code:
import sys, random, pprint
from PyQt5 import QtWidgets, QtGui, QtCore
from PyQt5 import QtGui
from PyQt5.QtCore import Qt
class Window(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.setGeometry(QtCore.QRect(200, 200, 700, 700))
self.widget = QtWidgets.QWidget(self)
self.widget.setGeometry(QtCore.QRect(10, 10, 400, 200))
self.widget.setObjectName("widget")
def paintEvent(self, event):
painter = QtGui.QPainter()
painter.begin(self.widget)
self.drawPoints(painter)
painter.end()
def drawPoints(self, painter):
#drawing code
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
ex = Window()
ex.show()
sys.exit(app.exec_())
What do i expect: area (400x200) which would be painted by drawPoints(). QWidget inherits QPaintDevice. So this code should work. But console says:
QPainter::begin: Paint device returned engine == 0, type: 1
QPainter::end: Painter not active, aborted
Could you help me, please.
It looks like you are attempting to replicate this example, correct?
The major difference appears to be that you are defining paintEvent() for the main window, rather than the widget you are actually trying to paint. It would work if you created a custom subclass of QWidget, defined paintEvent() there, and then inserted that into a standard QMainWindow instance, like this:
class MyWidget(QtWidgets.QWidget):
def __init__(self, parent=None):
super(MyWidget, self).__init__(parent=parent)
self.initUI()
def initUI(self):
self.setGeometry(QtCore.QRect(10, 10, 400, 200))
self.setObjectName("widget")
def paintEvent(self, event):
painter = QtGui.QPainter()
painter.begin(self)
self.drawPoints(painter)
painter.end()
def drawPoints(self, painter):
pass
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
my_window = QtWidgets.QMainWindow()
my_window.setGeometry(QtCore.QRect(200, 200, 700, 700))
my_window.setCentralWidget(MyWidget(my_window))
my_window.show()
sys.exit(app.exec_())
At the very least, it isn't printing that error message anymore.

Set splitter handle as QScrollArea corner widget?

I'm trying to display files and folders like column view in Mac finder.
I was able get the basic structure with the help of ListViews and QFileSystemModel. Then I set the splitter handle as a corner widget for the scroll area. I have two issues here
When I resize the listview, the splitter handle disappears.
Even after setting the splitter handle width to 0, I see spacing between
listviews.
# -*- coding: utf-8 -*-
from PyQt4 import QtCore, QtGui
import os
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
def _fromUtf8(s):
return s
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig)
class PopulateList(QtGui.QDialog):
def __init__(self,parent=None):
super().__init__(parent)
self.ui = Ui_Form()
self.ui.setupUi(self)
self.setModel()
self.show()
self.ui.splitter.setHandleWidth(0)#not working
self.ui.listView.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
self.ui.listView.setCornerWidget(self.getCornerWidget(self.ui.splitter))
self.ui.closePushButton.clicked.connect(self.close)
self.ui.listView.clicked.connect(self.showSubFiles)
def getCornerWidget(self, splitter):
self.handle=splitter.handle(1)
layout=QtGui.QHBoxLayout(self.handle)
layout.setSpacing(0)
layout.setMargin(0)
for i in range(0,2):
line = QtGui.QFrame(self.handle)
line.setFrameShape(QtGui.QFrame.VLine)
layout.addWidget(line)
return self.handle
def showSubFiles(self, index):
root_path = self.model.fileInfo(index).absoluteFilePath()
self.model1=QtGui.QFileSystemModel()
self.model1.setRootPath(root_path)
self.ui.listView_1.setModel(self.model1)
self.ui.listView_1.setRootIndex(self.model1.index(root_path))
def setModel(self):
root_path=os.path.expanduser("~")
self.model=QtGui.QFileSystemModel()
self.model.setRootPath(root_path)
self.model.setFilter(QtCore.QDir.NoDotAndDotDot | QtCore.QDir.Dirs)
self.ui.listView.setModel(self.model)
self.ui.listView.setRootIndex(self.model.index(root_path))
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName(_fromUtf8("Form"))
Form.resize(602, 365)
self.verticalLayout = QtGui.QVBoxLayout(Form)
self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))
self.splitter = QtGui.QSplitter(Form)
self.splitter.setOrientation(QtCore.Qt.Horizontal)
self.splitter.setObjectName(_fromUtf8("splitter"))
self.listView = QtGui.QListView(self.splitter)
self.listView.setObjectName(_fromUtf8("listView"))
self.listView_1 = QtGui.QListView(self.splitter)
self.listView_1.setObjectName(_fromUtf8("listView_1"))
self.verticalLayout.addWidget(self.splitter)
self.horizontalLayout = QtGui.QHBoxLayout()
self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout"))
spacerItem = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
self.horizontalLayout.addItem(spacerItem)
self.closePushButton = QtGui.QPushButton(Form)
self.closePushButton.setObjectName(_fromUtf8("closePushButton"))
self.horizontalLayout.addWidget(self.closePushButton)
self.verticalLayout.addLayout(self.horizontalLayout)
self.verticalLayout.setStretch(0, 1)
self.retranslateUi(Form)
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
Form.setWindowTitle(_translate("Form", "Form", None))
self.closePushButton.setText(_translate("Form", "Close", None))
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
listView=PopulateList()
sys.exit(app.exec_())
Are you able to use QColumnView? It is exactly this.
http://doc.qt.io/qt-5/qcolumnview.html
import sys
from PyQt5 import QtWidgets, QtCore
app = QtWidgets.QApplication(sys.argv)
model = QtWidgets.QFileSystemModel()
view = QtWidgets.QColumnView()
view.setModel(model)
model.setRootPath("/")
view.show()
sys.exit(app.exec())

catch link clicks in QtWebView and open in default browser

I am opening a page in QtWebView (in PyQt if that matters) and I want to open all links in the system default browser. I.e. a click on a link should not change the site in the QtWebView but it should open it with the default browser. I want to make it impossible to the user to change the site in the QtWebView.
How can I do that?
Thanks,
Albert
That does it:
import sys, webbrowser
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from PyQt4.QtWebKit import *
app = QApplication(sys.argv)
web = QWebView()
web.load(QUrl("http://www.az2000.de/projects/javascript-project/"))
web.page().setLinkDelegationPolicy(QWebPage.DelegateAllLinks)
def linkClicked(url): webbrowser.open(str(url.toString()))
web.connect(web, SIGNAL("linkClicked (const QUrl&)"), linkClicked)
web.show()
sys.exit(app.exec_())
Updated example for PyQt5 (the magic is to re-implement the "acceptNavigationRequest" method):
from PyQt5 import QtWidgets, QtCore, QtGui, QtWebEngineWidgets
class RestrictedQWebEnginePage(QtWebEngineWidgets.QWebEnginePage):
""" Filters links so that users cannot just navigate to any page on the web,
but just to those pages, that are listed in allowed_pages.
This is achieved by re-implementing acceptNavigationRequest.
The latter could also be adapted to accept, e.g. URLs within a domain."""
def __init__(self, parent=None):
super().__init__(parent)
self.allowed_pages = []
def acceptNavigationRequest(self, qurl, navtype, mainframe):
# print("Navigation Request intercepted:", qurl)
if qurl in self.allowed_pages: # open in QWebEngineView
return True
else: # delegate link to default browser
QtGui.QDesktopServices.openUrl(qurl)
return False
class RestrictedWebViewWidget(QtWidgets.QWidget):
"""A QWebEngineView is required to display a QWebEnginePage."""
def __init__(self, parent=None, url=None, html_file=None):
super().__init__(parent)
self.view = QtWebEngineWidgets.QWebEngineView()
self.page = RestrictedQWebEnginePage()
if html_file:
print("Loading File:", html_file)
self.url = QtCore.QUrl.fromLocalFile(html_file)
self.page.allowed_pages.append(self.url)
self.page.load(self.url)
elif url:
print("Loading URL:", url)
self.url = QtCore.QUrl(url)
self.page.allowed_pages.append(self.url)
self.page.load(self.url)
# associate page with view
self.view.setPage(self.page)
# set layout
self.vl = QtWidgets.QVBoxLayout()
self.vl.addWidget(self.view)
self.setLayout(self.vl)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
web = RestrictedWebViewWidget(url="YOUR URL") # or YOUR local HTML file
web.show()
sys.exit(app.exec_())
When you click a link that has the target="_blank" attribute, QT calls the CreateWindow method in QWebEnginePage to create a new tab/new window.
The key is to re-implement this method to, instead of opening a new tab, open a new browser window.
class WebEnginePage(QtWebEngineWidgets.QWebEnginePage):
def createWindow(self, _type):
page = WebEnginePage(self)
page.urlChanged.connect(self.open_browser)
return page
def open_browser(self, url):
page = self.sender()
QDesktopServices.openUrl(url)
page.deleteLater()
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.url = QUrl("https://stackoverflow.com/")
self.webView = QWebEngineView()
self.page = WebEnginePage(self.webView)
self.webView.setPage(self.page)
self.webView.load(self.url)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
web = MainWindow()
web.show()
sys.exit(app.exec_())

Resources