Using a QGraphicsItem in a QGraphicsLayout - python-3.x

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_())

Related

'spaceship' class is not defined (even though I've imported it?)

I run the main module, which should work correctly. But an error gets returned. 'spaceship' is not defined when I define 's=spaceship(parameters)' why is this I don't get it. I'm using zelle graphics for python. thank you
Functions from main module:
spaceshipGame file
from graphics import *
from spaceshipClass import *
def main():
window=createGraphicsWindow()
runGame(window)
def createGraphicsWindow():
win=GraphWin("Spaceship game",800,800)
return win
def createSpaceship(window,p1,p2,p3,speed,colour):
s=spaceship(window,p1,p2,p3,speed,colour)
return s
def runGame(window):
player=createSpaceship(window,Point(500,500),Point(500,470),Point(520,485),0.5,"red")
player.draw(window)
main()
spaceshipClass file
from spaceshipGame import *
from graphics import *
class spaceship:
def __init__(self,window,p1,p2,p3,speed,colour):
self.p1=p1
self.p2=p2
self.p3=p3
self.speed=speed
self.colour=colour
self.window=window
Never mind, I see the problem. Consult this example for more information:
Simple cross import in python
But the problem is the way you are cross importing, so delete from spaceshipGame import * from spaceshipClass or vise-versa (i.e. delete from spaceshipClass import * from spaceshipGame). You can import individually if you need to like in the example I provided.
There are also many other ways around it if you read the example. One of the easiest would be just merging them in the same file if they need to share a lot of methods.

Adding Parameters to init function of inherited class

i am quite new to inheritance and overriding methods and i am not quite sure how to override the __init__ method of a class, more specifically, adding another parameter to it.
Basically i want to override the __init__ method of the tkinter class simpledialog.Dialog.
From the documentation the init method of simpledialog.Dialog has the Parameters __init__(self,parent,title=None) and i want it to be __init__(self,parent,labeltitle,title=None)
Ok guys, so for context i also changed some of the other methods of the class, i will give you the code so that people know why i want labeltitle in the init method. I found a solution on how to solve my problem, if anyone has an idea or sees a problem with this let me know.
import tkinter
from tkinter import simpledialog
class MyDialog(simpledialog.Dialog):
def __init__(self,parent,labeltitle,title):
self.labeltitle=labeltitle
super().__init__(parent,title)
def body(self, master):
self.geometry("400x300")
tkinter.Label(master, text=self.labeltitle).grid(row=0)
self.e1 = tkinter.Entry(master)
self.e1.grid(row=0, column=1,pady=30)
return self.e1 # initial focus
def apply(self):
first = self.e1.get()
self.result = first
so now when i create an Object of MyDialog like this:
asd = MyDialog(root,"title_of_the_label","title_of_the_Dialogwindow")
i get the Dialogwindow with these titles. Now i can create multiple objects with different windowtitles and labeltitles, since the simpledialog.Dialog class only allowed to change the title of the Dialogwindow, not the labeltitle.

Replace package import in a module

I use a module that imports a function as a package import using relative import dot notation:
from .utils import target_func
class ClassINeed:
def function_i_call(self):
return target_func()
I want to import ClassINeed with from classineed import ClassINeed but replace target_func with a function of my own. Problem is, target_func is not part of the class I am importing. Therefore I do not see a way to access it. What would be a way to accomplish this?
On top of from classineed import ClassINeed, also do a import classineed then override the target_func as needed via classineed.target_func = lambda : 'hello!' for example.
P.S. Referring to the class ClassINeed with classineed.ClassINeed might be cleaner if you already have import classineed.

How do I get a basic working example for django-user-account?

I followed the installation instructions on django-user-accounts.
When calling http://[mysite]/account/signup
I could see:{# This template intentionally left blank to satisfy test suites. Your project should always provide a site_base.html itself. #} (and I take it as a good sign, I'll add my base template later).
After that, i created an app: ./manage.py startapp myapp_account
...and filled it with the minimum code from the "Usage" page of the manual mentioned above as i want to get a basic working register/login/out.
Now i get an error when calling http://[mysite]/account/signup/:
Exception Value: 'module' object has no attribute 'views'
Exception Location: /var/www/venv/django_1/django_1/urls.py in <module>, line 10
Python Executable: /var/www/venv/bin/python3.4
my code:
urls.py (main project called django_1):
from django.conf.urls import patterns, include, url
import myapp_account
urlpatterns = patterns('',
# this is line 10 in my case:
url(r'^account/signup/$', myapp_account.views.SignupView(),name="account_signup"),
url(r'^account/', include('account.urls')),
)
myapp_account/views.py:
import account.views
import account.forms
import myapp_account.forms
class SignupView(account.views.SignupView):
form_class = myapp_account.forms.SignupForm
def after_signup(self, form):
self.create_profile(form)
super(SignupView, self).after_signup(form)
def create_profile(self, form):
profile = self.created_user.get_profile()
profile.birthdate = form.cleaned_data["birthdate"]
profile.save()
class LoginView(account.views.LoginView):
form_class = account.forms.LoginEmailForm
myapp_account/forms.py
from django import forms
from django.forms.extras.widgets import SelectDateWidget
import account.forms
class SignupForm(account.forms.SignupForm):
birthdate = forms.DateField(widget=SelectDateWidget(years=range(1930, 2010)))
Is there a simpler way do get it working and be on the right track to extend the user accounts step by step?
As usual the answer was in the manual Django, Class-based views
:
Import the class based view directly
Call the class based view directly in the url
updated urls.py (main)
from django.conf.urls import patterns, include, url
from myapp_account.views import SignupView # <- import class based view
urlpatterns = patterns('',
# call class based view directly:
url(r'^account/signup/$', SignupView.as_view(), name="account_signup"),
url(r'^account/', include('account.urls')),
)
Still i'd be happy if someone cloud point me to a well made example of django-user-accounts.

How can I query asynchronously via a QSqlQueryModel?

I wish to query a SQL database via QSqlQueryModel (PyqQt 5/Qt 5.2) asynchronously, so that the GUI doesn't block. How can this be accomplished? Maybe through multithreading? Please provide code of how to do this. If using QSqlQueryModel asynchronously isn't practical, feel free to provide alternatives (should be usable with QTableView though).
My (synchronous) code currently looks as shown beneath. The main script bin/app.py loads gui/__init__.py and executes its main method. That in turn uses gui.models.Table to load data from the database. The problem is that gui.models.Table queries the database synchronously and locks up the GUI in the meantime.
bin/app.py:
import os.path
import sys
sys.path.insert(0, os.path.abspath(os.path.join(
os.path.dirname(__file__), "..")))
import gui
if __name__ == "__main__":
gui.main()
gui/__init__.py:
import sys
import os.path
from PyQt5 import uic
from PyQt5 import QtCore, QtWidgets
from gui import models
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
uic.loadUi(os.path.join(os.path.dirname(__file__), 'app.ui'), self)
self.tableView.setModel(models.Table(self))
def main():
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
app.exec_()
gui/models.py:
import os.path
from PyQt5.QtCore import *
from PyQt5.QtSql import *
class Table(QSqlQueryModel):
def __init__(self, parent=None):
super(Table, self).__init__(parent)
pth = os.path.abspath(os.path.join(os.path.dirname(__file__), "..",
"test.sqlite"))
db = QSqlDatabase.addDatabase("QSQLITE")
db.setDatabaseName(pth)
if not db.open():
raise Exception("Couldn't open database '{}'".format(pth))
try:
self.setQuery("select * from Test")
finally:
db.close()
Unfortunately, a typical database driver that Qt (or anyone else, really) uses is synchronous. Qt views unfortunately don't know how to deal with models in foreign threads.
The solution thus requires a shim proxy model, subclassing QIdentityProxyModel. The first step in the implementation is to shim all of the source model's method calls with blocking QMetaObject::invokeMethod calls. This is needed just to be correct, if not asynchronous just yet. It' just to expose a safe interface to a model that lives in another thread.
The next step is to provide an asynchronous veneer over some of the functionality. Suppose that you want to make the data method asynchronous. What you do is:
For each role, have a cache of variant values keyed by the model index.
On the dataChanged signal from the source model, cache all the values that were changed, across all roles. The data call needs to be queued in the model's thread - more on that later.
In data, if there's a cache hit, return it. Otherwise return a null variant and queue the data call in the model's thread.
Your proxy should have a private method called cacheData that will be called from the queued calls. In another answer, I've detailed how to queue functor calls in another thread. Leveraging that, your data call queuing method can look like:
void ThreadsafeProxyModel::queueDataCall(const QModelIndex & index, int role) {
int row = index.row();
int column = index.column();
void * data = index.internalPointer();
postMetacall(sourceModel()->thread(), [this, row, column, data, role]{
QVariant data = sourceModel()->data(createIndex(row, column, data), role);
QMetaObject::invoke(this, "cacheData",
Q_ARG(QVariant, data), Q_ARG(int, role),
Q_ARG(int, row), Q_ARG(int, column), Q_ARG(void*, data));
});
}
This is just a sketch. It'd be fairly involved, but certainly doable, and still maintaining the semantics of a real model.

Resources