Qpushbutton in custom QlistWidgetItem doesn't respond when running on embedded device - pyqt5

I'm quite new to pyqt5 and applications on embedded devices, and was hoping someone may have any tips or suggestions on the problems I'm facing.
I am working with a pyqt5 appliaction where the widget contains a QListWidget and two buttons. I have made a seperate widget that I use as a customized QListWidgetItem. The customized QListWidgetItem contains a textfield and a QPushButton.
Everything works perfectly on Ubuntu on my computer, but when I deploy and run the app on an embedded device, the buttons in the customized QListWidgetItem no longer responds. The "normal" buttons, that are not in the customized QListWidgetItem, still works normally.
I can't find a reason or fixes for this, and am quite stuck..
Here's my code, very simplified:
Edit! After some feedback I've created a smaller representation of the app/problem, which hopefully can make it easier to debug.
I no longer use pyqtSignal between the classes, only connected the buttons to different functions directly.
In this case, both the printing and color changing will happen if the buttons respond correctly.
python file:
import sys
from CustomListItem import Ui_custom_list_widget
from CollectorWidget import Ui_collector_widget
from PyQt5.QtWidgets import QWidget, QListWidgetItem, QApplication, QStackedWidget, QMainWindow
def main():
app = QApplication(sys.argv)
stack = QStackedWidget()
collector = CollectorWidget()
stack.addWidget(collector)
stack.setCurrentWidget(collector)
stack.show()
sys.exit(app.exec_())
class CollectorWidget(Ui_collector_widget, QWidget):
temp_list_items = []
def __init__(self, parent=None):
super(CollectorWidget, self).__init__(parent)
self.setupUi(self)
self.create_item_button.clicked.connect(self.create_item_clicked)
self.another_button.clicked.connect(lambda: print("this one works"))
def create_item_clicked(self):
self.listItem = QListWidgetItem()
self.item = CustomListItem()
self.item.custom_item_button.clicked.connect(self.test_signal)
self.qlistwidget_list.addItem(self.listItem)
self.qlistwidget_list.setItemWidget(self.listItem, self.item)
self.temp_list_items.append((self.listItem, self.item))
def test_signal(self):
print("--------------IT'S WORKING!--------------------------")
class CustomListItem(Ui_custom_list_widget, QWidget):
def __init__(self):
super().__init__()
self.setupUi(self)
self.item_name.setText("testing testing")
self.custom_item_button.clicked.connect(self.button_clicked)
def setItemText(self, text):
self.item_name.setText(text)
def button_clicked(self):
self.item_name.setStyleSheet("background-color: red;")
if __name__ == "__main__":
main()
Ui files (collector):
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'CollectorWidget.ui'
#
# Created by: PyQt5 UI code generator 5.15.6
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_collector_widget(object):
def setupUi(self, collector_widget):
collector_widget.setObjectName("collector_widget")
collector_widget.resize(625, 514)
self.verticalLayout = QtWidgets.QVBoxLayout(collector_widget)
self.verticalLayout.setObjectName("verticalLayout")
self.qlistwidget_list = QtWidgets.QListWidget(collector_widget)
self.qlistwidget_list.setObjectName("qlistwidget_list")
self.verticalLayout.addWidget(self.qlistwidget_list)
self.horizontalLayout = QtWidgets.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout")
self.create_item_button = QtWidgets.QPushButton(collector_widget)
self.create_item_button.setObjectName("create_item_button")
self.horizontalLayout.addWidget(self.create_item_button)
self.another_button = QtWidgets.QPushButton(collector_widget)
self.another_button.setObjectName("another_button")
self.horizontalLayout.addWidget(self.another_button)
self.verticalLayout.addLayout(self.horizontalLayout)
self.retranslateUi(collector_widget)
QtCore.QMetaObject.connectSlotsByName(collector_widget)
def retranslateUi(self, collector_widget):
_translate = QtCore.QCoreApplication.translate
collector_widget.setWindowTitle(_translate("collector_widget", "Form"))
self.create_item_button.setText(_translate("collector_widget", "Create"))
self.another_button.setText(_translate("collector_widget", "Just a button"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
collector_widget = QtWidgets.QWidget()
ui = Ui_collector_widget()
ui.setupUi(collector_widget)
collector_widget.show()
sys.exit(app.exec_())
Ui files (custom_list_item):
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'CustomListItem.ui'
#
# Created by: PyQt5 UI code generator 5.15.6
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_custom_list_widget(object):
def setupUi(self, custom_list_widget):
custom_list_widget.setObjectName("custom_list_widget")
custom_list_widget.resize(608, 40)
self.horizontalLayout = QtWidgets.QHBoxLayout(custom_list_widget)
self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout.setSpacing(0)
self.horizontalLayout.setObjectName("horizontalLayout")
self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.item_name = QtWidgets.QLabel(custom_list_widget)
font = QtGui.QFont()
font.setKerning(True)
self.item_name.setFont(font)
self.item_name.setStyleSheet("")
self.item_name.setWordWrap(True)
self.item_name.setObjectName("item_name")
self.horizontalLayout_2.addWidget(self.item_name)
self.custom_item_button = QtWidgets.QPushButton(custom_list_widget)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.custom_item_button.sizePolicy().hasHeightForWidth())
self.custom_item_button.setSizePolicy(sizePolicy)
self.custom_item_button.setMaximumSize(QtCore.QSize(20, 20))
self.custom_item_button.setStyleSheet("")
self.custom_item_button.setText("")
self.custom_item_button.setObjectName("custom_item_button")
self.horizontalLayout_2.addWidget(self.custom_item_button)
self.horizontalLayout.addLayout(self.horizontalLayout_2)
self.retranslateUi(custom_list_widget)
QtCore.QMetaObject.connectSlotsByName(custom_list_widget)
def retranslateUi(self, custom_list_widget):
_translate = QtCore.QCoreApplication.translate
custom_list_widget.setWindowTitle(_translate("custom_list_widget", "Form"))
self.item_name.setText(_translate("custom_list_widget", "TextLabel"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
custom_list_widget = QtWidgets.QWidget()
ui = Ui_custom_list_widget()
ui.setupUi(custom_list_widget)
custom_list_widget.show()
sys.exit(app.exec_())
Picture of app:

Related

How to count lines in qscintilla?

I'm using QScintilla to make my own notepad for fun in pyqt5 python. I was wandering if there is a way to get the number of lines of a QScintilla() widget?
You have to use the lines() method, you can also use the linesChanged signal.
import sys
from PyQt5 import QtWidgets, Qsci
class Editor(Qsci.QsciScintilla):
def __init__(self, parent=None):
super().__init__(parent)
self.setText("Foo\nBar")
self.print_lines()
self.linesChanged.connect(self.handle_lines_changed)
def handle_lines_changed(self):
self.print_lines()
def print_lines(self):
print("total lines: {}".format(self.lines()))
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
w = Editor()
w.resize(640, 480)
w.show()
sys.exit(app.exec_())

Insert qtpynodeeditor in main window pyside2

I want to use node editor in pyside2, i got the library qtpynodeeditor (https://pypi.org/project/qtpynodeeditor/). I am not able to insert inside to my main window.
I am able to display separately, Left window is node editor right is main window.
MainWindow_UI.py
# -*- coding: utf-8 -*-
################################################################################
## Form generated from reading UI file 'ListViewForNodeEditor_UI.ui'
##
## Created by: Qt User Interface Compiler version 5.14.1
##
## WARNING! All changes made in this file will be lost when recompiling UI file!
################################################################################
from PySide2.QtCore import (QCoreApplication, QMetaObject, QObject, QPoint,
QRect, QSize, QUrl, Qt)
from PySide2.QtGui import (QBrush, QColor, QConicalGradient, QCursor, QFont,
QFontDatabase, QIcon, QLinearGradient, QPalette, QPainter, QPixmap,
QRadialGradient)
from PySide2.QtWidgets import *
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
if MainWindow.objectName():
MainWindow.setObjectName(u"MainWindow")
MainWindow.resize(800, 600)
self.centralwidget = QWidget(MainWindow)
self.centralwidget.setObjectName(u"centralwidget")
self.verticalLayout = QVBoxLayout(self.centralwidget)
self.verticalLayout.setObjectName(u"verticalLayout")
self.graphicsView = QGraphicsView(self.centralwidget)
self.graphicsView.setObjectName(u"graphicsView")
self.verticalLayout.addWidget(self.graphicsView)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QMenuBar(MainWindow)
self.menubar.setObjectName(u"menubar")
self.menubar.setGeometry(QRect(0, 0, 800, 21))
MainWindow.setMenuBar(self.menubar)
self.statusbar = QStatusBar(MainWindow)
self.statusbar.setObjectName(u"statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QMetaObject.connectSlotsByName(MainWindow)
# setupUi
def retranslateUi(self, MainWindow):
MainWindow.setWindowTitle(QCoreApplication.translate("MainWindow", u"MainWindow", None))
# retranslateUi
NodeEditor.py
from ListViewForNodeEditor_UI import Ui_MainWindow
from PySide2.QtGui import *
from PySide2.QtWidgets import *
from PySide2.QtCore import *
import qdarkstyle
import qtpynodeeditor as nodeeditor
class testNode(QMainWindow):
def __init__(self, parent=None):
super(testNode, self).__init__(parent)
self.Wui = Ui_MainWindow()
self.Wui.setupUi(self)
#Shows the Node Editor
registry = nodeeditor.DataModelRegistry()
scene = nodeeditor.FlowScene(registry=registry)
self.view = nodeeditor.FlowView(scene)
self.view.show()
if __name__=="__main__":
import sys
app = QApplication(sys.argv)
dark_stylesheet = qdarkstyle.load_stylesheet_pyside2()
app.setStyleSheet(dark_stylesheet)
w = testNode()
w.show()
sys.exit(app.exec_())
any alternative node editor for pyside2 much appreciated.
You are showing the FlowView as a separate widget.
If you change the line
self.view.show()
to
self.Wui.verticalLayout.addWidget(self.view)
the FlowView will be added to your layout. See the Qt layout documentation for more information and examples.

PyQt5 Signal Between Classes Causing Lockup

I'm trying to send signals between classes, which works fine from the HMI class to the WorkerThread class, but causes a program lockup, or infinite loop, when WorkerThread tries to connect to a signal from the HMI class.
import sys
import time
import PyQt5
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtCore import QThread
from PyQt5.QtWidgets import QWidget, QApplication
from Home import Ui_HomeWin # PyQt5 Designer window
class WorkerThread(QThread):
hmiHandlesThis = PyQt5.QtCore.pyqtSignal(str)
def __init__(self, parent=None):
super(WorkerThread, self).__init__(parent)
self.counter = 0
# this attempted connection causes a lockup
self.HMI_Thread = HMI() # appears to be a recursive loop
self.HMI_Thread.updateGlobals.connect(self.update_global_widgets)
def run(self):
while True:
time.sleep(0.5)
print('Doing a bunch of other stuff: {}'.format(self.counter))
self.counter += 1
def build_a_command(self):
print('building a command...')
name = 'pbAutoMode'
# example command
command = name + '.setStyleSheet("QPushButton{ background-color: rgb(0, 0, 255); }")'
self.hmiHandlesThis.emit(command)
def update_global_widgets(self):
print('update some global widgets')
class HMI(QWidget):
updateGlobals = PyQt5.QtCore.pyqtSignal(name='updateGlobals')
def __init__(self, parent=None):
super(HMI, self).__init__(parent)
self.HomeWin = QtWidgets.QDialog()
self.HomeWin.setWindowFlags(QtCore.Qt.FramelessWindowHint)
ui = Ui_HomeWin()
ui.setupUi(self.HomeWin)
self.HomeWin.show()
# this connection works
self.workerThread = WorkerThread()
self.workerThread.hmiHandlesThis.connect(self.on_new_command)
self.workerThread.start()
def on_new_command(self, command):
print('New command is: {}'.format(command))
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = HMI()
sys.exit(app.exec_())~~~
I've tried placing the signal definitions inside the init functions, with no difference.
With Dennis Jensen's help, i've been able to get this running properly. I'm posting the working snippet here as an example of 'proper' thread building and the passing of signals.
import sys
import time
import PyQt5
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtCore import QObject, QThread
from PyQt5.QtWidgets import QWidget, QApplication
from Home import Ui_HomeWin # a PyQt5 Designer window
class WorkerThread(QObject):
hmiHandlesThis = PyQt5.QtCore.pyqtSignal(str, str)
def __init__(self, parent=None):
super(WorkerThread, self).__init__(parent)
self.counter = 0
def processRun(self):
while True:
time.sleep(0.5)
print('Doing a bunch of other stuff: {}'.format(self.counter))
self.counter += 1
def update_global_widgets(self):
print('update some global widgets')
def build_a_command(self):
print('building a command...')
name = 'pbAutoMode'
# example command
command = name + '.setStyleSheet("QPushButton{ background-color: rgb(0, 0, 255); }")'
self.hmiHandlesThis.emit(name, command)
class HMI(QWidget):
updateGlobals = PyQt5.QtCore.pyqtSignal(name='updateGlobals')
def __init__(self, parent=None):
super(HMI, self).__init__(parent)
self.HomeWin = QtWidgets.QDialog()
self.HomeWin.setWindowFlags(QtCore.Qt.FramelessWindowHint)
ui = Ui_HomeWin()
ui.setupUi(self.HomeWin)
self.HomeWin.show()
self.EstablishThread()
def EstablishThread(self):
# Create the Object from Class
self.Worker = WorkerThread()
# Assign the Database Signals to Slots
self.Worker.hmiHandlesThis.connect(self.on_new_command)
# Create the Thread
self.ThredHolder = QThread()
# Move the Listener to the Thread
self.Worker.moveToThread(self.ThredHolder)
# Assign the Listener Starting Function to the Thread Call
self.ThredHolder.started.connect(self.Worker.processRun)
# Start the Thread which launches Listener.Connect( )
self.ThredHolder.start()
def on_new_command(self):
print('Handling new command...')
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = HMI()
sys.exit(app.exec_())
Thanks Dennis!

pyqt5 videowidget not showing in layout

I am writing a program with pyqt5 where pressing a button first cycles through some pictures then cycles through some videos.
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtMultimedia import *
from PyQt5.QtMultimediaWidgets import *
import glob
import argparse
import sys
class MainWindow(QMainWindow):
def __init__(self,args):
super(MainWindow, self).__init__()
self.setWindowTitle('Navon test')
self.setWindowFlags(Qt.FramelessWindowHint)
# exit option for the menu bar File menu
self.exit = QAction('Exit', self)
self.exit.setShortcut('Ctrl+q')
# message for the status bar if mouse is over Exit
self.exit.setStatusTip('Exit program')
# newer connect style (PySide/PyQT 4.5 and higher)
self.exit.triggered.connect(app.quit)
self.setWindowIcon(QIcon('icon.ico'))
self.centralwidget = CentralWidget(args)
self.setCentralWidget(self.centralwidget)
def keyPressEvent(self, QKeyEvent):
if QKeyEvent.key() == Qt.Key_Escape:
QCoreApplication.instance().quit()
self.centralwidget.startvid()
class CentralWidget(QWidget):
def __init__(self,args):
super(CentralWidget, self).__init__()
self.layout = QVBoxLayout()
self.layout.setAlignment(Qt.AlignCenter)
self.setLayout(self.layout)
self.player = QMediaPlayer(None, QMediaPlayer.VideoSurface)
self.vw = QVideoWidget()
self.player.setVideoOutput(self.vw)
def startvid(self):
self.layout.addWidget(self.vw)
url= QUrl.fromLocalFile(glob.glob("videos/*")[0])
content= QMediaContent(url)
self.player.setMedia(content)
self.player.setVideoOutput(self.vw)
self.player.play()
if __name__== "__main__":
parser = argparse.ArgumentParser()
#~ parser.add_argument("-nb","--nobox",action="store_true", help="do not wait for the box connection")
args = parser.parse_args()
app = QApplication(sys.argv)
mainwindow = MainWindow(args)
#~ mainwindow.showFullScreen()
mainwindow.show()
sys.exit(app.exec_())
I tried to paste the minimal code. The thing is, I press the button nothing shows, although I used examples like this one PyQt5 - Can't play video using QVideoWidget to test if playing the video is ok, and these work. It's as if it is not adding the widget to the layout or something. Any idea what might be wrong?
I had to use QGraphicsView to achieve what I wanted, here is a fix:
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtMultimedia import *
from PyQt5.QtMultimediaWidgets import *
import glob
class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.setWindowTitle('Navon test')
self.setWindowFlags(Qt.FramelessWindowHint)
# exit option for the menu bar File menu
self.exit = QAction('Exit', self)
self.exit.setShortcut('Ctrl+q')
# message for the status bar if mouse is over Exit
self.exit.setStatusTip('Exit program')
# newer connect style (PySide/PyQT 4.5 and higher)
self.exit.triggered.connect(app.quit)
self.setWindowIcon(QIcon('icon.ico'))
self.centralwidget = VideoPlayer()
self.setCentralWidget(self.centralwidget)
def keyPressEvent(self, QKeyEvent):
if QKeyEvent.key() == Qt.Key_Escape:
self.centralwidget.phaseQuit(2)
self.centralwidget.play()
class VideoPlayer(QWidget):
def __init__(self, parent=None):
super(VideoPlayer, self).__init__(parent)
self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface)
self.videoItem = QGraphicsVideoItem()
self.videoItem.setSize(QSizeF(640, 480))
scene = QGraphicsScene(self)
graphicsView = QGraphicsView(scene)
scene.addItem(self.videoItem)
layout = QVBoxLayout()
layout.addWidget(graphicsView)
self.setLayout(layout)
self.mediaPlayer.setVideoOutput(self.videoItem)
self.counter = 0
def play(self):
if self.mediaPlayer.state() == QMediaPlayer.PlayingState:
pass
else:
self.mediaPlayer.setMedia(QMediaContent(QUrl.fromLocalFile(glob.glob("videos/*")[self.counter])))
self.mediaPlayer.play()
self.counter += 1
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
player = MainWindow()
player.show()
sys.exit(app.exec_())

Access untranslated string in PyQt?

I am writing a little pyqt application. Now I have start using Qtranslator with *.ts and *.qm files to get a Swedish translation.
I use e.g. self.tr(“Test this”) “Swedish Testar detta”. I am wondering while using the Swedish translation, if it is possible to get back the original untranslated string, in this case “Test this” in the program?
This i my little program and I want the "translate_string" method to print the original string.
from PyQt5.QtWidgets import (QApplication, QDialog, QPushButton, QVBoxLayout)
import sys
from PyQt5.QtCore import (QTranslator)
class Form(QDialog):
def __init__(self):
super(Form, self).__init__()
button = QPushButton(self.tr("&Close"))
self.test_lang = QPushButton(self.tr("Translate"))
self.string = self.tr("Test this")
layout = QVBoxLayout()
layout.addWidget(self.test_lang)
layout.addWidget(button)
self.setLayout(layout)
self.test_lang.clicked.connect(self.translate_string)
button.clicked.connect(self.close)
def translate_string(self):
print(self.string)
if __name__ == '__main__':
app = QApplication(sys.argv)
translator = QTranslator()
translator.load("test_trans_sv_SE.qm")
app.installTranslator(translator)
form = Form()
form.show()
sys.exit(app.exec_())