How do you position a wx.MessageDialog (wxPython)? - python

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.

Related

Trouble Adding The Save Menu Item To My GUI

I used PythonCard to make my GUI and the only menu items I have currently are Save and Exit. Exit is fully functional and closes the program; but when I click on Save nothing happens. I can only assume the command is wrong. I have done some thorough searching and have found nothing. The command I used was "save". Obviously this is not correct. Can anyone tell me what command I need to use?
Resource File
There's really not enough information here. You need to bind EVT_MENU to an event handler for the save menu item. Then in the event handler, you'll have to define what the "Save" behavior is. For example, does it save to a database, a file, or what? Once you have that figured out, you put it in your handler and do it or have the handler spin up a thread.
EDIT: If you want to save a file, see the wx.FileDialog and set the style flag to wx.SAVE. Something like this should work:
def onSaveFile(self, event):
"""
Create and show the Save FileDialog
"""
wildcard = "Text (*.txt)|*.txt|" \
"All files (*.*)|*.*"
dlg = wx.FileDialog(
self, message="Save file as ...",
defaultDir=self.currentDirectory,
defaultFile="", wildcard=wildcard, style=wx.SAVE
)
if dlg.ShowModal() == wx.ID_OK:
path = dlg.GetPath()
print "You chose the following filename: %s" % path
dlg.Destroy()
See also the wxPython demo, or this or the docs

wxpython change message dialog font?

Python 2.7.3 x64
wxPython 2.8 x64
I'm having trouble changing the font of the wxpython message dialog box. I'd like to use a fixed-width font (I think wxFAMILY_MODERN is) to control the formatting of the output. Here's the code I'm using to test with ...
def infDialog (self, msg, title):
""" Display Info Dialog Message """
font = wx.Font(14, wx.MODERN, wx.NORMAL, wx.NORMAL)
style = wx.OK | wx.ICON_INFORMATION | wx.STAY_ON_TOP
dialog = wx.MessageDialog(self, msg, title, style)
dialog.CenterOnParent()
dialog.SetFont(font)
result = dialog.ShowModal()
if result == wx.ID_OK:
print dialog.GetFont().GetFaceName()
dialog.Destroy()
return
# End infDialog()
But the results when I click OK are always "Arial". Any thoughts? Perhaps I need to make a custom dialog class?
Thanks,
-RMWChaos
The wx.MessageDialog is a wrapper around the OS / system message dialog. I suspect each OS only allows so much editing or none at all. So yes, using a custom wx.Dialog or the generic message dialog widget (wx.lib.agw.genericmessagedialog) is the way to go if fonts are important.
I was looking all over the internet and found that no one actually took the time to answer the question, instead just telling users to create their own dialog class. There is actually an easy way in which you should be able to change the font of your message dialog. Grabbing the dialog's textCtrl object and then setting the font of that object should do the trick.
Simply replace:
dialog.SetFont(font)
with
txt_ctrl = dialog.text
txt_ctrl.SetFont(font)
Let me know if this works for you.

Customising location-sensitive context menu in QTextEdit

I am trying to adjust the context menu in a QTextEdit. I have succeeded in getting access to and then displaying the default menu with the following code:
class LinkTextBrowser(QTextBrowser):
def contextMenuEvent(self, event):
menu = self.createStandardContextMenu(event.pos())
# do stuff to menu here
menu.popup(event.globalPos())
However, this does not work for location-sensitive clicks. The case in question is the "Copy Link Location" item in a QTextBrowser's right click menu, which is only enabled if you right click on a link, for obvious reasons. I can't get it to ever be enabled. I suspect I am passing the wrong position to createStandardContextMenu, but I can't figure out the correct position to feed it.
I have tried both event.globalPos() and event.pos(), neither of which work. I also looked at the source code for QTextEdit, but didn't get anywhere. What position is it expecting?
Edit: Update: It appears the problem is the scrolling in the TextBrowser; if I scroll to the top of the window and use event.pos() it behaves. I don't have working code yet, but correcting for the scroll is the solution.
(Specifically, I want to disconnect the signal emitted by the Copy Link Location action and connect it to my own function so I can adjust the URL before copying it to the clipboard, allowing me to make links absolute and so forth before copying, and I have no particular desire to re-write the working bits.)
Here is the working transform of the coordinates:
class LinkTextBrowser(QTextBrowser):
def contextMenuEvent(self, event):
self.link_pos = event.pos()
# correct for scrolling
self.link_pos.setX(self.link_pos.x() + self.horizontalScrollBar().value())
self.link_pos.setY(self.link_pos.y() + self.verticalScrollBar().value())
menu = self.createStandardContextMenu(self.link_pos)
# do stuff to menu
menu.popup(event.globalPos())
Try self.mapToGlobal(event.pos()), it should take into account scroll position.
Maybe you can try something like:
QMenu *menu = new QMenu();
menu->addAction(...);
menu->exec(textEdit->mapToGlobal(pos));
It's C++ but I'm sure that you can easy convert it to python.

wxPython: Exit Fullscreen

To display a wxPython window in full screen mode you use:
ShowFullScreen(True)
How do you get out of full screen though? I've tried the obvious way:
ShowFullScreen(True)
sleep(5)
ShowFullScreen(False)
This doesn't work though. When I run the script, nothing appears. After 5 seconds a window roughly 200x250 appears in the top-left corner of the screen, without anything inside of it. It doesn't appear to have any borders either.
If I change this to
showFullScreen(True)
then I get stuck with a full screen window that I have to use Alt + F2 -> xkill to get out of.
It looks like you need to Show() the window first. (According to the documentation, you shouldn't have to. Maybe this is a bug.) I tested on Mac OS X and Windows - they both exhibit issues if you don't call Show() first.
Also note that you shouldn't sleep in the main GUI thread. You'll hang the UI. Using CallLater is one potential solution, as shown in my example.
Working example:
import wx
def main():
app = wx.PySimpleApp()
frame = wx.Frame(None, -1, 'Full Screen Test')
frame.Show()
frame.ShowFullScreen(True)
wx.CallLater(5000, frame.ShowFullScreen, False)
app.MainLoop()
if __name__ == '__main__':
main()
The documentation for ShowFullScreen reads:
ShowFullScreen(show, style=wx.FULLSCREEN_ALL)
Depending on the value of show parameter the window is either shown full screen or restored to its normal state.
Parameters:
show (bool)
style (long): is a bit list containing some or all of the following values, which indicate what elements of the window to hide in full-screen mode:
wx.FULLSCREEN_NOMENUBAR
wx.FULLSCREEN_NOTOOLBAR
wx.FULLSCREEN_NOSTATUSBAR
wx.FULLSCREEN_NOBORDER
wx.FULLSCREEN_NOCAPTION
wx.FULLSCREEN_ALL (all of the above)
So put your Full Screen toggle event/s in a Menu and start full screen mode with:
self.window.ShowFullScreen(True, style=(wx.FULLSCREEN_NOTOOLBAR | wx.FULLSCREEN_NOSTATUSBAR |wx.FULLSCREEN_NOBORDER |wx.FULLSCREEN_NOCAPTION))
Note that I omitted wx.FULLSCREEN_NOMENUBAR, in this way you will still be able to access the menu to turn full screen mode off again.

Saving wx widget contents to a file

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.)

Categories

Resources