I want to create one canvas widget, which allows user to draw on it. I am using canvas.bind for it. What I want is the size of canvas should be 32x32 originally, but when it is displayed, it should be like zoomed version of original widget, without resizing the original canvas. I have to use smaller size ( 32x32 ) for further processing on the drawn picture. Meaning if canvas size is 32x32 then it should be displayed as 512x512 size for drawing purpose , but 32x32 size for processing purpose. I tried with canvas.Scale but it seems that it will not be helpful for this purpose because it resizes original widget. Can someone please guide me? I use python2.7.
Thanks!
If I completely understand your problem, then I think this would be your solution:
from __future__ import division
import Tkinter
ORIGINAL_WIDTH = 32
ORIGINAL_HEIGHT = 32
WINDOW_WIDTH = 512
WINDOW_HEIGHT = 512
WIDTH_RATIO = WINDOW_WIDTH/ORIGINAL_WIDTH
HEIGHT_RATIO = WINDOW_HEIGHT/ORIGINAL_HEIGHT
class App(Tkinter.Tk):
def __init__(self, *args, **kwargs):
Tkinter.Tk.__init__(self, *args, **kwargs)
self.canvas = canvas = Tkinter.Canvas( self,
highlightthickness = 0,
width = WINDOW_WIDTH,
height = WINDOW_HEIGHT )
self.canvas.pack()
# Create a list for holding canvas objects
self.scene = []
# Draw objects and scale them
self.draw()
self.zoom()
def draw(self):
canvas = self.canvas
# Draw rectangles within the range of 0..32 x 0..32
rect1 = canvas.create_rectangle( 2, 0, 30, 2, fill='black' )
rect2 = canvas.create_rectangle( 0, 2, 2, 30, fill='black' )
rect3 = canvas.create_rectangle( 30, 2, 32, 30, fill='black' )
rect4 = canvas.create_rectangle( 2, 30, 30, 32, fill='black' )
rect5 = canvas.create_rectangle( 10, 10, 22, 22, fill='black' )
self.scene.extend( (rect1, rect2, rect3, rect4, rect5) )
def zoom(self):
canvas = self.canvas
# Scale all objects on scene
for item in self.scene:
canvas.scale( item, 0, 0, WIDTH_RATIO, HEIGHT_RATIO )
App().mainloop()
Related
Not sure if what I am trying to do is wrong or impossible. Here is my code:
import pygame
class Window(object):
def __init__(self, (width, height), color, cap=' '):
self.width = width
self.height = height
self.color = color
self.cap = cap
self.screen = pygame.display.set_mode((self.width, self.height))
def display(self):
self.screen
#screen =
pygame.display.set_caption(self.cap)
self.screen.fill(self.color)
class Ball(object):
def __init__(self, window, (x, y), color, size, thick=None):
self.window = window
self.x = x
self.y = y
self.color = color
self.size = size
self.thick = thick
def draw(self):
pygame.draw.circle(self.window, self.color, (self.x, self.y),
self.size, self.thick)
def main():
black = (0, 0, 0)
white = (255, 255, 255)
screen = Window((600, 600), black, 'Pong')
screen.display()
ball = Ball(screen, (300, 300), white, 5)
ball.draw()
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
pygame.display.flip()
pygame.quit()
main()
This is the error I get:
Traceback (most recent call last):
File "C:\Users\acmil\Desktop\Team 7\newPongLib.py", line 47, in <module>
main()
File "C:\Users\acmil\Desktop\Team 7\newPongLib.py", line 36, in main
ball.draw()
File "C:\Users\acmil\Desktop\Team 7\newPongLib.py", line 28, in draw
self.size, self.thick)
TypeError: argument 1 must be pygame.Surface, not Window
I don't understand if i make a Window object why it won't draw a ball to the screen. Any help is appreciated.
Change your Ball class to the following:
class Ball(object):
def __init__(self, window, (x, y), color, size, thick=0):
self.window = window
self.x = x
self.y = y
self.color = color
self.size = size
self.thick = thick
def draw(self):
pygame.draw.circle(self.window.screen, self.color, (self.x, self.y),
self.size, self.thick)
I made two modifications to your code.
First, as for the error you were getting, you were passing in a custom Window object that you had defined instead of the pygame's Screen object that pygame was expecting. Check out the documentation on this function here.
Second, your original constructor defined thick=None by default, but that pygame function expects an int, so I changed it to thick=0.
It should work after these two changes. Let me know if you still are having issues!
I am trying to display the webcam stream as well as write the video to a file simultaneously.But while am writing, it freezes the live stream. The problem is that OpenCV uses a loop to record video,the program gets stuck in the OpenCV loop and the user is unable to continue.It doesn't listen for user response. How can i simultaneously record video and listen for user responses?
code iam using :
import wx
import vlc
import os
import user
import numpy as np
import time
import cv, cv2
class MainWindow(wx.Panel):
def __init__(self, parent,capture):
wx.Panel.__init__(self, parent)
mainSizer = wx.BoxSizer(wx.VERTICAL)
# video
videoWarper = wx.StaticBox(self,size=(640,480)
videoBoxSizer = wx.StaticBoxSizer(videoWarper, wx.VERTICAL)
videoFrame = wx.Panel(self, -1,size=(640,480))
capture = ShowCapture(videoFrame, capture)
videoBoxSizer.Add(videoFrame,0)
mainSizer.Add(videoBoxSizer,0)
parent.Centre()
self.Show()
self.SetSizerAndFit(mainSizer)
# Panels
# The first panel holds the video and it's all black
self.videopanel = wx.Panel(self, -1)
self.videopanel.SetBackgroundColour(wx.BLACK)
# The second panel holds controls
ctrlpanel = wx.Panel(self, -1 )
self.timeslider = wx.Slider(ctrlpanel, -1, 0, 0, 1000)
self.timeslider.SetRange(0, 1000)
record = wx.Button(ctrlpanel, label="Record")
end = wx.Button(ctrlpanel, label="End")
# Bind controls to events
self.Bind(wx.EVT_BUTTON, self.OnRecord, record)
self.Bind(wx.EVT_BUTTON, self.OnEnd, end)
# Give a pretty layout to the controls
ctrlbox = wx.BoxSizer(wx.VERTICAL)
box = wx.BoxSizer(wx.HORIZONTAL)
# box contains some buttons and the volume controls
box.Add(record)
box.Add(end)
# Merge box to the ctrlsizer
ctrlbox.Add(box, flag=wx.EXPAND, border=10)
ctrlpanel.SetSizer(ctrlbox)
# Put everything togheter
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(ctrlpanel, flag=wx.EXPAND | wx.BOTTOM | wx.TOP, border=10)
self.SetSizer(sizer)
self.SetMinSize((350, 300))
# VLC player controls
self.Instance = vlc.Instance()
self.player = self.Instance.media_player_new()
def OnRecord(self, evt):
fourcc = cv2.cv.CV_FOURCC('D', 'I', 'V', 'X')
out = cv2.VideoWriter('video.avi', fourcc, 8.0, (640, 480))
counter = 0
while counter < 1:
ret,frame = capture.read()
out.write(frame)
def OnEnd(self, evt):
out = cv2.VideoWriter('video.avi', fourcc, 8.0, (640, 480))
out.release()
cv2.destroyAllWindows()
class ShowCapture(wx.Panel):
def __init__(self, parent, capture, fps=8):
wx.Panel.__init__(self, parent, wx.ID_ANY, (0,0), (640,480))
self.capture = capture
ret, frame = capture.read()
height, width = frame.shape[:2]
parent.SetSize((width, height))
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
self.bmp = wx.BitmapFromBuffer(width, height, frame)
self.timer = wx.Timer(self)
self.timer.Start(1000./fps)
self.Bind(wx.EVT_PAINT, self.OnPaint)
self.Bind(wx.EVT_TIMER, self.NextFrame)
def OnPaint(self, evt):
dc = wx.BufferedPaintDC(self)
dc.DrawBitmap(self.bmp, 0, 0)
def NextFrame(self, event):
ret, frame = self.capture.read()
if ret:
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
self.bmp.CopyFromBuffer(frame)
self.Refresh()
capture = cv2.VideoCapture(-1)
app = wx.App(False)
frame = wx.Frame(None, title='CamGUI')
panel = MainWindow(frame, capture)
frame.Show()
app.MainLoop()
Does raspberry pi capable of Read/write the video parallely or it hurts the performance of pi?
Hope for experts advice :)
Add a timer, that will allow you to test for input and other changes during the execution of the application.
wx.timer
I have the following code:
QGraphicsScene* pScene = new QGraphicsScene(this);
ui->graphicsView->setScene(pScene);
pScene->addRect(0, 0, 200, 200);
QGraphicsRectItem* pRect1 = pScene->addRect(40, 40, 100, 100);
QGraphicsRectItem* pRect2 = new QGraphicsRectItem(20, 20, 19, 19, pRect1);
QPointF pf1 = pRect1->pos();
QPointF pf2 = pRect2->pos();
QPointF pf3 = pRect2->mapFromParent(pRect1->pos());
QPointF pf4 = pRect2->mapToParent(pRect2->pos());
QPointF spf1 = pRect1->scenePos();
QPointF spf2 = pRect2->scenePos();
Nothing special, just a QGraphicsView with QGraphicsScene and a few QGraphicsRectItem(s).
Question: Why do all the points (pf1, pf2, pf3, pf4 and even spf1, spf2) equal QPointF(0.0, 0.0) after execution?
I'm using Qt 5.4.1.
From my understanding spf1 must be QPointF(40.0, 40.0) and spf2 must be QPointF(20.0, 20.0).
If you will look in the documentation then you will find:
QGraphicsRectItem *QGraphicsScene::addRect(const QRectF &rect, const
QPen &pen = QPen(), const QBrush &brush = QBrush())
Creates and adds a rectangle item to the scene, and returns the item
pointer. The geometry of the rectangle is defined by rect, and its pen
and brush are initialized to pen and brush. Note that the item's
geometry is provided in item coordinates, and its position is
initialized to (0, 0). For example, if a QRect(50, 50, 100, 100) is
added, its top-left corner will be at (50, 50) relative to the origin
in the items coordinate system
.As result, the coordinate of the Item is (0,0) but you can set it with:
pRect1->setPos(QPoint(30,30));
and look what will happen. Hope it will help you to understand QGraphicsScene coordinate system!
P.S.:
QGraphicsRectItem* pRect1 = pScene->addRect(0, 0, 100, 100);
QGraphicsRectItem* pRect2 = pScene->addRect(0, 0, 20, 20);
pRect1->setPos(QPoint(40,40));
pRect2->setPos(QPoint(20,20));
In this jsfiddle I have a Raphael canvas with two images. The first one is the complete image (not clipped) and the second one is the same image but clipped. For some reason the second image is not showing up. What's wrong with this code?
javascript:
var paper = Raphael(document.getElementById('canvas'));
var img = paper.image('http://designsbynickthegeek.com/wp-content/uploads/2012/01/social-header.png', 0, 0, 480, 259 );
var img2 = paper.image('http://designsbynickthegeek.com/wp-content/uploads/2012/01/social-header.png', 0, 300, 40, 40 );
img2.attr({'clip-rect': "0,0,40,40" });
You made two mistakes.
First: You scaled your image down. Change
var img2 = paper.image('http://designsbynickthegeek.com/wp-content/uploads/2012/01/social-header.png',
0, 300, 40, 40 );
to
var img2 = paper.image('http://designsbynickthegeek.com/wp-content/uploads/2012/01/social-header.png',
0, 300, 480, 259 );
Second: You used the wrong clipping coordinates. Change
img2.attr({'clip-rect': "0,0,40,40" });
to
img2.attr({'clip-rect': "0,300,40,40" });
see your edited fiddle here.
I have a rounded rectangle that I make like so
dc.RoundRect(textBorder, CPoint(20, 20));
Later on I draw a line through it about 1/3 of the way down.
dc.LineTo(textBorder.right, textBorder.top + 15);
Now I would like to fill just the part above the line with a solid color. In other words I need to fill a partially rounded rectangle, because the top of the rectangle is rounded, but the bottom of it is truncated by the line. Is there an easy way to do this?
Have you tried using a combination of CreateRoundRectRegion and then FillRgn to fill the non-rectangular area?
This the example given in the docs for CreateRoundRectRegion:
CRgn rgnA, rgnB, rgnC;
VERIFY(rgnA.CreateRoundRectRgn( 50, 50, 150, 150, 30, 30 ));
VERIFY(rgnB.CreateRoundRectRgn( 200, 75, 250, 125, 50, 50 ));
VERIFY(rgnC.CreateRectRgn( 0, 0, 50, 50 ));
int nCombineResult = rgnC.CombineRgn( &rgnA, &rgnB, RGN_OR );
ASSERT( nCombineResult != ERROR && nCombineResult != NULLREGION );
CBrush brA, brB, brC;
VERIFY(brA.CreateSolidBrush( RGB(255, 0, 0) ));
VERIFY(pDC->FillRgn( &rgnA, &brA)); // rgnA Red Filled
VERIFY(brB.CreateSolidBrush( RGB(0, 255, 0) ));
VERIFY(pDC->FillRgn( &rgnB, &brB)); // rgnB Green Filled
VERIFY(brC.CreateSolidBrush( RGB(0, 0, 255) )); // rgnC Blue
VERIFY(pDC->FrameRgn( &rgnC, &brC, 2, 2 ));
In general, when you want to do something with non-rectangular areas you have to start looking into regions.