Call a function every 1 seconds in python - python

class Viewer:
def __init__(self, width, height, arm_info, point_info, point_l):
self.list_x = [1,2,3,4]
self.list_y = [5,6,7,8]
self.i = 0
self.arm_info = arm_info
self.point_info = point_info
def on_key_press(self,symbol,modifiers):
if symbol == pyglet.window.key.Z:
self.point_info[:] = [self.list_x[self.i],self.list_y[self.i]]
self.i += 1
Here to update the point_info[:] I have to press the 'Z' everytime, I just want Z to be pressed once to update point_info[:] in every 1 second .
def on_key_press(self,symbol,modifiers):
if symbol == pyglet.window.key.Z:
for i in range(0,4):
self.point_info[:] = [self.list_x[i],self.list_y[i]]
time.sleep(1)
I have tried above but it doesn't work. How can I do this?
Here is the complete code, the render method is called from another module.
class Viewer(pyglet.window.Window):
def __init__(self, width, height, arm_info, point_info, point_l, mouse_in):
self.list_x = [100,150,200,300,400]
self.list_y = [100,150,200,300,400]
#initialisation of variables
def render(self):
pyglet.clock.tick()
self._update_arm()
self.switch_to()
self.dispatch_events()
self.dispatch_event('on_draw')
self.flip()
def on_draw(self):
#draws on the screen
def _update_arm(self):
#updates the coordinates of the arm , as it moves
def on_key_press(self, symbol, modifiers):
#HERE LIES THE PROBLEM
if symbol == pyglet.window.key.S:
for j in range(0,4):
self.point_info[:] = [self.list_x[j],self.list_y[j]]
print(self.point_info)
#below 2 lines are for drawing on the screen.
self.clear()
self.batch.draw()
j=+1
time.sleep(1)

I created a small runnable example code, on how to achieve this. The point is, that sleep() blocks the program flow. With pyglet, you have a convenient way to schedule future executions with the pyglet.clock.schedule* methods. You can use that, to call a specific function in the future.
Note: Actual, piglet is running a main loop in it's framework. If you hold the program at some position (like you do with sleep()), no further code can be executed meanwhile, therefore, no drawing can happen, if pyglet requires to call some required methods around the draw call. I guess, you are not supposed to call the on_draw() method by yourself.
import pyglet
from pyglet.window import key
from pyglet import clock
import random
window = pyglet.window.Window()
label = pyglet.text.Label('Hello, world',
font_name='Times New Roman',
font_size=36,
x=window.width//2, y=window.height//2,
anchor_x='center', anchor_y='center')
def updatePoint(dt):
label.x = random.random() * window.width//2
label.y = random.random() * window.height//2
#window.event
def on_key_press(symbol, modifiers):
if symbol == key.S:
print('The "S" key was pressed.')
for j in range(0,4):
clock.schedule_once(updatePoint, j)
#window.event
def on_draw():
window.clear()
label.draw()
if __name__ == '__main__':
pyglet.app.run()

Related

How to change pixel_ratio in pyglet?

I coded a game using pylet. It uses a static window with width 1600 and height 900 assuming users have a fullHD display so everything will be visible. However on some devices (with small displays) the window is way bigger as expected. I figured out that the pixel_ratio is set up (for example to 2.0) making each virtual pixel to be displayed double size (2x2) in physical pixel.
I want to prevent this behavior but can't figure out how, I know I can get the pixel ratio easily by get_pixel_ratio() but I actually don't know how to set them or prevent pyglet from automatically setting them.
I also tried to use glViewport which seemed to have an effect but it didn't worked the way I wanted.
So how can I change the pixel_ratio or prevent changing it automatically.
Asked around in the official discord server for information, as I tried to reproduce the issue myself with some code, and this is what I used to test it:
import math
from pyglet import *
from pyglet.gl import *
key = pyglet.window.key
class main(pyglet.window.Window):
def __init__ (self, width=800, height=600, fps=False, *args, **kwargs):
super(main, self).__init__(width, height, *args, **kwargs)
self.x, self.y = 0, 0
self.keys = {}
verts = []
for i in range(30):
angle = math.radians(float(i)/30 * 360.0)
x = 100*math.cos(angle) + 300
y = 100*math.sin(angle) + 200
verts += [x,y]
self.pixel_ratio = 100
self.circle = pyglet.graphics.vertex_list(30, ('v2f', verts))
self.alive = 1
def on_draw(self):
self.render()
def on_close(self):
self.alive = 0
def on_key_release(self, symbol, modifiers):
try:
del self.keys[symbol]
except:
pass
def on_key_press(self, symbol, modifiers):
if symbol == key.ESCAPE: # [ESC]
self.alive = 0
self.keys[symbol] = True
def render(self):
self.clear()
glClear(pyglet.gl.GL_COLOR_BUFFER_BIT)
glColor3f(1,1,0)
self.circle.draw(GL_LINE_LOOP)
self.flip()
def run(self):
while self.alive == 1:
self.render()
# -----------> This is key <----------
# This is what replaces pyglet.app.run()
# but is required for the GUI to not freeze
#
event = self.dispatch_events()
if __name__ == '__main__':
x = main()
x.run()
Not that the code mattered heh, since the variable pixel_ratio is just, and I quote: "indicating that the actual number of pixels in the window is larger than the size of the Window created."
This is something OSX does to cope with the high DPI, using this information you should be able to scale your graphics accordingly. Window.get_framebuffer_size() will show you the difference in requested Window size and Framebuffer size, if any.
So your only way to actually scale up, would be to use glScale or if you're using sprites you can use Sprite.scale to scale the image-data. If you're using 2D graphics I'd go with the sprite option as it's pretty easy to work with.

Pyglet running but not responding to esc commands

I am relatively new to Python and Pyglet, I am trying to create an app that dynamically displays photos accordingly to the ID of a command sent via serial.
Here is my code:
import pyglet
from pyglet import clock
import serial
import json
import os
base_dir = 'data'
data = []
currentDatum = ''
def initialiseData():
global data
#load the json
with open('dataset.json') as f:
data = json.load(f)
#for every file in the json load the image
for d in data:
d['media'] = pyglet.image.load(os.path.join(base_dir, d['name']))
print("Scan a tag")
def readSerial(dt):
global currentDatum
tag = ser.readline()
tag = tag.strip()
for d in data:
if d['id'] == tag:
currentDatum = d
print(currentDatum)
ser = serial.Serial('/dev/cu.usbmodem1421', 9600)
initialiseData()
window = pyglet.window.Window(1000, 800, resizable = True)
#window.event
def on_draw():
window.clear()
currentDatum['media'].anchor_x = currentDatum['media'].width/2 - window.width/2
currentDatum['media'].anchor_y = currentDatum['media'].height/2 - window.height/2
currentDatum['media'].blit(0, 0)
clock.schedule(readSerial)
pyglet.app.run()
The application works fine, in the sense that it loads the data from the son and when I send the serial ID it gets read instantly, but every mouse interaction freezes the app: I cannot close the window, cannot resize it, it just gets stuck. Any advice?
I have no idea what the program actually does, or how to use it.
And since I can't replicate your environment (you've got a usbmodem for instance), I'll try my best approach at a generic solution that should work and plan ahead for future development on your project:
import pyglet
from pyglet.gl import *
key = pyglet.window.key
class main(pyglet.window.Window):
def __init__ (self, width=800, height=600, fps=False, *args, **kwargs):
super(main, self).__init__(width, height, *args, **kwargs)
self.x, self.y = 0, 0
self.batch = pyglet.graphics.Batch()
self.data = []
self.currentDatum = ''
self.ser = serial.Serial('/dev/cu.usbmodem1421', 9600)
self.initialiseData()
pyglet.clock.schedule(self.readSerial)
self.alive = 1
def on_draw(self):
self.render()
def on_close(self):
self.alive = 0
def on_mouse_motion(self, x, y, dx, dy):
pass
def on_mouse_release(self, x, y, button, modifiers):
pass
def on_mouse_press(self, x, y, button, modifiers):
pass
def on_mouse_drag(self, x, y, dx, dy, button, modifiers):
pass
def on_key_release(self, symbol, modifiers):
pass
def on_key_press(self, symbol, modifiers):
if symbol == key.ESCAPE: # [ESC]
self.alive = 0
def render(self):
self.clear()
# For future reference, use batches:
self.batch.draw()
# But this is how it's implemented atm:
self.currentDatum['media'].anchor_x = self.currentDatum['media'].width/2 - self.width/2
self.currentDatum['media'].anchor_y = self.currentDatum['media'].height/2 - self.height/2
self.currentDatum['media'].blit(0, 0)
self.flip()
def initialiseData(self):
#load the json
with open('dataset.json') as f:
self.data = json.load(f)
#for every file in the json load the image
for d in self.data:
d['media'] = pyglet.image.load(os.path.join(base_dir, d['name']))
print("Scan a tag")
def readSerial(self, dt):
tag = self.ser.readline()
tag = tag.strip()
for d in self.data:
if d['id'] == tag:
self.currentDatum = d
print(self.currentDatum)
def run(self):
while self.alive == 1:
self.render()
# -----------> This is key <----------
# This is what replaces pyglet.app.run()
# but is required for the GUI to not freeze
#
event = self.dispatch_events()
if __name__ == '__main__':
x = main()
x.run()
It's bound to be a few run time errors in this code, syntax that I've might have messed up. But I've ported as much of your code as possible into a object oriented way of thinking. Aka a class that inherits the Window class in order for you to modify elements within and the window itself.
There's also some placeholder-functions that you can use to handle mouse and keyboard events. These are inherited/overlapping the pyglet.window.Window class. So any function supported by Window can be put into this class.
There's also a custom pyglet.app.run() that handles the event polling, making sure you don't get stuck on keyboard, mouse or window (resize, move etc) events.
Hope this works.

Make intro screen with pyglet

I am trying to make a simple game with pyglet, and it has to include an intro screen. Unfortunately, it's been proving more difficult than I expected.
The following code is a simpler version of what I am trying to do.
import pyglet
from game import intro
game_window = pyglet.window.Window(800, 600)
intro.play(game_window)
#game_window.event
def on_draw():
game_window.clear()
main_batch.draw()
def update(dt):
running = True
if __name__ == '__main__':
pyglet.clock.schedule_interval(update, 1/120.0)
main_batch = pyglet.graphics.Batch()
score_label = pyglet.text.Label(text = 'RUNNING GAME', x = 400, y = 200, batch=main_batch)
pyglet.app.run()
Where game/intro.py has the following written in it:
import pyglet
from time import sleep
def play(game_window):
game_window.clear()
studio = pyglet.text.Label('foo studios', font_size=36, font_name='Arial', x=400, y=300)
studio.draw()
sleep(5)
This opens a window (the intro window) and waits 5 seconds, after which the message "RUNNING GAME" appears, but the "foo studios" message does not appear.
Clearly I am doing something wrong.
I am not very experienced with pyglet, but I managed to get the game running (needs a bit of tweaking, but it's essentially done). All I need left is the intro screen.
If anyone knows a good way of doing an intro screen (just with text, I don't need any animations of music for now), I would be very grateful.
You're better off creating classes based on for instance pyglet.sprite.Sprite and using those objects as "windows" or "screens".
Feels like i'm pasting this code everywhere but use this, and in "def render()` put the different "scenarios"/"windows" you'd wish to be rendered at the time.
import pyglet
from time import time, sleep
class Window(pyglet.window.Window):
def __init__(self, refreshrate):
super(Window, self).__init__(vsync = False)
self.frames = 0
self.framerate = pyglet.text.Label(text='Unknown', font_name='Verdana', font_size=8, x=10, y=10, color=(255,255,255,255))
self.last = time()
self.alive = 1
self.refreshrate = refreshrate
def on_draw(self):
self.render()
def render(self):
self.clear()
if time() - self.last >= 1:
self.framerate.text = str(self.frames)
self.frames = 0
self.last = time()
else:
self.frames += 1
self.framerate.draw()
self.flip()
def on_close(self):
self.alive = 0
def run(self):
while self.alive:
self.render()
event = self.dispatch_events() # <-- This is the event queue
sleep(1.0/self.refreshrate)
win = Window(23) # set the fps
win.run()
What does it is the fact that you have a rendering function that clears and flips the entire graphical memory X times per second and you descide which objects are included in that render perior in the render function.
Try it out and see if it helps.
Here is a example using the above example, it consists of 3 things:
* A main window
* A Intro screen
* A Menu screen
You can ignore class Spr() and def convert_hashColor_to_RGBA(), these are mere helper functions to avoid repetative code further down.
I will also go ahead and mark the important bits that actually do things, the rest are just initation-code or positioning things.
import pyglet
from time import time, sleep
__WIDTH__ = 800
__HEIGHT__ = 600
def convert_hashColor_to_RGBA(color):
if '#' in color:
c = color.lstrip("#")
c = max(6-len(c),0)*"0" + c
r = int(c[:2], 16)
g = int(c[2:4], 16)
b = int(c[4:], 16)
color = (r,g,b,255)
return color
class Spr(pyglet.sprite.Sprite):
def __init__(self, texture=None, width=__WIDTH__, height=__HEIGHT__, color='#000000', x=0, y=0):
if texture is None:
self.texture = pyglet.image.SolidColorImagePattern(convert_hashColor_to_RGBA(color)).create_image(width,height)
else:
self.texture = texture
super(Spr, self).__init__(self.texture)
## Normally, objects in graphics have their anchor in the bottom left corner.
## This means that all X and Y cordinates relate to the bottom left corner of
## your object as positioned from the bottom left corner of your application-screen.
##
## We can override this and move the anchor to the WIDTH/2 (aka center of the image).
## And since Spr is a class only ment for generating a background-image to your "intro screen" etc
## This only affects this class aka the background, so the background gets positioned by it's center.
self.image.anchor_x = self.image.width / 2
self.image.anchor_y = self.image.height / 2
## And this sets the position.
self.x = x
self.y = y
def _draw(self):
self.draw()
## IntoScreen is a class that inherits a background, the background is Spr (our custom background-image class)
## IntoScreen contains 1 label, and it will change it's text after 2 seconds of being shown.
## That's all it does.
class IntroScreen(Spr):
def __init__(self, texture=None, width=300, height = 150, x = 10, y = 10, color='#000000'):
super(IntroScreen, self).__init__(texture, width=width, height=height, x=x, y=y, color=color)
self.intro_text = pyglet.text.Label('Running game', font_size=8, font_name=('Verdana', 'Calibri', 'Arial'), x=x, y=y, multiline=False, width=width, height=height, color=(100, 100, 100, 255), anchor_x='center')
self.has_been_visible_since = time()
def _draw(self): # <-- Important, this is the function that is called from the main window.render() function. The built-in rendering function of pyglet is called .draw() so we create a manual one that's called _draw() that in turn does stuff + calls draw(). This is just so we can add on to the functionality of Pyglet.
self.draw()
self.intro_text.draw()
if time() - 2 > self.has_been_visible_since:
self.intro_text.text = 'foo studios'
## Then we have a MenuScreen (with a red background)
## Note that the RED color comes not from this class because the default is black #000000
## the color is set when calling/instanciating this class further down.
##
## But all this does, is show a "menu" (aka a text saying it's the menu..)
class MenuScreen(Spr):
def __init__(self, texture=None, width=300, height = 150, x = 10, y = 10, color='#000000'):
super(MenuScreen, self).__init__(texture, width=width, height=height, x=x, y=y, color=color)
self.screen_text = pyglet.text.Label('Main menu screen', font_size=8, font_name=('Verdana', 'Calibri', 'Arial'), x=x, y=y+height/2-20, multiline=False, width=300, height=height, color=(100, 100, 100, 255), anchor_x='center')
def _draw(self):
self.draw()
self.screen_text.draw()
## This is the actual window, the game, the glory universe that is graphics.
## It will be blank, so you need to set up what should be visible when and where.
##
## I've creates two classes which can act as "screens" (intro, game, menu etc)
## And we'll initate the Window class with the IntroScreen() and show that for a
## total of 5 seconds, after 5 seconds we will swap it out for a MenuScreeen().
##
## All this magic is done in __init__() and render(). All the other functions are basically
## just "there" and executes black magic for your convencience.
class Window(pyglet.window.Window):
def __init__(self, refreshrate):
super(Window, self).__init__(vsync = False)
self.alive = 1
self.refreshrate = refreshrate
self.currentScreen = IntroScreen(x=320, y=__HEIGHT__/2, width=50) # <-- Important
self.screen_has_been_shown_since = time()
def on_draw(self):
self.render()
def on_key_down(self, symbol, mod):
print('Keyboard down:', symbol) # <-- Important
def render(self):
self.clear()
if time() - 5 > self.screen_has_been_shown_since and type(self.currentScreen) is not MenuScreen: # <-- Important
self.currentScreen = MenuScreen(x=320, y=__HEIGHT__-210, color='#FF0000') # <-- Important, here we switch screen (after 5 seconds)
self.currentScreen._draw() # <-- Important, draws the current screen
self.flip()
def on_close(self):
self.alive = 0
def run(self):
while self.alive:
self.render()
event = self.dispatch_events()
sleep(1.0/self.refreshrate)
win = Window(23) # set the fps
win.run()

How to find is a canvas item is touching another canvas item, Tkinter

I have a program where the user controls a block and navigates through pipes, similar to the game flappy bird. I want to know if tkinter has a way of telling me if one rectangle touches or hits another. I know there is a find_overlapping method for the canvas, but when i use find_overlapping on the pipe's rectangle it gives me the id of the pipe! I want to know if canvas items have a way of knowing if another canvas item is touching it!
Thanks
Here is my code:
from Tkinter import *
from random import *
root=Tk()
c=Canvas(root,width=600,height=600)
speed=20
num=1
first=True
b=0
pipes=[]
done=False
class Pipe():
def __init__(self,canvas,pipes,length,width=75,color="Green",position=600,speed=5):
self.speed=speed
self.canvas=canvas
self.length=length
self.width=width
self.color=color
self.position=position
self.current1=self.canvas.create_rectangle((self.position,0,self.position+self.width,self.length),outline=self.color,fill=self.color)
self.current2=self.canvas.create_rectangle((self.position,600,self.position+self.width,self.length+150),outline=self.color,fill=self.color)
self.pipes=pipes
self.pipes.append(self.current1)
self.pipes.append(self.current2)
def move(self):
global done
if (len(self.canvas.find_overlapping(self.position,0,self.position+self.width,self.length))==1 and len(self.canvas.find_overlapping(self.position,600,self.position+self.width,self.length+150))==1) and not done:
self.position-=3
self.canvas.coords(self.current1,(self.position,0,self.position+self.width,self.length))
self.canvas.coords(self.current2,(self.position,600,self.position+self.width,self.length+150))
if self.position>-75:
self.canvas.after(self.speed,self.move)
else:
self.pipes.remove(self.current1)
self.pipes.remove(self.current2)
self.canvas.delete(self.current1)
self.canvas.delete(self.current2)
else:
print self.canvas.find_overlapping(self.position,0,self.position+self.width,self.length)
print
print self.canvas.find_overlapping(self.position,600,self.position+self.width,self.length+150)
done=True
class Player():
def __init__(self,canvas,x=150,y=300,size=40):
self.size=size
self.faller=True
self.x=x
self.y=y
self.fell=5
self.canvas=canvas
#For now
self.current=self.canvas.create_rectangle((self.x-20,self.y-20,self.x+20,self.y+20),tags="user",outline="Blue",fill="Blue")
self.canvas.after(100,self.fall)
self.canvas.bind("<1>",self.jump)
def fall(self):
global done
if self.faller and not done:
self.y+=self.fell
self.fell*=1.001
self.canvas.coords(self.current,(self.x-20,self.y-20,self.x+20,self.y+20))
self.canvas.after(30,self.fall)
elif done:
a=600-self.y+20
a/=50
while self.y<580:
self.y+=a
self.canvas.coords(self.current,(self.x-20,self.y-20,self.x+20,self.y+20))
def jump(self,e):
if not done:
self.faller=False
for x in range(10):
self.canvas.after(100,self.move)
self.faller=True
self.fell=5
def move(self):
self.y-=7.5
self.canvas.coords(self.current,(self.x-20,self.y-20,self.x+20,self.y+20))
def changey(self,a):
self.y=a
def run():
global b,first,done
if not done:
if first:
b=randint(5,450)
first=False
else:
if b<225:
b=randint(5,b+225)
if b>225:
b=randint(b-225,450)
else:
b=randint(0,600)
a=Pipe(c,pipes,b)
a.move()
c.after(2000,run)
else:
return
root.focus_set()
user=Player(c)
c.after(2000,run)
c.pack()
root.mainloop()
Canvas.find_overlapping return a tuple with all the ids of shapes in the bbox. If only your id is returned it might be because it is the sole one.
You can use it with the bbox of another shape like this : canvas.find_overlapping(*canvas.bbox(aShape)).
Note that overlapping works on rectangle and might be erroneous for instance on circles.

pyqt - error while running, probably wrong paintevent method implementation

Me and my colleagues are writing a data processing application in python.
We are currently working on the frontend part of the application.
We have a big problem though, that's that the application gets the following error after a random amount of time:
QWidget::repaint: Recursive repaint detected
This one also pops up from time to time:
QPainter::begin: Paint device returned engine == 0, type: 1
This is the file where all gui related stuff happens, I cut out the irrelevant methods for the sake of not being to lengthy:
gfx.py:
import sys, random, math
from PyQt4 import QtGui, QtCore
from random import randrange
from eventbased import listener
app = QtGui.QApplication(sys.argv)
def exec():
return app.exec_()
class MapView(QtGui.QMainWindow, listener.Listener):
def __init__(self, mapimagepath = 0, nodes = 0):
QtGui.QMainWindow.__init__(self)
listener.Listener.__init__(self)
self.setWindowTitle('Population mapping')
self.map = Map(self, mapimagepath)
self.setCentralWidget(self.map)
self.map.start()
self.center()
def center(self):
screen = QtGui.QDesktopWidget().screenGeometry()
size = self.geometry()
self.move(50, 0)
def handle(self, event):
if(event.type == 0):
self.map.addNode(event.object.scanner)
if(event.type == 1):
self.map.delNode(event.object.scanner)
if(event.type == 2):
self.map.addBranch(event.object.node1.scanner, event.object.node2.scanner)
if(event.type == 3):
self.map.delBranch(event.object.node1.scanner, event.object.node2.scanner)
if(event.type == 4):
self.map.changeNode(event.object.scanner.sensorid, event.result)
if(event.type == 5):
self.map.changeBranch(event.object.node1.scanner.sensorid, event.object.node2.scanner.sensorid, event.result)
self.repaint(self.map.contentsRect())
self.update(self.map.contentsRect())
######################################################################
class Map(QtGui.QFrame):
def __init__(self, parent, mapimagepath):
QtGui.QFrame.__init__(self, parent)
#self.timer = QtCore.QBasicTimer()
#coordinaten hoeken NE en SW voor kaart in map graphics van SKO
self.realmap = RealMap(
mapimagepath,
(51.0442, 3.7268),
(51.0405, 3.7242),
550,
800)
parent.setGeometry(0,0,self.realmap.width, self.realmap.height)
self.refreshspeed = 5000
self.mapNodes = {}
def addNode(self, scanner):
coord = self.realmap.convertLatLon2Pix((scanner.latitude, scanner.longitude))
self.mapNodes[scanner.sensorid] = MapNode(scanner, coord[0], coord[1])
# type: 4 --> changenode ,
#((change, gem_ref, procentuele verandering ref), scanner object)
def changeNode(self, sensorid, branchdata):
self.mapNodes[sensorid].calcDanger(branchdata[2])
def paintEvent(self, event):
painter = QtGui.QPainter(self)
rect = self.contentsRect()
#teken achtergrond
self.realmap.drawRealMap(painter)
#teken nodes
for sensorid, mapNode in self.mapNodes.items():
mapNode.drawMapNode(painter, self.realmap)
######################################################################
class RealMap:
def __init__(self, path, coordRightTop,
coordLeftBot, width, height, pixpermet = 2.6):
self.path = path
self.coordLeftBot = coordLeftBot
self.coordRightTop = coordRightTop
self.width = width
self.height = height
self.realdim = self.calcRealDim()
self.pixpermet = pixpermet
def drawRealMap(self, painter):
image = QtGui.QImage(self.path)
painter.drawImage(0,0,image)
######################################################################
class MapNode:
dangertocolor = {"normal":"graphics//gradients//green.png",
"elevated":"graphics//gradients//orange.png",
"danger":"graphics//gradients//red.png"}
def __init__(self, scanner, x, y, danger = 0):
self.scanner = scanner
self.x = x
self.y = y
self.danger = 'normal'
self.calcDanger(danger)
def drawMapNode(self, painter, realmap):
radiusm = self.scanner.range
radiusp = radiusm*realmap.pixpermet
factor = radiusp/200 # basis grootte gradiƫnten is 200 pixels.
icon = QtGui.QImage("graphics//BT-icon.png")
grad = QtGui.QImage(MapNode.dangertocolor[self.danger])
grad = grad.scaled(grad.size().width()*factor, grad.size().height()*factor)
painter.drawImage(self.x-100*factor,self.y-100*factor, grad)
painter.drawImage(self.x-10, self.y-10,icon)
painter.drawText(self.x-15, self.y+20, str(self.scanner.sensorid) + '-' + str(self.scanner.name))
An object is made through our application class:
mapview = gfx.MapView(g_image)
mapview.show()
So the first question is. What are we doing wrong in the paintEvent method?
Secondly question
Is there a way to make the paintevent not be called at EVERY RANDOM THING that happens ? (like mouseovers, etc)?
I tried something like:
def paintEvent(self, event):
if(isinstance(event, QtGui.QPaintEvent)):
painter = QtGui.QPainter(self)
rect = self.contentsRect()
#teken achtergrond
self.realmap.drawRealMap(painter)
#teken nodes
for sensorid, mapNode in self.mapNodes.items():
mapNode.drawMapNode(painter, self.realmap)
else:
pass
This 'works' but is to general I guess.. It actually makes the error appear a lot faster then without the conditional.
When in your gfx.py you have:
self.repaint(self.map.contentsRect())
self.update(self.map.contentsRect())
Calling repaint and calling update one right after another is redundant. And if a paint event comes through that handler and you call repaint() there, you are asking for infinite recursion.
Take note of any Warnings or Notes in the documentation.
http://doc.qt.io/qt-4.8/qwidget.html#update
http://doc.qt.io/qt-4.8/qwidget.html#repaint
http://doc.qt.io/qt-4.8/qwidget.html#paintEvent
I don't see the cause for your other error right off, but it probably has to do with QPainter getting used when it shouldn't...
http://doc.qt.io/qt-4.8/qpainter.html#begin
http://doc.qt.io/qt-4.8/qpainter.html#details
Hope that helps.

Categories

Resources