How to import __feature__ of PySide6? - qt

from PySide6.__feature__ import snake_case, true_property
from PySide6.QtWidgets import QMainWindow, QWidget, QHBoxLayout, QApplication
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.main_layout = QHBoxLayout()
self.container = QWidget()
self.container.set_layout(self.main_layout)
if __name__ == '__main__':
app = QApplication([])
main_window = MainWindow()
main_window.show()
app.exec()
I got an error message when trying to run the above code:
ModuleNotFoundError: No module named 'PySide6.__feature__'
If I break the first line into
import PySide6
from __feature__ import snake_case, true_property
the code could run but PyCharm complains that
Unresolved reference: __feature__
How could I fix it?
Thanks for your help.

Related

PyInstaller - AttributeError: 'ApplicationLogin' object has no attribute 'img_location'

I created a Windows .exe file from a python script using PyInstaller but when I launch the executable I get the error: AttributeError: 'ApplicationLogin' object has no attribute 'img_location'. However, running the same script from the terminal it works without issues.
Below is the piece of the code where the error is detected. The python version I used is 3.9.10
import os
from PyQt5.QtWidgets import QWidget, QDialog, QMessageBox
from PyQt5.QtCore import pyqtSignal
from PyQt5.QtGui import QPixmap
from preventivo_config_file import Preventivo_Config
from password_edit import PasswordEdit
from gestione_utenti import UserMng
from menu_preventivo import PreventivoMenu
from preventivo_login_dialogUi import Ui_f_login_dialog
class ApplicationLogin(QDialog, Ui_f_login_dialog):
closed = pyqtSignal()
login = pyqtSignal()
def __init__(self):
super(ApplicationLogin, self).__init__()
self.read_configFile()
self.setup_login()
def read_configFile(self):
prev_config=Preventivo_Config("preventivo_config")
parametri=prev_config.preventivo_config_records()
if not parametri:
return
self.img_location=parametri['images']
self.icons_location=parametri['icons']
def setup_login(self):
self.setupUi(self)
pixmap = self.caricamento_immagini("mx1.png")
I tried to look on the web for similar issue but I didn't find any hint

Qt: QMediaPlayer.setSource() was blocking the GUI so I moved it to a separate thread; am I doing this right?

Running this code:
from PySide6 import QtWidgets as qtw
from PySide6 import QtMultimedia as qtm
from PySide6 import QtMultimediaWidgets as qtmw
from PySide6 import QtCore as qtc
app = qtw.QApplication()
path = "video.mp4"
video_widget = qtmw.QVideoWidget()
video_widget.show()
media_player = qtm.QMediaPlayer()
media_player.setVideoOutput(video_widget)
media_player.mediaStatusChanged.connect(media_player.play)
media_player.setSource(path)
qtc.QTimer.singleShot(2000, lambda: media_player.setSource(''))
app.exec()
, you will notice that when media_player.setSource('') is called after 2000 milliseconds, the GUI becomes unresponsive for a good second or so. And it seems like it is not possible to move only the setSource() call to a separate thread, I get a warning saying QObject::killTimer: Timers cannot be stopped from another thread (you can replicate this by replacing qtc.QTimer... call with qtc.QThreadPool.globalInstance().start(lambda: media_player.setSource(''))). So, after hours of pondering, as a work around, I moved the entire QMediaPlayer instance and all objects related to it to a thread of its own and used QVideoSink's videoFrameChanged signal to update the video on the video widget:
from PySide6 import QtWidgets as qtw
from PySide6 import QtMultimedia as qtm
from PySide6 import QtMultimediaWidgets as qtmw
from PySide6 import QtCore as qtc
path = "video.mp4"
class VideoPlayer(qtmw.QVideoWidget):
_stop_worker_signal = qtc.Signal()
_initialize_media_player_signal = qtc.Signal()
_set_media_source_signal = qtc.Signal(str)
_play_media_signal = qtc.Signal()
_stop_media_signal = qtc.Signal()
_pause_media_signal = qtc.Signal()
def __init__(self) -> None:
super().__init__()
self._worker = Worker()
self._worker_thread = qtc.QThread()
self._worker.moveToThread(self._worker_thread)
self._stop_worker_signal.connect(self._worker.stop)
self._initialize_media_player_signal.connect(self._worker.create_media_player)
self._worker.video_sink_frame_changed_signal.connect(lambda frame: self.videoSink().setVideoFrame(frame))
self._set_media_source_signal.connect(self._worker.set_media_source)
self._stop_media_signal.connect(self._worker.stop_media)
self._worker_thread.start()
self._initialize_media_player_signal.emit()
self._set_media_source_signal.emit(path)
self.show()
def keyPressEvent(self, event):
if event.key() == qtc.Qt.Key.Key_Q:
self._set_media_source_signal.emit('')
def closeEvent(self, event: qtc.QEvent):
loop = qtc.QEventLoop()
self._worker.stopped_signal.connect(loop.exit)
self._stop_worker_signal.emit()
loop.exec()
self._worker_thread.exit()
class Worker(qtc.QObject):
video_sink_frame_changed_signal = qtc.Signal(qtm.QVideoFrame)
stopped_signal = qtc.Signal()
def create_media_player(self):
self._audio_output = qtm.QAudioOutput(qtm.QMediaDevices.defaultAudioOutput())
self._video_sink = qtm.QVideoSink()
self._video_sink.videoFrameChanged.connect(self.video_sink_frame_changed_signal)
self._media_player = qtm.QMediaPlayer()
self._media_player.setAudioOutput(self._audio_output)
self._media_player.setVideoSink(self._video_sink)
self._media_player.mediaStatusChanged.connect(self._media_player.play)
def set_media_source(self, source: str) -> None:
self._media_player.setSource(source)
def stop_media(self) -> None:
if not self._media_player.playbackState() == qtm.QMediaPlayer.PlaybackState.StoppedState:
self._media_player.stop()
def stop(self):
self._media_player.stop()
self._audio_output.deleteLater()
self._video_sink.deleteLater()
self._media_player.deleteLater()
self.stopped_signal.emit()
app = qtw.QApplication()
vp = VideoPlayer()
app.exec()
Now, there's no unresponsiveness in the GUI when setSource() is called but, as one can see, it's a pretty convoluted way to do this. Is there a better way?

how to set the QDockWidget Group color?

The picture bellow is a pyside6 application's capture, I move all QDockWidget into a single group, but the group's header's background has two different color. How to change them into a single color(qss or code)? Thanks very much!
Environment:
macos 11.6.5
python 3.9.12
pyside6 6.3.1
Reproduction Code:
# coding: utf-8
import sys
import platform
from PySide6.QtWidgets import QApplication, QMainWindow, QDockWidget, QTextEdit
from PySide6.QtCore import Qt, QSysInfo
def main():
app: QApplication = QApplication(sys.argv)
window = QMainWindow()
dock1 = QDockWidget("dock1")
dock2 = QDockWidget("dock2")
for dock in [dock1, dock2]:
dock.setFeatures(dock.DockWidgetFloatable | dock.DockWidgetMovable)
window.addDockWidget(Qt.LeftDockWidgetArea, dock1)
window.addDockWidget(Qt.RightDockWidgetArea, dock2)
os_info = QTextEdit()
os_info.setText(platform.version())
dock1.setWidget(os_info)
qt_info = QTextEdit()
info = QSysInfo()
qt_info.setText(f"{info.kernelVersion()}, {info.prettyProductName()}, {info.productVersion()}")
dock2.setWidget(qt_info)
window.show()
app.exec()
if __name__ == '__main__':
main()
I have solve it with the signal method myself:
# coding: utf-8
import sys
import platform
from PySide6.QtWidgets import QApplication, QMainWindow, QDockWidget, QTextEdit, QTabBar
from PySide6.QtCore import Qt, QSysInfo
def main():
app: QApplication = QApplication(sys.argv)
window = QMainWindow()
dock1 = QDockWidget("dock1")
dock2 = QDockWidget("dock2")
for dock in [dock1, dock2]:
dock.setFeatures(dock.DockWidgetFloatable | dock.DockWidgetMovable)
window.addDockWidget(Qt.LeftDockWidgetArea, dock1)
window.addDockWidget(Qt.RightDockWidgetArea, dock2)
os_info = QTextEdit()
os_info.setText(platform.version())
dock1.setWidget(os_info)
qt_info = QTextEdit()
info = QSysInfo()
qt_info.setText(f"{info.kernelVersion()}, {info.prettyProductName()}, {info.productVersion()}")
dock2.setWidget(qt_info)
style = """
QTabBar {
background-color: #ff0000;
}
"""
app.setStyleSheet(style)
# force update theme on dock change
for w in window.children():
if isinstance(w, QDockWidget):
w.dockLocationChanged.connect(lambda: app.setStyleSheet(style))
window.show()
app.exec()
if __name__ == '__main__':
main()

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_())

Native Qt signal is not callable in PyCharm

I created a QMainWindow with menu and tools :
import sys
from PyQt4 import QtGui
class Example(QtGui.QMainWindow):
def __init__(self):
super(Example, self).__init__()
self.initUI()
Then, I created a quit action by shortcut :
def initUI(self):
exitaction=QtGui.QAction(QtGui.QIcon('exit.png'),'&Exit',self)
exitaction.setShortcut('Ctrl+Q')
exitaction.setStatusTip('EXIT application')
Now : pycharm tells me it can't find reference qApp in __init__.py :
exitaction.triggered().connect(QtGui.qApp.quit)
self.statusBar()
menubar=self.menuBar()
fileMenu=menubar.addMenu('&File')
fileMenu.addAction(exitaction)
self.setGeometry(300,300,250,150)
self.setWindowTitle('Menubar')
self.show()
def main():
app=QtGui.QApplication(sys.argv)
ex=Example()
sys.exit(app.exec_())
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
Try to use QApplication istead of QtGui.qapp:
exitaction.triggered().connect(QApplication.instance().quit)
Compare the answer to: calling quit() method of QApplication

Resources