It would be helpful somebody run this code for me as a sanity check.
Python 3.3.1 (default, Apr 17 2013, 22:30:32)
[GCC 4.7.3] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>from PyQt5.QtCore import pyqtSignal
>>>for i in dir(pyqtSignal):
... if i == 'emit':
... print(True)
...
>>>
Is true returned for anyone else? Note that with a QObject import from PyQt4:
>>> from PyQt4.QtCore import QObject
>>> for i in dir(QObject):
... if i == 'emit':
... print(True)
...
True
pyqtSignal is not a signal, it is a factory function for creating signals, so of course it doesn't have a emit attribute. It just returns a descriptor, which when bound to a QObject instance will return the actual signal object. That means only a bound signal will have an emit method.
The QObject.emit method is a relic from times before new style signals were introduced in pyqt, and now has been removed. Just use the emit method on the bound signal to emit it:
class SomeObject(QObject):
someSignal = pyqtSignal(...)
instance = SomeObject()
instance.someSignal.emit(value)
Related
I'm trying to use instances of QGraphicsItem such as QGraphicsRectItem in a QGraphicsLayout. My understanding from the example here is that I should define a class that inherits from both QGraphicsRectItem and QGraphicsLayout. If I try to do that then scene.addItem(rect) causes a segmentation fault, but reversing the order of QGraphicsLayoutItem and QGraphicsRectItem in the class definition fixes it. This however leads to the same issue when I try to add an instance of this class to a QGraphicsLayout. Does it only recognize the inheritance from the first class listed? Do I have to use a different approach due to limitations in Python? If so, what would that approach be?
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import sys
class MyRectItem(QGraphicsLayoutItem, QGraphicsRectItem):
pass
app = QApplication([])
rect = MyRectItem()
scene = QGraphicsScene()
scene.addItem(rect)
graphics_view = QGraphicsView(scene)
graphics_view.show()
sys.exit(app.exec_())
I have this code:
from abc import ABCMeta, abstractmethod
class Instruction (object):
__metaclass__ = ABCMeta
def __init__(self, identifier_byte):
#type: (int) ->
self.identifier_byte = identifier_byte
#abstractmethod
def process (self):
print ("Identifier byte: ()".format(self.identifier_byte))
class LDAInstruction (Instruction):
def process (self):
super(Instruction,self).process()
with works fine with Python 3.2 but not with 2.6. Then based on this topic: TypeError: super() takes at least 1 argument (0 given) error is specific to any python version?
I changed the last line to:
super(Instruction,self).process()
which causes this error message on this precise line:
AttributeError: 'super' object has no attribute 'process'
For me it seems that there is a "process" method for the super invocation. Is Python saying that "super" is an independent object, unrelated to instruction? If yes, how can I tell it that super shall only invoke the base class constructor?
If not, how I shall proceed? Thanks for any ideas.
You're passing the wrong class to super in your call. You need to pass the class you're making the call from, not the base class. Change it to this and it should work:
super(LDAInstruction, self).process()
It's unrelated to your main error, but I'd further note that the base-class implementation of process probably has an error with its attempt at string formatting. You probably want {0} instead of () in the format string. In Python 2.7 and later, you could omit the 0, and just use {}, but for Python 2.6 you have to be explicit.
I wrote a simple class for notifying user using tray balloon message. Here is the code:
# -*- coding: utf8 -*-
import sys
import time
from PyQt4 import QtGui
class TrayInformer():
def __init__(self, icon_file):
self.app = QtGui.QApplication(sys.argv)
self.app.setQuitOnLastWindowClosed(False)
self.tray_icon = QtGui.QSystemTrayIcon(
QtGui.QIcon(icon_file)
)
def notify(self, title, message, wait_time=1000):
self.tray_icon.show()
self.tray_icon.showMessage(title, message)
time.sleep(wait_time / 1000)
self.tray_icon.hide()
inf = TrayInformer('timeico.ico')
inf.notify('Error', 'Connection refused', 5000)
inf.notify('test', 'test', 500)
After running it I sometimes get: Process finished with exit code -1073741819 (0xC0000005). What could be the problem?
Try to instantiate QSystemTrayIcon with parent specified. I've had resembling random crashes on exit, and surprisingly tray icon appeared to cause the problem
<...> the problem is probably the random order in which C++
instances get destroyed. Explicitly del'ing a object, or giving it an appropriate parent is the best way to deal with it.
QSystemTrayIcon still crashed app (PyQt4 4.9.1)
In my PyQt4-based program, QSliders (with signals sliderMoved and sliderReleased connected to callables) sometimes "freeze", i.e. they don't move anymore when trying to drag them with the mouse, even though sliderMoved and sliderReleased are still emitted.
This behaviour happens seemingly randomly, sometimes after running the program for hours -- making it more or less impossible to reproduce and test.
Any help to solve this issue would be welcome.
EDIT: This is with PyQt 4.10.4 on Python 3.4 and Windows 7.
After some debugging I am pretty sure that this was due to calling a GUI slot from a separate thread, which (I knew) is forbidden. Fixing this to use a proper signal-slot approach seems to have fixed the issue.
After calling the patch function defined below, all slot calls are wrapped by a wrapper that checks that they are called only from the GUI thread -- a warning is printed otherwise. This is how I found the culprit.
import functools
import sys
import threading
import traceback
from PyQt4.QtCore import QMetaMethod
from PyQt4.QtGui import QWidget
SLOT_CACHE = {}
def patch():
"""Check for calls to widget slots outside of the main thread.
"""
qwidget_getattribute = QWidget.__getattribute__
def getattribute(obj, name):
attr = qwidget_getattribute(obj, name)
if type(obj) not in SLOT_CACHE:
meta = qwidget_getattribute(obj, "metaObject")()
SLOT_CACHE[type(obj)] = [
method.signature().split("(", 1)[0]
for method in map(meta.method, range(meta.methodCount()))
if method.methodType() == QMetaMethod.Slot]
if (isinstance(attr, type(print)) and # Wrap builtin functions only.
attr.__name__ in SLOT_CACHE[type(obj)]):
#functools.wraps(
attr, assigned=functools.WRAPPER_ASSIGNMENTS + ("__self__",))
def wrapper(*args, **kwargs):
if threading.current_thread() is not threading.main_thread():
print("{}.{} was called out of main thread:".format(
type(obj), name), file=sys.stderr)
traceback.print_stack()
return attr(*args, **kwargs)
return wrapper
else:
return attr
QWidget.__getattribute__ = getattribute
I am having difficulty connecting a signal with a method in PyQt4.
I can connect a bound signal of object A with a method of object B,
but I can't connect a bound signal of object A with a method of self
(object where the connections are made.)
What am I doing wrong? See below:
from PyQt4.QtGui import *
from PyQt4.QtCore import *
class FooA(QObject):
trigger=pyqtSignal(str)
def receive_trigger(self,a):
print'triggered in FooA, string',a
class MainObj(QObject):
def __init__(self):
self.a1=FooA()
self.a2=FooA()
#I can connect signals and methods of separate objects:
self.a1.trigger.connect(self.a2.receive_trigger)
self.a1.trigger.emit('hi')
#... but I can't connect a signal with a method of self
self.a1.trigger.connect(self.receive_trigger)
self.a1.trigger.emit('hi')
def receive_trigger(self,a):
print 'triggered in MainObj'
executes as:
MainObj()
triggered in FooA, string hi
triggered in FooA, string hi
I expected to see an additional line, > triggered in MainObj
Thanks in advance.
Bill
As you already seem to know, signals must belong to QObjects, but this problem is occurring because you are not calling the constructor of QObject. FooA does not override the constructor, therefore the default constructor is called and the signals work as expected. In MainObj however, you do not call the superclass' (QObject) constructor, so signals will not work. To fix, either put:
QObject.__init__(self)
or
super(QObject, self).__init__()
(based on your conventions) at the top of MainObjs contructor, and the signals will then work as expected.