PyQt4 pass transformation matrix as argument to constructor - python

I am writing a widget for PyQt4 and the project style guide dictates that I pass static properties of Qt elements through kwargs in the constructor.
Unfortunately, I am having trouble finding the correct kwarg name for the property I want to pass.
My current implementation looks like this:
self.scene = QtGui.QGraphicsScene(self)
self.view = QtGui.QGraphicsView(self.scene, self.mainArea)
# Flip y axis for sane drawing
matrix = QtGui.QMatrix()
matrix.scale(1, -1)
self.view.setMatrix(matrix)
I want to find a way to pass the matrix through the QGraphicsView constructor, if that's even possible.
I have tried the following
self.view = QtGui.QGraphicsView(self.scene, self.mainArea, matrix=matrix)
self.view = QtGui.QGraphicsView(self.scene, self.mainArea, transform=matrix)
but both of these instances tell me that they are unknown keyword arguments. I am not sure if this is even possible through the constructor, but I haven't been able to find a definitive answer anywhere.
I am also fuzzy on what the "static properties" of Qt elements are exactly.

Are you sure you've understood the style guide properly? I doubt that it expects you to set every possible property of every conceivable class using kwargs. The QGraphicsView class has eighty properties. Do you think it's plausible that Qt would define constructors with eighty optional arguments?
I think it's more likely that the guide is simply asking you to use kwargs wherever they are available. Otherwise, you should just use the property setter functions.
PS:
The matrix of a QGraphicsView is not a property anyway, so for your specific example, the point is moot.

Related

PyQt5 QGraphicsItem odd inheritance behaviour

This is a problem I've found the solution to, but not the answer to. The following is the relevant part of my code:
class MyClass(QGraphicsPolygonItem, MyAbstractGraphicsShapeItem, MyGraphicsItem)
def __init__(self):
super(MyClass, self).__init__()
The first class is the type of graphics object I'm trying to create. For me, the first one I did was a polygon. The second class is one which needed to inherit QAbstractGraphicsShapeItem to change the objects color through. The third class works with any QGraphicsItem. To make everything modular and reusable, this was my setup.
The issue I faced was as such:
If the first class was after the second class, MyClass would no longer recognize it had a polygon I could set.
If the third class was before the second class, MyClass would stop painting itself, showing up in no way on screen.
As you can see, the sequence shown in my code is the only one that works. One of the sequences (third, first, second) even crashes the program. Here is what I think happens:
The graphic item classes inherit in this order, from superclass <--- subclass.
QGraphicsItem <--- QAbstractGraphicsShapeItem <--- QGraphicsPolygonItem
When the initialization priority is the same as the inheritance direction from subclasses to superclasses, the inheritance works.
The Point
This is what I think the initialization order looks like in these situations:
MyAbstractgraphicsShapeItem, QGraphicsPolygonItem, MyGraphicsItem, QAbstractGraphicsShapeItem, QGraphicsItem
QGraphicsPolygonItem, MyGraphicsItem, MyAbstractgraphicsShapeItem, QAbstractGraphicsShapeItem, QGraphicsItem
QGraphicsPolygonItem, MyAbstractgraphicsShapeItem, MyGraphicsItem, QAbstractGraphicsShapeItem, QGraphicsItem
Where the third is the working one.
I cannot see the difference between them. I know how it should work but not why. The initialization order shouldn't matter, as the super call should order them like this, where there are no conflicts between functionality. I know that QAbstractGraphicsShapeItem doesn't have boundingRect or paint functions, but I believe they should be overwritten by QGraphicsPolygonItem class functions. I would like an answer, because this was a really baffling issue to solve.
Edit:
I'll add the other two classes, just the relevant parts:
class MyGraphicsItem(QGraphicsItem):
def __init__(self):
super(MyQGraphicsItem, self).__init__()
class MyAbstractGraphicsShapeItem(QAbstractGraphicsShapeItem):
def __init__(self):
super(MyAbstractGraphicsShapeItem, self).__init__()
For additional detail, MyGraphicsItem allows me to place graphics items in relation to the parent as I wish, while MyAbstractGraphicsShapeItem allows me to create button like behavior (since QAbstractButton only works with QWidgets).

Keeping classes loosely coupled and sharing data

I've been working in python on a project where I have a GUI which I split up a bunch of the work between classes. I don't know a lot of the best practices for passing data around between classes, and I've frequently run into the issue, where I have to implement something, or change something for work, and I've resorted to making a lot of the classes objects of another class in order to give it the data I need.
Any ideas or suggests would be greatly appreciated on how to keep my classes independent for later modification and still pass the relevant data around without affecting interfaces too much?
As an example
class Window():
def __init__(self, parent=None):
self.parent = parent
def doStuff(self):
#do work here
class ParseMyWork(Window):
def __init__(self, parent=None):
self.parent=parent
I often find myself doing stuff like the above giving objects to class Window
or simply inheriting everything from them as in ParseMyWork
There must be better and cleaner ways of passing data around without making my classes utterly dependent on eachother, where one little change creates a cascade effect that forces me to make changes in a bunch of other classes.
Any answers to the question don't necessarily have to be in python, but it will be helpful if they are
If I'm understanding your question correctly, I would say that inheritance is not necessary in your case. Why not give ParseMyWork a function for dealing with a specific Window task?
class Window():
def __init__(self, parent=None):
self.parent = parent
def doStuff(self):
#do work here
class ParseMyWork():
def __init__(self, parent=None):
self.parent=parent`
def doWindowActivity(self, window):
window.doStuff
Then you can use the function like this
work_parser = ParseMyWork()
window = Window()
work_parser.doWindowActivity(window);
That way you can use your work_parse instance with any window instance.
Apologies in advance for my Python, it's been a while so if you see any rookie mistakes, do point them out.
Keep it simple.py:
def doStuff(window):
#do work here
return window
def parseStuff(stuff):
pass
really.py:
from simple import doStuff, parseStuff
def really_simple(window):
okay = doStuff(window)
return parseStuff(okay)
don't complicate the class:
from really import really_simple
really_simple(window)
imo: classes are overly complicated objects, and in a lot of cases more confusing than they need to be, plus they hold references and modify stuff, and can be difficult to decouple once they have been tied to other classes. if there isn't a clear reason why a class needs to be used, then it probably doesn't need to be used.
Classes are super powerful, so it's good you're getting started with em.
Discalimer: Haven't worked in python for a while now, so things might not be exact. The general idea still applies though.
Getting into your question now:
I would say the best way to achieve what you want is to create an instance of the first object where you will extract information from.
Now when creating a class, it's vital that you have attributes within them that you will want to be stored within it that you would like to retrieve once the class is instantiated.
For example, using your Window class example above, let's say that you have an attribute called resolution. It would look something like this:
class Window():
def __init__(self, parent = None):
self.parent = None
self.resolution = '40x80'
Now the resolution information associated with your Window class is forever part of any Window class instance. Now, the next step would be to create a get method for resolution. This should be done as follow:
class Window():
def __init__(self, parent = None):
self.parent = None
self.resolution = '40x80'
def getResoultion():
return self.resolution
Now, the reason we created this get method is because we can now set a variable to the information that is returned with it.
So let's say that you have everything associated with your Window class in its own file (let's say the file name is called Window.py). In a separate file (let's call it main.py), you can do the following:
import Window
windowInstance = Window()
windowResolution = windowInstance.getResolution()
If you print out the variable windowResolution, you should get that 40x80 printed out.
Now, as a side note, I do believe it is possible to get the information associated with an attribute with an instance of a class by simply doing something like
windowResolution = windowInstance.resolution
but that is bad practice in general. The reason, in a nutshell, is because you are now exposing attribute names of your class which you do not want to do because it makes it easy for a person outside of your code to learn the name where that information is held and change it. This can then lead to a myriad of other problems when it comes to making an overall program work. That is why it is best practice to use getters and setters. I already showed what getters are. Simply a get method for attributes. Setters, as you can probably assume, allow for one to set the information of an attribute to something else. Now you might say "Gabe, if we can create setter methods, what's the point of it if they just change it". My answer to that is to not give a setter method to all attributes. For attributes you don't mind for a person to change, give it a setter method, but for attributes you do not want any outside users to touch, simply don't create a setter method for it. Same goes with getter methods too. Users don't need to see all of the information of all attributes that makes your program work. Here's a better explanation: https://en.wikipedia.org/wiki/Mutator_method
Now, back to your example. Now let's say you have your ParseMyWork class in its own file like we did with your Window class, and let's say that ParseMyWork needs the resolution info from Window class. You can do the following :
import Window
import ParseMyWork
windowInstance = Window()
windowResolution = windowInstance.getResolution()
parseInstance = ParseMyWork(windowResolution)
This will only pass the window resolution information associated with your Window class. Hope this helps.

What is the proper way to add an attribute to a base class in a Python library and have it inherited?

I am trying to extend a Python library to add functionality I desire. The library provides a number of HTML form objects (such as Textbox, Dropdown, Checkbox, etc.), all derived from an Input object. I want to add an additional attribute to all of these derived objects. What is the proper way of proceeding?
I can:
Modify the original source code for the Input class, adding the attribute I want.
Create a new class that inherits Input and adds my attribute, and then create a bunch of new classes that inherit Textbox, Dropdown, and my new Input class.
Create new classes for Textbox, Dropdown, etc. with the attribute.
Solution 1 is the easiest and simplest, but is inherently wrong, whereas the other two seem like much more work and code-repetition than this task should call for.
Is there a solution I'm missing?
The 4th solution is monkey patching and might be a good idea. Before you try this, make sure this won't break anything now or in the future:
def additional_method(self, arg):
print("hello", arg)
Input.additional_method = additional_method
or for short stuff:
Input.additional_method = lambda self, arg: do_something(arg)
now all existing and future Input instances (and therefore instances of all Input subclasses) have an additional_method attached to them.
This works also for any future subclasses of Input that might not even exist yet, or you might not be aware of, at the time of adding the method, so is therefore better (i.e. more generic) than creating an alternative inheritance hierarchy, which you'll have to then maintain and keep in sync with upstream changes.
NOTE: before you downvote just because it contains the phrase "monkey patching", consider that monkey patching doesn't have to be dangerous/fragile, and is a first class (as in "respected") feature in many languages.
You can use a mixin (multiple inheritance). It's a class that just contains your extra attribute, and add this class to the parent class of a subclass of Textbox, Dropdown, Checkbox... like this:
from ... import TextBox
class Mixin:
def __init__(self):
self.new_attribude = ...
class TextBox_with_new_attribute(Mixin, TextBox):
pass
But, it depends tightly on your goals...
Edit: base on #Veedrac comment, in case of third party library.
If there are a lot of classes you could dynamically apply a mixin:
for cls in list_of_classes_to_patch:
patched = type(cls.__name__, (my_mixin, cls), {})
setattr(place_to_export, cls.__name__, patched)
place_to_export can be defined as import this_module as place_to_export.

Different ways of using __init__ for PyQt4

So... I'm working on trying to move from basic Python to some GUI programming, using PyQt4. I'm looking at a couple different books and tutorials, and they each seem to have a slightly different way of kicking off the class definition.
One tutorial starts off the classes like so:
class Example(QtGui.QDialog):
def __init__(self):
super(Example, self).__init__()
Another book does it like this:
class Example(QtGui.QDialog):
def __init__(self, parent=None):
super(Example, self).__init__(parent)
And yet another does it this way:
class Example(QtGui.QDialog):
def__init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
I'm still trying to wrap my mind around classes and OOP and super() and all... am I correct in thinking that the last line of the third example accomplishes more or less the same thing as the calls using super() in the previous ones, by explicitly calling the base class directly? For relatively simple examples such as these, i.e. single inheritance, is there any real benefit or reason to use one way vs. the other? Finally... the second example passes parent as an argument to super() while the first does not... any guesses/explanations as to why/when/where that would be appropriate?
The first one simply doesn't support passing a parent argument to its base class. If you know that you'll never need the parent arg, that's fine, but this is less flexible.
Since this example only has single inheritance, super(Example, self).__init__(parent) is exactly the same as QtGui.QDialog.__init__(self, parent); the former uses super to get a "version" of self that calles QtGui.QDialog's methods instead of Example's, so that self is automatically included, while the latter directly calls the function QtGui.QDialog.__init__ and explicitly passes the self and parent arguments. In single inheritance there's no difference AFAIK other than the amount of typing and the fact that you have to change the class name if you change inheritance. In multiple inheritance, super resolves methods semi-intelligently.
The third example actually uses QWidget instead of QDialog, which is a little weird; presumably that works because QDialog is a subclass of QWidget and doesn't do anything meaningful in its __init__, but I don't know for sure.

Python-passing variable between classes

I'm trying to create a character generation wizard for a game. In one class I calculate the attributes of the character. In a different class, I'm displaying to the user which specialties are available based on the attributes of the character. However, I can't remember how to pass variables between different classes.
Here is an example of what I have:
class BasicInfoPage(wx.wizard.WizardPageSimple):
def __init__(self, parent, title):
wiz.WizardPageSimple.__init__(self, parent)
self.next = self.prev = None
self.sizer = makePageTitle(self, title)
<---snip--->
self.intelligence = self.genAttribs()
class MOS(wx.wizard.WizardPageSimple):
def __init__(self, parent, title):
wiz.WizardPageSimple.__init__(self, parent)
self.next = self.prev = None
self.sizer = makePageTitle(self, title)
def eligibleMOS(self, event):
if self.intelligence >= 12:
self.MOS_list.append("Analyst")
The problem is that I can't figure out how to use the "intelligence" variable from the BasicInfoPage class to the MOS class. I've tried several different things from around the Internet but nothing seems to work. What am I missing?
Edit I realized after I posted this that I didn't explain it that well. I'm trying to create a computer version of the Twilight 2000 RPG from the 1980s.
I'm using wxPython to create a wizard; the parent class of my classes is the Wizard from wxPython. That wizard will walk a user through the creation of a character, so the Basic Information page (class BasicInfoPage) lets the user give the character's name and "roll" for the character's attributes. That's where the "self.intelligence" comes from.
I'm trying to use the attributes created her for a page further on in the wizard, where the user selects the speciality of the character. The specialities that are available depend on the attributes the character has, e.g. if the intelligence is high enough, the character can be an Intel Anaylst.
It's been several years since I've programmed, especially with OOP ideas. That's why I'm confused on how to create what's essentially a global variable with classes and methods.
You may have "Class" and "Instance" confused. It's not clear from your example, so I'll presume that you're using a lot of class definitions and don't have appropriate object instances of those classes.
Classes don't really have usable attribute values. A class is just a common set of definitions for a collection of objects. You should think of of classes as definitions, not actual things.
Instances of classes, "objects", are actual things that have actual attribute values and execute method functions.
You don't pass variables among classes. You pass variables among instances. As a practical matter only instance variables matter. [Yes, there are class variables, but they're a fairly specialized and often confusing thing, best avoided.]
When you create an object (an instance of a class)
b= BasicInfoPage(...)
Then b.intelligence is the value of intelligence for the b instance of BasicInfoPage.
A really common thing is
class MOS( wx.wizard.PageSimple ):
def __init__( self, parent, title, basicInfoPage ):
<snip>
self.basicInfo= basicInfoPage
Now, within MOS methods, you can say self.basicInfo.intelligence because MOS has an object that's a BasicInfoPage available to it.
When you build MOS, you provide it with the instance of BasicInfoPage that it's supposed to use.
someBasicInfoPage= BasicInfoPage( ... )
m= MOS( ..., someBasicInfoPage )
Now, the object m can examine someBasicInfoPage.intelligence
Each page of a Wizard -- by itself -- shouldn't actually be the container for the information you're gathering.
Read up on the Model-View-Control design pattern. Your pages have the View and Control parts of the design. They aren't the data model, however.
You'll be happier if you have a separate object that is "built" by the pages. Each page will set some attributes of that underlying model object. Then, the pages are independent of each other, since the pages all get and set values of this underlying model object.
Since you're building a character, you'd have some class like this
class Character( object ):
def __init__( self ):
self.intelligence= 10
<default values for all attributes.>
Then your various Wizard instances just need to be given the underlying Character object as a place to put and get values.
My problem was indeed the confusion of classes vs. instances. I was trying to do everything via classes without ever creating an actual instance. Plus, I was forcing the "BasicInfoPage" class to do too much work.
Ultimately, I created a new class (BaseAttribs) to hold all the variables I need. I then created in instance of that class when I run the wizard and pass that instance as an argument to the classes that need it, as shown below:
#---Run the wizard
if __name__ == "__main__":
app = wx.PySimpleApp()
wizard = wiz.Wizard(None, -1, "TW2K Character Creation")
attribs = BaseAttribs
#---Create each page
page1 = IntroPage(wizard, "Introduction")
page2 = BasicInfoPage(wizard, "Basic Info", attribs)
page3 = Ethnicity(wizard, "Ethnicity")
page4 = MOS(wizard, "Military Occupational Specialty", attribs)
I then used the information S.Lott provided and created individual instances (if that's what it's called) within each class; each class is accessing the same variables though.
Everything works, as far as I can tell. Thanks.
All you need is a reference. It's not really a simple problem that I can give some one-line solution to (other than a simple ugly global that would probably break something else), but one of program structure. You don't magically get access to a variable that was created on another instance of another class. You have to either give the intelligence reference to MOS, or take it from BasicInfoPage, however that might happen. It seems to me that the classes are designed rather oddly-- an information page, for one thing, should not generate anything, and if it does, it should give it back to whatever needs to know-- some sort of central place, which should have been the one generating it in the first place. Ordinarily, you'd set the variables there, and get them from there. Or at least, I would.
If you want the basic answer of "how do I pass variables between different classes", then here you go, but I doubt it's exactly what you want, as you look to be using some sort of controlling framework:
class Foo(object):
def __init__(self, var):
self.var = var
class Bar(object):
def do_something(self, var):
print var*3
if __name__ == '__main__':
f = Foo(3)
b = Bar()
# look, I'm using the variable from one instance in another!
b.do_something(f.var)
If I understood you correctly, then the answer is: You can't.
intelligence should be an attribute of WizardPageSimple, if you'd want both classes to inherit it.
Depending on your situation, you might try to extract intelligence and related attributes into another baseclass. Then you could inherit from both:
class MOS(wiz.WizardPageSimple, wiz.IntelligenceAttributes): # Or something like that.
In that case you must use the co-operative super. In fact, you should be using it already. Instead of calling
wiz.WizardPageSimple.__init__(self, parent)
call
super(MOS, self).__init__(self, parent)

Categories