I made an joystick with qframe class and also i converted my mouse location data to -1,1 but when i try to send this location data to my mainwindow class with pyqt signal it gives an error 'pyqt signal has no attiribute emit' like this, i go to pyqtSignal class
here it is it really dont have emit function but there are many example like this on the net,does my pyqt files broken or something or is it because of absance of QObject class? How can i pass my data to other class?
Here it is my joystick class;
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from PyQt5.QtCore import QPointF, QTimer, Qt ,pyqtSignal
from PyQt5.QtGui import QPainter, QPen
from PyQt5.QtWidgets import QFrame, QApplication, QLabel
import sys
import rospy
from sensor_msgs.msg import Joy
class clock(QFrame):
def __init__(self):
super(clock,self).__init__()
self.setMinimumSize(300,300)
self.setMaximumSize(300,300)
self.x=self.width()/2
self.y=self.height()/2
self.relative_x=0
self.relative_y=0
self.signal=pyqtSignal(int)
def sub(self):
self.node=rospy.init_node("hanınamk",anonymous=True)
rospy.Subscriber('/joy',Joy,self.joyControl)
def joyControl(self,data):
self.data=data.axes
self.x=(-(self.data[0]*150)+150)
self.y=(-(self.data[1]*150)+150)
print(self.data[0],self.data[1])
self.repaint()
def paintEvent(self,event):
pen=QPen()
pen.setWidth(5)
pen.setBrush(Qt.black)
painter=QPainter(self)
painter.setPen(pen)
painter.setRenderHint(QPainter.Antialiasing)
painter.drawEllipse(self.rect())
painter_2=QPainter(self)
painter_2.setBrush(Qt.black)
painter_2.setRenderHint(QPainter.Antialiasing)
painter_2.drawEllipse(QPointF(self.x,self.y),50,50)
def mouseMoveEvent(self,e):
self.relative_x=(e.x()-150)/150.0
self.relative_y=(e.y()-150)/150.0
# print(round(self.relative_x,1),round(self.relative_y,1))
self.signal.emit(self.relative_x)
if self.relative_x**2+self.relative_y**2<1:
self.x=e.x()
self.y=e.y()
self.repaint()
def mousePressEvent(self,e):
if self.relative_x**2+self.relative_y**2<1:
self.x=e.x()
self.y=e.y()
self.repaint()
def mousePressEvent(self,e):
if self.relative_x**2+self.relative_y**2<1:
self.x=e.x()
self.y=e.y()
self.repaint()
def mouseReleaseEvent(self,e):
self.x=self.width()/2
self.y=self.height()/2
self.repaint()
if __name__=="__main__":
app=QApplication(sys.argv)
win=clock()
win.show()
sys.exit(app.exec_())
and my main class;
from PyQt5.QtCore import QRect, pyqtSignal, pyqtSlot
from PyQt5.QtGui import QMouseEvent
from PyQt5.QtWidgets import QApplication, QHBoxLayout, QLabel, QWidget
import sys
from joystick import clock
class Main(QWidget):
def __init__(self):
super(Main,self).__init__()
self.setWindowTitle('Main')
self.setMinimumSize(900,900)
self.setMaximumSize(900,900)
layout=QHBoxLayout()
layout.setGeometry(QRect(200,200,300,300))
self.joy=clock()
self.joy_2=clock()
self.setLayout(layout)
layout.addWidget(self.joy)
layout.addWidget(self.joy_2)
self.label=QLabel(self)
#pyqtSlot(int)
def on_change(self,data):
print(data)
if __name__=="__main__":
app=QApplication(sys.argv)
win=Main()
win.show()
sys.exit(app.exec_())
Make the signal a class attribute not an instance attribute:
class clock(QFrame):
signal = pyqtSignal(int)
def __init__(self):
# ...
and connect it in Main.__init__:
self.joy.signal.connect(self.on_change)
self.joy2.signal.connect(self.on_change)
Related
I'm trying to test if a shortcut is working using PyQt5 and QTest. Here is my code:
Main.py
from PyQt5.QtGui import QKeySequence
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QApplication, QPushButton
class Window(QWidget):
def __init__(self):
super().__init__()
self.more_btn = QPushButton("More")
self.more_btn.clicked.connect(self.on_clicked)
self.more_btn.setShortcut(QKeySequence.Undo)
vbox = QVBoxLayout()
vbox.addWidget(self.more_btn)
self.setLayout(vbox)
def on_clicked(self):
print("Item clicked")
test_main.py
import sys
import unittest
from PyQt5.QtGui import QKeySequence
from PyQt5.QtTest import QTest
from PyQt5.QtWidgets import QApplication
from Main import Window
class MainTestCase(unittest.TestCase):
def test_main(self):
app = QApplication(sys.argv)
form = Window()
QTest.keySequence(form, QKeySequence.Undo)
When I run test_main, item_clicked should be printed, but it doesn't. I tried to debug the program and set the breatpoint at the print("Item clicked") line, it didn't stop. It seems that QTest.keySequence didn't work. Why? How should I make it work?
An application is being created with a large number of different windows.
The bottom line is that I am trying to get from the main window (by clicking button) to the client window. There is "Back" button in the clients window, which should return the user to the main window.
Both codes are in different files. The problem occurs at the stage of pressing the "Customers" button (Process finished with exit code -1073740791 (0xC0000409)).
Moreover, if everything is in one file, then everything works fine. But only here the program is not planned to be small, so I don't want to put a huge code in one file.
Welcome_Screen.py
import sys
from PyQt5.uic import loadUi
from PyQt5 import QtWidgets, QtGui
from PyQt5.QtWidgets import QDialog, QApplication
import Customers
class WelcomeScreen(QDialog):
def __init__(self):
super(WelcomeScreen, self).__init__()
loadUi('screens/welcomescreen.ui', self)
self.CustomerData.clicked.connect(self.go_to_CustomerData)
def go_to_CustomerData(self):
client = Customers.CustomerScreen()
widget.addWidget(client)
widget.setCurrentIndex(widget.currentIndex() + 1)
# main
app = QApplication(sys.argv)
app.setWindowIcon(QtGui.QIcon('Icons/MainIcon.png'))
app.setApplicationDisplayName('Bonus Program')
welcome = WelcomeScreen()
widget = QtWidgets.QStackedWidget()
widget.addWidget(welcome)
widget.setFixedWidth(600)
widget.setFixedHeight(475)
widget.show()
try:
sys.exit(app.exec_())
except:
print("Exiting")
Customers.py
import sys
from PyQt5.uic import loadUi
from PyQt5 import QtWidgets, QtCore, QtGui
from PyQt5.QtWidgets import QDialog, QApplication, QWidget, QMessageBox, QTableWidget, QTableWidgetItem, QTableView
from PyQt5.QtSql import QSqlDatabase, QSqlTableModel, QSqlQuery
from PyQt5.QtGui import QIcon
import Welcome_Screen as ws
import sqlite3
db_path = 'Bonus_db.sqlite'
class CustomerScreen(QDialog):
def __init__(self):
super(CustomerScreen, self).__init__()
loadUi("screens/customerscreen.ui", self)
self.back_btn.setIcon(QIcon('Icons/Back.png'))
self.back_btn.setIconSize(QtCore.QSize(45, 60))
self.back_btn.clicked.connect(self.go_Back_to_WelcomeScreen)
# self.SoldTos.clicked.connect(self.gotoSoldTos)
def go_Back_to_WelcomeScreen(self):
welcome = ws.WelcomeScreen()
ws.widget.addWidget(welcome)
ws.widget.setCurrentIndex(ws.widget.currentIndex() + 1)
Customer_app = QApplication(sys.argv)
cust_window = CustomerScreen()
cust_window.show()
sys.exit(Customer_app.exec_())
Problem
I Want to Mute all sound QWebEngineView on Button click. And Also UnMute all Sound on another Button Click. I searched a lot on the internet but no one asked this type of Questions.
Code
from PyQt5.QtWebEngineWidgets import QWebEngineView, QWebEngineSettings
from PyQt5.QtCore import QUrl
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QPushButton
import sys
class Main(QWidget):
def __init__(self):
super(Main, self).__init__()
self.vbox=QVBoxLayout()
self.mutebtn=QPushButton('Mute this WebPage')
self.mutebtn.clicked.connect(self.mutebrowser)
self.vbox.addWidget(self.mutebtn)
self.unmutebtn=QPushButton('UnMute this WebPage')
self.unmutebtn.clicked.connect(self.unmutebrowser)
self.vbox.addWidget(self.unmutebtn)
self.browser=QWebEngineView()
self.browser.setUrl(QUrl('https://youtu.be/B-wmrlzdK3k'))
self.vbox.addWidget(self.browser)
self.setMinimumSize(400,500)
self.setLayout(self.vbox)
def mutebrowser(self):
# Code to Mute Sound in "self.browser"
pass
def unmutebrowser(self):
# Code to UnMute Sound in "self.browser"
pass
if __name__ == '__main__':
app=QApplication(sys.argv)
win=Main()
win.show()
sys.exit(app.exec_())
My code was created with PyQt4 and I want to convert it to PyQt5.
I have tried some scripts to convert the code; but, nothing changed except the name.
What do I need to change manually in order to make the code work with PyQt5?
Here is the first part of my code:
import sys
from pymaxwell import *
from numpy import *
from PyQt4 import QtGui, QtCore, uic
from PyQt4.QtGui import QMainWindow, QApplication
from PyQt4.QtCore import *
from PyQt4.phonon import Phonon
from ffmpy import FFmpeg
import os
import app_window_dark
import about
uifile = 'Ui/app_window_dark.ui'
aboutfile = 'Ui/about.ui'
Ui_MainWindow, QtBaseClass = uic.loadUiType(uifile)
Ui_Dialog= uic.loadUiType(uifile)
class About(QtGui.QMainWindow, about.Ui_Dialog):
def __init__(self, parent=None):
super(About, self).__init__()
QtGui.QMainWindow.__init__(self, parent)
Ui_Dialog.__init__(self)
self.setWindowModality(QtCore.Qt.ApplicationModal)
point = parent.rect().bottomRight()
global_point = parent.mapToGlobal(point)
self.move(global_point - QPoint(395, 265))
self.setupUi(self)
class MyApp(QtGui.QMainWindow, app_window_dark.Ui_MainWindow):
def __init__(self):
super(MyApp, self).__init__()
QtGui.QMainWindow.__init__(self)
self.ui = Ui_MainWindow.__init__(self)
self.setupUi(self)
self.about_btn.clicked.connect(self.popup)
#prev next
self.btn_next.clicked.connect(self.renderSet)
self.btn_prev.clicked.connect(self.renderSet)
and also this code:
if __name__ == "__main__":
app = QApplication(sys.argv)
#style = QApplication.setStyle('plastique')
window = MyApp()
window.setFixedSize(750, 320)
window.show()
sys.exit(app.exec_())
The main change from Qt4 to Qt5 and hence from PyQt4 to PyQt5 is the rearrangement of certain classes so that the Qt project is scalable and generates a smaller executable.
The QtGui library was divided into 2 submodules: QtGui and QtWidgets, in the second only the widgets, namely QMainWindow, QPushButton, etc. And that is the change you must make:
[...]
from PyQt5 import QtGui, QtCore, uic, QtWidgets
from PyQt5.QtWidgets import QMainWindow, QApplication
from PyQt5.QtCore import *
[...]
Ui_MainWindow, QtBaseClass = uic.loadUiType(uifile)
Ui_Dialog= uic.loadUiType(uifile)
class About(QtWidgets.QMainWindow, about.Ui_Dialog):
def __init__(self, parent=None):
QtWidgets.QMainWindow.__init__(self, parent)
self.setupUi(self)
self.setWindowModality(QtCore.Qt.ApplicationModal)
point = parent.rect().bottomRight()
global_point = parent.mapToGlobal(point)
self.move(global_point - QPoint(395, 265))
class MyApp(QtWidgets.QMainWindow, app_window_dark.Ui_MainWindow):
def __init__(self):
QtWidgets.QMainWindow.__init__(self)
self.setupUi(self)
self.about_btn.clicked.connect(self.popup)
#prev next
self.btn_next.clicked.connect(self.renderSet)
self.btn_prev.clicked.connect(self.renderSet)
Note: Phonon does not exist in PyQt5, you must use QtMultimedia, an accurate solution you can find it in the following answer: Phonon class not present in PyQt5
PySide2(5.6.0~a1) Qt UI file loader returns an empty window whereare PyQt5 loader works fine. Could you explained to me where I am wrong.
Non Working PySide2 version:
import sys
from PySide2.QtWidgets import QDialog, QApplication
from PySide2 import QtUiTools
class AppWindow(QDialog):
def __init__(self):
super().__init__()
self.ui = QtUiTools.QUiLoader().load("dialog1.ui")
self.show()
app = QApplication(sys.argv)
w = AppWindow()
sys.exit(app.exec_())
Working PyQt5 version:
import sys
from PyQt5.QtWidgets import QDialog, QApplication
from PyQt5 import uic
class AppWindow(QDialog):
def __init__(self):
super().__init__()
self.ui = uic.loadUi("dialog1.ui", self)
self.show()
app = QApplication(sys.argv)
w = AppWindow()
sys.exit(app.exec_())
Using this function also does not work :
def loadUiWidget(uifilename, parent=None):
loader = QtUiTools.QUiLoader()
uifile = QtCore.QFile(uifilename)
uifile.open(QtCore.QFile.ReadOnly)
ui = loader.load(uifile, parent)
uifile.close()
return ui
In PySide2 there's no function to QMainWindow class overwrite itself. It's necessary to show the ui:
import sys
from PySide2.QtWidgets import QDialog, QApplication
from PySide2 import QtUiTools
class AppWindow(QDialog):
def __init__(self):
super().__init__()
self.ui = QtUiTools.QUiLoader().load("dialog1.ui")
self.ui.show()
app = QApplication(sys.argv)
w = AppWindow()
sys.exit(app.exec_())
QUiLoader().load() returns the widget as an object so if you assign it to a variable it will not do anything, you should use show():
import sys
from PySide2.QtWidgets import QApplication
from PySide2 import QtUiTools
app = QApplication(sys.argv)
w = QtUiTools.QUiLoader().load("dialog1.ui")
w.show()
sys.exit(app.exec_())
If you want to load QMainWindow from designer *.ui file you can use
import sys
from PySide2.QtWidgets import QApplication, QMainWindow
from PySide2.QtUiTools import QUiLoader
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setCentralWidget(QUiLoader().load("form.ui"))
but slot-signal bindings, which are set in the designer in *.ui file, are not working anyway.
So, for full-function use of designer GUI and slot-signal bindings, the only way I found is to compile *.ui file to python module with pyside UI compiler:
pyside2-uic mainwindow.ui > ui_mainwindow.py
and then include produced ui_mainwindow. In this method the slot-signal pairs from Qt UI designer will work well.
import sys
from PySide2.QtWidgets import QApplication, QMainWindow
from ui_mainwindow import Ui_MainWindow
class MainWindow(QMainWindow, Ui_MainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.setupUi(self)