I have created different shapes like circle/rect etc in my program using BufferedPaintDC on event. Now i want to save the file as I click the saveas button in the menu option. For that I am using memoryDC and save the contents as bmp file.
def Saveas(self,event):
dlg = wx.FileDialog(self, "Choose a file", self.dirname, "", "*.*", \
wx.SAVE | wx.OVERWRITE_PROMPT)
if dlg.ShowModal() == wx.ID_OK: # user enters filename as something.bmp
self.show_bmp = wx.StaticBitmap(self)
w, h = self.GetClientSize()
draw_bmp = wx.EmptyBitmap(w, h)
c = wx.MemoryDC(draw_bmp)
c.SetBrush(wx.Brush('white'))
c.Clear()
c.SetPen(wx.Pen("purple", 15))
c.DrawRectangle(30,30,60,60) ### ??????####
myimage = self.show_bmp.GetBitmap()
self.filename=dlg.GetFilename()
name = os.path.join('C:\mad', self.filename)
myimage.SaveFile(name, wx.BITMAP_TYPE_JPEG)
self.filename=name
dlg.Destroy()
Now my problem is how do I get the things drawn by the buffered dc on the " c ", so that they can be then converted to image?? I hope my question is clear.As u can see I am drawing the rectangle on the "c" and that is being converted to an image. But I want to get the shapes created on ONPaint . How do I extract that?
Thanks
What you're asking is very close to saying you want to take a screenshot. Although technically grabbing a copy of what the window currently looks like is not the same as cloning what the OnPaint does, it's possible it would do the job for you.
If it doesn't work, take note of the technique, including the use of DC.Blit(), as those would be the tools you'd use.
See this wxpython-users mailing list post by Andrea Gavana for image-grabbing code.
Edit: if the problem is that because you're doing all your drawing inside the EVT_PAINT handler, then you probably need a different technique. Draw everything from a different routine to a pre-allocated buffer bitmap. Inside the OnPaint, which is just how the image actually gets to the screen, you don't draw, you just copy the already-drawn bitmap. The buffer bitmap persists between OnPaint calls (and in fact is basically independent of OnPaint), so you can add a Save() routine that works rather simply as well. See the wxPyWiki DoubleBuffererDrawing page for various snippets that will show you how to do that. (Also note, this will be a bit of a learning curve, so ask for more help if it's not enough.)
Related
I noticed that if using windows focus detection, the rect value will change depending on what part of the program you are in. I want the size of the main window only if possible.
I've managed to get around some of these issues by checking the window title. If the title is empty, it's a dropdown menu, so ignore. If it is titled "Open", "Save As", etc, then it's obviously a dialogue box and ignore. However, the message "Do you want to quit without saving?" seems to have only the title of the program itself, so that slips through the check.
I just tested the heights of those boxes to see if there was a constant value to ignore, but each program seems to have different heights. I could possibly just ignore anything under a certain resolution, but I'd prefer not to as it's not actually solving the issue, and there may be some rare cases where it needs to use that particular resolution.
Here's the bits of code I currently use from pywin32 to do the detection. I also have the ctypes alternatives, but it's basically the same thing.
import win32gui
import win32process
import psutil
hwnd = win32gui.GetForegroundWindow()
print 'pid:', win32process.GetWindowThreadProcessId(hwnd)[1]
print 'rect:', win32gui.GetWindowRect(hwnd)
print 'name:', win32gui.GetWindowText(hwnd)
print 'exe:', psutil.Process(win32process.GetWindowThreadProcessId(hwnd)[1]).name()
Basically I want the size of the main window at all times, no matter which other windows are loaded on top of it. I've only found GetWindowRect and GetClientRect which both do the same thing, just wondering if I'm missing something?
Managed to get to the solution by realising it was basically the last parent window I needed:
def _get_parent(self):
while True:
try:
parent = win32gui.GetParent(hwnd)
except UnboundLocalError:
hwnd = win32gui.GetForegroundWindow()
else:
if parent:
hwnd = parent
else:
break
return hwnd
Basically it just keeps checking if the current window has a parent until there are no more parents. Not super efficient but does the job. I've only really tested it on paint > save as > are you sure you want to replace?, but it gets the correct hwnd value for the main window and returns a constant resolution.
I have a function call on button click which is used to display a number of cuboids. However i want the ability to rotate my frame on user mouse drag so as to get the desired viewing angle (as preferred by user)
However, i cant seem to rotate as well as zoom on my display window.
Edit: What i found was upon a right click drag it changes the viewing angle. However it does not get reflected. Weirdly enoughn it is reflected only after i maximize and then restore the screen. Is there some setting i can do to make it work seamlessly.
Also, the first display happens after i move the window from its initial position. Else its just blank upon launch!! Please advise
def testDraw():
global containers
myscene = display(title='Diagram')
#myscene.material = materials.wood
myscene.select()
myscene.exit=False
#myscene.userspin = True
myscene.userspin = 1
myscene.forward = (.1, -.3, -1)
mybox = [['','','','','','','',''] for x in range(len(containers))]
for x in range(len(containers)):
for y in range(len(containers[x])):
mybox[x]=box(pos=(float(containers[x][1])+float(containers[x][2])/2,float(containers[x][3])+float(containers[x][4])/2,float(containers[x][5])+float(containers[x][6])/2),width=float(containers[x][6]),height=float(containers[x][4]),length=float(containers[x][2]))
#,color='color.'+containers[x][7]
#mybox = box(pos=(2.5,1,5), length=10, height=2, width=5,color=color.blue)
#mybox2 = box(pos=(12.5,1,5), length=10, height=2, width=5,color=color.green)
#Name,length0,length1,height0,height1,width0,width1,color
containers=[['Container_1','`enter code here`0','2','0','7','0','2','blue'],
['Container_2','2','5','0','10','0','2','green'],
['Container_3','7','10','0','5','0','2','red']]
I don't understand what is meant by "it does not get reflected". What is "it"? Also, you haven't provided a runnable program, so it' difficult to know what the context is.
I'll advertise that a better place to pose VPython questions is in the VPython forum at
https://groups.google.com/forum/?fromgroups&hl=en#!forum/vpython-users
Renpy uses a lot of python and custom made code, in order to show text that is displayed on screen using the say statement.
After running into some troubles with the nvl mode within renpy, I found it necessary to know how many lines are going to be displayed on screen (taking into account the font size, naturally and the size of the text window).
So my question:
As I didn't find anything in the documentation in regards to that, I'm wondering if there is any command or other possibility to precalculate the height of a text that is to be displayed?
get_virtual_layout() is part of class Text in text.py.
I copied this from text.py:
# Find the virtual-resolution layout.
virtual_layout = self.get_virtual_layout()
# The laid-out size of this Text.
vw, vh = virtual_layout.size
This looks promising, I think.
With the virtual text size (width, height) you could possibly calculate the lines of text by using the text window size (width, height).
pseudo code:
lines = int(vw/text_window.width)
#the text height would then be
text_height_needed = int(lines*vh)
# does it fit in completely
complete_text_in_window = text_window.height >= text_height_needed
# visible lines
visible_lines = int(text_window.height/vh)
Also, it is worth to take a deeper look at text.py(e.g. def render(self, width, height, st, at)), in order to get to know the use of virtual_layout.
I hope it helps somehow.
Update:
def render(...) initializes the virtual layouts, so get_virtual_layout() is not None anymore, but represents an instance of Layout() with scaled width and height.
I'm working (still) on a book binding application, and to make it aesthetically pleasing, I've added a thumbnail to every page you drag in. It works just fine, but the only problem is that when I drag in a whole book (i.e. 400 images), it freezes completely until it's done.
Here's my simple drop code:
def fileDropped(self, file):
f = str(file[-1])
if os.path.splitext(f)[1][1:] != 'tif':
reply = QtGui.QMessageBox.question(self, 'Message', 'All files must be TIF images. Would you like me to convert a copy of your file to the TIF format?', QtGui.QMessageBox.Yes | QtGui.QMessageBox.No, QtGui.QMessageBox.No)
if reply == QtGui.QMessageBox.Yes:
if not os.path.exists('./djvu_backup/'): os.mkdir('./djvu_backup/')
if f not in self.getChildren(self.ui.pageList): # It's a custom method. It does what it looks like it does.
icon = QtGui.QIcon(f)
pixmap = icon.pixmap(72, 72)
icon = QtGui.QIcon(pixmap)
item = QtGui.QListWidgetItem(f, self.ui.pageList)
item.setIcon(icon)
item.setStatusTip(f)
return True
Also, just as a side question, as you can see in the code, f = str(file[-1]). I have to select the last element from my dropped files array every time the method is called, as it is called for every file dropped, even if they are dropped all at once. Is there a reason/workaround for this?
Thank you!
You could try to make the thumbnailing faster, but that would only increase the size of the book that you could drop before you'd notice the problem. The answers are to either only thumbnail a page as it's displayed, or relegate the thumbnailing to a background thread and update the display as each is finished.
I know this is really simple but have you considered using a QProgressBar just so the users can see that the program is still processing when it appears to be frozen?
Is there any reason why the position, pos, flag doesn't seem to work in the following example?
dlg = wx.MessageDialog(
parent=self,
message='You must enter a URL',
caption='Error',
style=wx.OK | wx.ICON_ERROR | wx.STAY_ON_TOP,
pos=(200,200)
)
dlg.ShowModal()
dlg.Destroy()
The documentation is here: http://www.wxpython.org/docs/api/wx.MessageDialog-class.html
'self' is a reference to the frame. I'm running in Windows Vista, python26, wxpython28. The message dialog always appears to be in the middle of the screen.
If for some reason it's not possible to position the dialog, is there anyway to at least restrict the dialog to be in the frame, rather than just the center of the screen?
It seems to be a bug and i think you should file the same. for time being you can user your own dervied dialog class to center it as you wish. Also instead of wx.MessageDialog you can use wx.MessageBox, it will save you few lines.