PyQt5 QGraphicsView object has no attribute 'resetMatrix'? - python

Consider this PyQT5 example, let's call it test.py (for me, behaves the same under both python2 and python3 on Ubuntu 18.04):
#!/usr/bin/env python
from __future__ import print_function
import sys, os
from PyQt5 import QtCore, QtWidgets, QtGui
class PhotoViewer(QtWidgets.QGraphicsView):
def __init__(self, parent):
super(PhotoViewer, self).__init__(parent)
self.parent = parent
#self.resetMatrix() # SO: 39101834, but "AttributeError: 'PhotoViewer' object has no attribute 'resetMatrix'"
self.scale(1.0, 1.0)
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
QtWidgets.QMainWindow.__init__(self)
self.setWindowTitle("test.py")
self.setMinimumWidth(1000)
self.setMinimumHeight(600)
self.viewer = PhotoViewer(self)
wid = QtWidgets.QWidget(self)
self.setCentralWidget(wid)
VBlayout = QtWidgets.QVBoxLayout()
VBlayout.addWidget(self.viewer)
wid.setLayout(VBlayout)
if __name__ == "__main__":
app = QtWidgets.QApplication([])
main = MainWindow()
main.show()
sys.exit(app.exec_())
If I run it as is, it runs fine, without a problem.
If I uncomment the commented self.resetMatrix() line, then the program fails with:
$ python test.py
Traceback (most recent call last):
File "test.py", line 29, in <module>
main = MainWindow()
File "test.py", line 20, in __init__
self.viewer = PhotoViewer(self)
File "test.py", line 11, in __init__
self.resetMatrix() # SO: 39101834, but "AttributeError: 'PhotoViewer' object has no attribute 'resetMatrix'"
AttributeError: 'PhotoViewer' object has no attribute 'resetMatrix'
But this I find rather bizarre, because PhotoViewer inherits from QGraphicsView, calling PhotoViewer.scale() which is a QGraphicsView method is clearly not a problem - and How to reset the scale in QGraphicsView? documents that calling QGraphicsView()->resetMatrix() should be possible, and also it is documented for both:
http://pyqt.sourceforge.net/Docs/PyQt4/qgraphicsview.html#resetMatrix
http://pyqt.sourceforge.net/Docs/PyQt5/api/QtWidgets/qgraphicsview.html -> "The C++ documentation can be found here." -> https://doc.qt.io/qt-5/qgraphicsview.html#resetMatrix
What is the mistake I'm making - why cannot I call resetMatrix in this case; and what should I do to be able to call this function?

It seems that it is a bug of PyQt5, I have tested it with PySide2 and it works correctly. But there is a workaround, if you check the source code you see that the the resetMatrix() method calls only resetTransform() so it uses that method.
class PhotoViewer(QtWidgets.QGraphicsView):
def __init__(self, parent):
super(PhotoViewer, self).__init__(parent)
self.parent = parent
self.resetTransform() # self.resetMatrix()
self.scale(1.0, 1.0)

Related

Type Error: QApplication(List[str]): not enough arguments

Disclaimer: I am relatively new to programming, and especially new to Python.
I am trying to learn to build a GUI with PyQt5 and I keep receiving the error "Type Error: QApplication(List[str]): not enough arguments" when trying to launch my application... I don't see any arguments that would make sense to use, and the ones that I have tried(that would be valid) then cause it to say " module.init() takes at most 2 arguments (3 given)"
import sys
from PyQt5 import QtWidgets, QtGui
class Main(QtWidgets.QApplication):
def __init__(self):
super(Main, self).__init__()
self.setGeometry(100, 100, 300, 500)
self.setWindowTitle('HelloWorld')
self.setWindowIcon(QtWidget.QIcon('Image.png'))
self.show()
app = QtWidgets.QApplication(sys.argv)
gui = Main()
sys.exit(app.exec_())
Viewing your code I noticed that you are confusing QApplication with some Widget.
The QApplication class manages the GUI application's control flow
and main settings. It's Not a Widget.
In your case you could use a widget, for example:
import sys
from PyQt5 import QtWidgets, QtGui
class Main(QtWidgets.QWidget):
def __init__(self):
super(Main, self).__init__()
self.setGeometry(100, 100, 300, 500)
self.setWindowTitle('HelloWorld')
self.setWindowIcon(QtGui.QIcon('Image.png'))
self.show()
app = QtWidgets.QApplication(sys.argv)
gui = Main()
sys.exit(app.exec_())
Note: I have changed self.setWindowIcon(QtWidget.QIcon('Image.png')) to self.setWindowIcon(QtGui.QIcon('Image.png'))
QtWidgets.QApplication.__init__() requires at the very least a list of arguments to be passed to it when starting. My guess is that your code fails when you try to initialize your own Main class that calls QtWidgets.QApplication init. Try:
class Main(QtWidgets.QApplication):
def __init__(self, *args, **kwargs): # allow it to receive any number of arguments
super(Main, self).__init__(*args, **kwargs) # forward to 'super' __init__()
# etc.
# when initializing:
gui = Main(sys.argv)

Python program works, but it shows an error. Why?

I am new in programming and I have done my research on this website and others, but I can't find anything helpful for my problem. I am writing a Python program with several PyQt windows opening when different buttons are pressed. This is my program:
import sys, os,
from PyQt4 import QtCore, QtGui, uic
Ui_IntroWindow = uic.loadUiType('introduction.ui')[0]
Ui_ElmWindow = uic.loadUiType('elm.ui')[0]
Ui_ClueWindow = uic.loadUiType('pistaelm.ui') [0]
Ui_ButtonWindow = uic.loadUiType('firtsguibutton.ui')[0]
class IntroWindow(QtGui.QMainWindow, Ui_IntroWindow):
def __init__ (self, parent=None):
QtGui.QMainWindow.__init__(self, parent)
self.setupUi(self)
self.continuar.clicked.connect(self.continuar_clicked)
def continuar_clicked(self):
window = ElmWindow(self)
window.show()
window.exec_()
self.close()
class ElmWindow(QtGui.QMainWindow, Ui_ElmWindow):
def __init__(self, parent=None):
QtGui.QMainWindow.__init__(self, parent)
self.setupUi(self)
self.bpista.clicked.connect(self.pista)
self.bcontinuar.clicked.connect(self.continuar)
def pista(self):
pistaelm = ClueWindow(self)
pistaelm.show()
pistaelm.exec_()
def continuar(self):
elemento = str(self.elemento.text())
main = ButtonWindow(self)
if elemento == 'cobalto':
main.show()
main.exec_()
self.close()
class ClueWindow(QtGui.QMainWindow, Ui_ClueWindow):
def __init__ (self, parent=None):
QtGui.QMainWindow.__init__(self, parent)
self.setupUi(self)
class ButtonWindow(QtGui.QMainWindow, Ui_ButtonWindow):
def __init__(self, parent = None):
QtGui.QMainWindow.__init__(self, parent)
self.setupUi(self)
app = QtGui.QApplication(sys.argv)
myWindow = IntroWindow()
myWindow.show()
app.exec_()
I have several sub windows created, for example in:
def continuar_clicked(self):
window = ElmWindow(self)
window.show()
window.exec_()
self.close()
If i don't write
window.exec_()
the window will open, but the buttons won't work. But when i write it I get an error:
Traceback (most recent call last):
File "C:\Users\Work\Desktop\Project\project.py", line 19, in continuar_clicked
window.exec_()
AttributeError: 'ElmWindow' object has no attribute 'exec_'
How can I stop the error?
Objects derived from QMainWindow do not have a method exec_(). This is why you see the exception.
The reason this exception is modifying the behaviour of your program is because when an exception is raised, the rest of the slot currently being executed is not run. So your continuar_clicked method runs until it hits the line with the missing method, and stops.
This points to the fact that not calling self.close() in continuar_clicked keeps your GUI working. Calling self.close() is apparently breaking the program.
SO what does this mean? Well it points to a bad object hierarchy. You are spawning new windows, that are children of an existing window, and then closing the parent window. Quite possibly the parent window is being deleted, depending on whether the Qt.WA_DeleteOnClose attribute is set to true for your windows.
So I would suggest redesigning your program. Perhaps have a parent window that is always open, or write a window managing class which handles the creation/closing of all windows (eg a window object calls a method from your window managing object to close the current window and open a new window).
Ultimately how you structure your code will be up to you as it is difficult to gauge the details of your program from a minimal example

Can't seem to call a custom dialog from the mainWindow. PySide

I need to call a form(custom dialog designed with QtDesigner) through the slot of a button on the Main Window(also on QtDesigned, hence seperate file). Below is the relevant code:
def __init__(self, parent = None):
super(MainWindow, self).__init__(parent)
self.setupUi(self)
self.btn.clicked.connect(self.my_func)
def my_func(self):
form = Form_UI.Custom_Dialog()
if form.exec_():
print "successfully opened"
How ever I get the following error:
Traceback (most recent call last):
File "F:\myPath\code.py", line 27, in my_func
if form.exec_():
AttributeError: 'Custom_Dialog' object has no attribute 'exec_'
I don't understand, because the following code(using built-in Dialog) works just fine:
def __init__(self, parent = None):
super(MainWindow, self).__init__(parent)
self.setupUi(self)
self.btn.clicked.connect(self.my_func)
def my_func(self):
form = QtGui.QDialog()
if form.exec_():
print "successfully opened"
Any help would be appreciated. Thanks in advance.
The class generated by pyuic4 does not derive from QDialog, so if you don't write a python class for that ui file as you did for the main window, you need to create a QDialog object and a ui class object:
def my_func(self):
form = QtGui.QDialog()
ui_form = Form_UI.Custom_Dialog()
ui_form.setupUi(form)
if form.exec_():
print "successfully opened"

Difficulty with inheritance in PyQt

I'm trying to run an example from the book "Rapid GUI Programming with Python and QT" and I'm getting an error message.
import sys
from math import *
from PyQt4.QtCore import *
from PyQt4.QtGui import *
class Form(QDialog):
def __init__(self,parent = None):
super(Form,self).__init__(parent)
self.browser = QTextBrowser()
self.lineedit = QLineEdit("Type an Expression and press enter")
self.lineedit.selectAll()
layout = QBoxLayout()
layout.addWidget(self.browser)
layout.addWidget(self.lineedit)
self.setLayout(layout)
self.lineedit.setFocus()
self.connect(self.lineedit, SIGNAL("returnPressed()"),self.UpdateGUI)
self.setWindowTitle("Ryans App")
def UpdateGUI(self):
try
text = self.lineedit.text()
self.browser.append("%s = <b>%s</b>" % (text,eval(text)))
except:
self.browser.append("<font color=red>%s is Invalid!</font>" % text )
app = QApplication(sys.argv)
form = Form()
form.show()
app.exec_()
The trace I'm getting is:
Traceback (most recent call last):
File "C:\Users\MyName\workspaces\LearningProject\src\LearningModule.py", line 33, in <module>
form = Form()
File "C:\Users\MyName\workspaces\LearningProject\src\LearningModule.py", line 16, in __init__
layout = QBoxLayout()
TypeError: QBoxLayout(QBoxLayout.Direction, QWidget parent=None): not enough arguments
I'm confused as to why it's requiring an argument to create the Form object as I'm just trying to inherit from QDialog... am I missing a subtlety in the syntax?
The version I have uses QVBoxLayout instead:
...
self.lineedit.selectAll()
layout = QVBoxLayout()
layout.addWidget(self.browser)
...
My understanding is that since it lines the widgets up vertically, the .LeftToRight and parent are not strictly necessary.
I'm using the most recent code archive for python 2.6 from the book website.
When creating a QBoxLayout, you need to specify a direction (e.g. QBoxLayout.LeftToRight) and optionally a parent (in this case, self should work as the parent).
These should be added on your layout = QBoxLayout() line.

Using Python PyQT4 slots and signals in Monkey Studio

I'm writing my first GUI application using PyQT4 and the Monkey Studio ide.
I've made a dialog (mainwindow.ui) with a button that sends the signal clicked() to the MainWindow's slot slot1()
This is the MainWindow code:
from PyQt4 import uic
(Ui_MainWindow, QMainWindow) = uic.loadUiType('mainwindow.ui')
class MainWindow (QMainWindow):
"""MainWindow inherits QMainWindow"""
def __init__ (self, parent = None):
QMainWindow.__init__(self, parent)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
def __del__ (self):
self.ui = None
def slot1(self):
print "Test"
It does not work: AttributeError: 'MainWindow' object has no attribute 'slot1'
I've tried adding #pyqtSlot("") before def slot1(self), but I get this error:
NameError: name 'pyqtSlot' is not defined
I've also tried #QtCore.pyqtSignature("slot1()"), to no effect.
Turns out I also had to import from PyQt4.QtCore import *, which made me able to use #pyqtSlot().
Without the quotes, because that would throw another C++ error.

Categories