wxpython , passing boolean flag for background checking - python

How can i get a value from button click from my frame?
btnYes = wx.Button(panel, -1, "OK")
self.Bind(wx.EVT_BUTTON, self.clickYes, btnYes)
def clickYes(self, evt):
print "clicked Yes"
self.Close()
whenever a user click yes , i want to get a value to check in other module. Something like confirmation flag. When user is confirmed one item then carrying on doing other items. The confirmation flag i will be using is here below :
def my_methodABC():
matchList = []
for x, y in product(d1rows, d2rows):
if userConfirmedFromWxPythonClickYesButton():
matchList.append(abc)
return matchList

Use a MessageDialog. There are lots of examples on the web. Here are a couple:
http://wiki.wxpython.org/MessageBoxes
http://www.blog.pythonlibrary.org/2010/06/26/the-dialogs-of-wxpython-part-1-of-2/
And here's a really simple example:
import wx
########################################################################
class MainFrame(wx.Frame):
""""""
#----------------------------------------------------------------------
def __init__(self):
"""Constructor"""
wx.Frame.__init__(self, None, title="Test")
panel = wx.Panel(self)
btn = wx.Button(panel, label="Ask Question")
btn.Bind(wx.EVT_BUTTON, self.showMessageDlg)
#----------------------------------------------------------------------
def showMessageDlg(self, event):
"""
Show a message
"""
msg = "Do you want to continue?"
title = "Question!"
style = wx.YES_NO|wx.YES_DEFAULT|wx.ICON_QUESTION
dlg = wx.MessageDialog(parent=None, message=msg,
caption=title, style=style)
result = dlg.ShowModal()
if result == wx.ID_YES:
print "User pressed yes!"
else:
print "User pressed no!"
dlg.Destroy()
if __name__ == "__main__":
app = wx.App(False)
frame = MainFrame()
frame.Show()
app.MainLoop()
You would probably want to call your match list method if the user pressed the yes button rather than just printing a message to stdout though.

Related

On button click open wxpython TextEntryDialog and get multiple input from user

I want to open a TextEntryDialog, when user clicks the button. So if i have a button in the parent frame which i am going to bind this way:
self.Bind(wx.EVT_BUTTON, self.OnAddNew, self.add_new_btn)
Now i have to open a TextEntryDialog when user clicks the button add_new. I want to make textentrydialog somewthing like this
Python, Using wxPython to get multiple input from user
How can i do that? Do i need to just paste that code in ` def OnAddNew(self, event):
Here is the pastebin link to my code: https://pastebin.com/UEYscgFa
I have created class inside a function, so is it possible to do in that way?
NO!
GetData is a class in its own right.
That code already provides you with the method.
The MyFrame is all fluff, to create a standalone working example.
def OnButton(self,event):
dlg = GetData(parent = self.panel)
dlg.ShowModal()
if dlg.result_name:
self.log.AppendText("Name: "+dlg.result_name+"\n")
self.log.AppendText("Surname: "+dlg.result_surname+"\n")
self.log.AppendText("Nickname: "+dlg.result_nickname+"\n")
else:
self.log.AppendText("No Input found\n")
dlg.Destroy()
Edit: I don't understand where the instructions in my comments eluded you but for my sins, here is your code cleaned up and edited as in the comments.
import sqlite3
import wx
import os
class Example(wx.Frame):
def __init__(self, parent, title):
super(Example, self).__init__(parent, title=title, size=(1000,800))
self.inter_list = list()
self.plot_list = list()
self.InitUI()
self.Layout()
self.Centre()
self.Show()
def InitUI(self):
self.p = wx.Panel(self)
bs = wx.BoxSizer(wx.VERTICAL)
gs = wx.GridSizer(10, 18, 5, 5)
bs.Add(gs, 1, wx.EXPAND)
self.search_btn=wx.Button(self.p,-1,"Search!")
self.search_btn.Bind(wx.EVT_BUTTON, self.OnSearch, self.search_btn)
bs.Add(self.search_btn,0,wx.ALIGN_CENTER)
self.p.SetSizer(bs)
def OnSearch(self, event):
dlg = GetData(parent = self.p)
dlg.ShowModal()
if dlg.result_name:
print "Name: "+dlg.result_name+"\n"
print "Surname: "+dlg.result_surname+"\n"
print "Nickname: "+dlg.result_nickname+"\n"
else:
print "No Input found\n"
dlg.Destroy()
class GetData(wx.Dialog):
def __init__(self, parent):
wx.Dialog.__init__(self, parent, wx.ID_ANY, "Name Input", size= (650,220))
self.p = wx.Panel(self,wx.ID_ANY)
self.lblname = wx.StaticText(self.p, label="Name", pos=(20,20))
self.name = wx.TextCtrl(self.p, value="", pos=(110,20), size=(500,-1))
self.lblsur = wx.StaticText(self.p, label="Surname", pos=(20,60))
self.surname = wx.TextCtrl(self.p, value="", pos=(110,60), size=(500,-1))
self.lblnick = wx.StaticText(self.p, label="Nickname", pos=(20,100))
self.nickname = wx.TextCtrl(self.p, value="", pos=(110,100), size=(500,-1))
self.saveButton =wx.Button(self.p, label="Save", pos=(110,160))
self.closeButton =wx.Button(self.p, label="Cancel", pos=(210,160))
self.saveButton.Bind(wx.EVT_BUTTON, self.SaveConnString)
self.closeButton.Bind(wx.EVT_BUTTON, self.OnQuit)
self.Bind(wx.EVT_CLOSE, self.OnQuit)
self.Show()
def OnQuit(self, event):
self.result_name = None
self.Destroy()
def SaveConnString(self, event):
self.result_name = self.name.GetValue()
self.result_surname = self.surname.GetValue()
self.result_nickname = self.nickname.GetValue()
self.Destroy()
app = wx.App()
Example(None, title = 'Raman Spectroscopy Database')
app.MainLoop()

wxPython - Automatically closing nested modal dialogs

Python 2.7, WxPython 3.0.2
We are trying to automatically close an entire program under certain conditions. For various reasons, we can't just kill the process. We've had some level of success with it. We can close it if there's no modal dialogs, or a single modal dialog. Once we introduce the second modal dialog (nested), it fails to stop properly.
The actual error received appears to be:
wx._core.PyAssertionError: C++ assertion "IsRunning()" failed at ..\..\src\common\evtloopcmn.cpp(83) in wxEventLoopBase::Exit(): Use ScheduleExit() on not running loop
Here's a working example of our issue. The frame will automatically close after 5 seconds. Clicking the button will load a dialog. Clicking the button on the dialog will open another dialog. It works fine until the last dialog is opened.
from threading import Thread
from time import sleep
import wx
class MainFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, title="TEST", size=(400, 400))
self.Show()
self.__someDialog = None
self.__myThread = None
self.__okButton = wx.Button(self, -1, "Press me")
self.Bind(wx.EVT_BUTTON, self.__onOK)
self.__myThread = Thread(target=self.__waitThenClose, name="Closer")
self.__myThread.setDaemon(True)
self.__myThread.start()
def __onOK(self, evt):
self.__someDialog = SomeDialog(self)
self.__someDialog.ShowModal()
def closeOpenDialogs(self):
lst = wx.GetTopLevelWindows()
for i in range(len(lst) - 1, 0, -1):
if isinstance(lst[i], wx.Dialog):
print "Closing " + str(lst[i])
lst[i].Close(True)
#lst[i].Destroy()
def __waitThenClose(self):
for x in range(0, 5):
print "Sleeping..."
sleep(1)
self.closeOpenDialogs()
wx.CallAfter(self.Close, True)
class SomeDialog(wx.Dialog):
def __init__(self, parent):
wx.Dialog.__init__(self, parent, id=-1, title='Some Dialog')
self.SetSize((300, 300))
self.__anotherDialog = None
self.__okButton = wx.Button(self, -1, "Press me")
self.Bind(wx.EVT_BUTTON, self.__onOK)
wx.EVT_CLOSE(self, self.__on_btn_cancel)
def __onOK(self, evt):
self.__anotherDialog = AnotherDialog(self)
self.__anotherDialog.ShowModal()
def __on_btn_cancel(self, event):
self.EndModal(wx.ID_CANCEL)
class AnotherDialog(wx.Dialog):
def __init__(self, parent):
wx.Dialog.__init__(self, None, id=-1, title='Another Dialog')
self.SetSize((200, 200))
wx.EVT_CLOSE(self, self.__on_btn_cancel)
def __on_btn_cancel(self, event):
self.EndModal(wx.ID_CANCEL)
if __name__ == "__main__":
app = wx.App()
mainFrame = MainFrame()
app.MainLoop()
I think what is happening here is that the first call to ShowModal() blocks the at the app level (not just the frame level) which is preventing the second dialog from becoming fully initialized. To work around this issue I would call Show() instead of ShowModal() and add wx.FRAME_FLOAT_ON_PARENT to the dialog style flags. You can also call Disable() on the parts of the program you don't want the user to interact with while the dialogs are open.
EDIT: Here is a working example:
from threading import Thread
from time import sleep
import wx
class MainFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, title="TEST", size=(400, 400))
self.Show()
self.__someDialog = None
self.__okButton = wx.Button(self, -1, "Press me")
self.Bind(wx.EVT_BUTTON, self.__onOK)
self.__myThread = Thread(target=self.__waitThenClose, name="Closer")
self.__myThread.setDaemon(True)
self.__myThread.start()
def __onOK(self, evt):
self.__someDialog = SomeDialog(self)
self.__someDialog.ShowModal()
def closeOpenDialogs(self, evt=None):
lst = wx.GetTopLevelWindows()
for i in range(len(lst) - 1, 0, -1):
dialog = lst[i]
if isinstance(dialog, wx.Dialog):
print "Closing " + str(dialog)
# dialog.Close(True)
wx.CallAfter(dialog.Close)
# sleep(1)
# dialog.Destroy()
def __waitThenClose(self):
for x in range(0, 10):
print "Sleeping..."
sleep(1)
wx.CallAfter(self.closeOpenDialogs)
wx.CallAfter(self.Close, True)
class SomeDialog(wx.Dialog):
def __init__(self, parent):
wx.Dialog.__init__(self, parent, id=-1, title='Some Dialog')
self.SetSize((300, 300))
self.__anotherDialog = None
self.__okButton = wx.Button(self, -1, "Press me")
self.Bind(wx.EVT_BUTTON, self.__onOK)
wx.EVT_CLOSE(self, self.__on_btn_cancel)
def __onOK(self, evt):
self.__anotherDialog = AnotherDialog(self)
self.__anotherDialog.SetWindowStyleFlag(
wx.FRAME_FLOAT_ON_PARENT|wx.DEFAULT_DIALOG_STYLE)
self.__anotherDialog.Show()
def __on_btn_cancel(self, event):
event.Skip()
self.EndModal(wx.ID_CANCEL)
class AnotherDialog(wx.Dialog):
def __init__(self, parent):
wx.Dialog.__init__(self, parent, id=-1, title='Another Dialog')
self.SetSize((200, 200))
wx.EVT_CLOSE(self, self.__on_btn_cancel)
parent.Disable()
def __on_btn_cancel(self, event):
event.Skip()
self.GetParent().Enable()
# self.EndModal(wx.ID_CANCEL)
if __name__ == "__main__":
app = wx.App()
mainFrame = MainFrame()
app.MainLoop()
The only way to reliably gracefully close all the modal dialogs, whether they were explicitly opened by your own code or not, is to use wxModalDialogHook to remember all the opened dialogs and then close them all, in the reverse (i.e. LIFO) order, before quitting the application.
Unfortunately I don't know if wxModalDialogHook is available in Python.

wxPython - checking for empty text dialogs

I have some python code, using wxpython, that will do the following:
ask the user for a number using a wxpython dialog box
check if that number is currently in use, if it is the box appears asking for a number again
Once an unused number has been entered, a new dialog will appear asking for a name. If in use, it will ask again
Both the new number and name are stored for later use
The code looks something like this:
while True:
codeNumberPrompt = wx.TextEntryDialog(self, "New code #: ", "Add New Code", str(len(self.codes)), style=wx.OK)
codeNumberPrompt.ShowModal()
self.codeNumber = codeNumberPrompt.GetValue()
#check if number is in use
if int(self.codeNumber) not in self.numbersInUse:
#new code name input
while True:
codeNamePrompt = wx.TextEntryDialog(self, "New code name: ", "Add New Code", style=wx.OK)
codeNamePrompt.ShowModal()
self.codeName = codeNamePrompt.GetValue()
#check if name is in use
if self.codeName.lower() not in self.namesInUse:
break
wx.MessageBox('Code name is currently in use', 'Warning', wx.OK | wx.ICON_INFORMATION)
break
else:
wx.MessageBox('Code number is currently in use', 'Warning', wx.OK | wx.ICON_INFORMATION)
My first question, is there a better/cleaner way to do this?
My second question (where I get stuck): I need to be able to handle some exception cases. For example:
if the user X's out of the first dialog, I dont want the second dialog box to show up and I want to proceed as if nothing happened (i.e. doesnt try to store the number or name values)
if the user leaves the number or name dialog entry blank, I want to ask them for that info again
I cant seem to find out how wxpython handles the X button in dialog boxes. Currently, if the user leaves a default value in the first (number) box, and then X's, the second box (name) will still show up
You should be able to catch the wx.CLOSE event and prevent a dialog from closing. However, I believe you would be better off using a wizard-type approach. In the first step, you would check the number and then hit Next. Then you would accept the name and close out of the dialog. I feel like that would be a more natural flow for the user.
I put together a fun little example, but you will note that I didn't save the data in any meaningful way. You'll want to add that yourself:
import wx
########################################################################
class MyDialog(wx.Dialog):
""""""
#----------------------------------------------------------------------
def __init__(self):
"""Constructor"""
wx.Dialog.__init__(self, None, title="Information")
self.numbers = [1, 2, 3]
self.names = ['mike', 'nick', 'george']
#--------------------------------------------------
# create the number panel
self.number_panel = wx.Panel(self)
self.number_text = wx.TextCtrl(self.number_panel)
self.number_text.SetFocus()
next_btn = wx.Button(self.number_panel, label='Next')
next_btn.Bind(wx.EVT_BUTTON, self.onNext)
panel_sizer = wx.BoxSizer(wx.VERTICAL)
panel_sizer.Add(self.number_text, 0, wx.ALL|wx.EXPAND, 5)
panel_sizer.Add(next_btn, 0, wx.ALL, 5)
self.number_panel.SetSizer(panel_sizer)
#--------------------------------------------------
# create the name panel
self.name_panel = wx.Panel(self)
self.name_panel.Hide()
self.name_text = wx.TextCtrl(self.name_panel)
ok_btn = wx.Button(self.name_panel, label='OK')
ok_btn.Bind(wx.EVT_BUTTON, self.onOK)
name_sizer = wx.BoxSizer(wx.VERTICAL)
name_sizer.Add(self.name_text, 0, wx.ALL, 5)
name_sizer.Add(ok_btn, 0, wx.ALL, 5)
self.name_panel.SetSizer(name_sizer)
#--------------------------------------------------
# layout panels
self.my_sizer = wx.BoxSizer(wx.VERTICAL)
self.my_sizer.Add(self.number_panel, 1, wx.EXPAND)
self.my_sizer.Add(self.name_panel, 1, wx.EXPAND)
self.SetSizer(self.my_sizer)
#--------------------------------------------------
self.ShowModal()
wx.CallAfter(self.my_sizer.Layout)
#----------------------------------------------------------------------
def onNext(self, event):
""""""
number = int(self.number_text.GetValue())
if number in self.numbers:
wx.MessageBox('Code number is currently in use',
'Warning', wx.OK | wx.ICON_INFORMATION)
self.number_text.SetFocus()
return
else:
self.my_sizer.Detach(self.number_panel)
self.name_panel.Show()
self.Layout()
self.numbers.append(number)
#----------------------------------------------------------------------
def onOK(self, event):
""""""
name = self.name_text.GetValue()
if name.lower() in self.names:
wx.MessageBox('Code name is currently in use',
'Warning', wx.OK | wx.ICON_INFORMATION)
return
else:
self.names.append(name)
self.Close()
########################################################################
class MyPanel(wx.Panel):
""""""
#----------------------------------------------------------------------
def __init__(self, parent):
"""Constructor"""
wx.Panel.__init__(self, parent)
info_button = wx.Button(self, label="Get Info")
info_button.Bind(wx.EVT_BUTTON, self.onGetInfo)
#----------------------------------------------------------------------
def onGetInfo(self, event):
""""""
dlg = MyDialog()
dlg.Destroy()
########################################################################
class MyFrame(wx.Frame):
""""""
#----------------------------------------------------------------------
def __init__(self):
"""Constructor"""
wx.Frame.__init__(self, None, title='Demo')
panel = MyPanel(self)
self.Show()
if __name__ == '__main__':
app = wx.App(False)
frame = MyFrame()
app.MainLoop()

Escape key to Close WxPython GUI

I am working on a rather simple wxpython GUI, and would like to be able to have the escape key close the window. Right now I just have a close button that executes sys.exit(0), but I'd like the escape key to do this to.
Does anyone know a way to do this?
import win32clipboard
import wx
from time import sleep
import sys
class MainFrame(wx.Frame):
def __init__(self,title):
wx.Frame.__init__(self, None, title="-RRESI Rounder-", pos=(0,0), size=(210,160))
panel=Panel(self)
icon = wx.Icon('ruler_ico.ico', wx.BITMAP_TYPE_ICO)
self.SetIcon(icon)
class Panel(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
x1=10; x2=110
y1=40; dy=25; ddy=-3
boxlength=80
self.button =wx.Button(self, label="GO", pos=(100,y1+dy*3))
self.Bind(wx.EVT_BUTTON, self.OnClick,self.button)
self.button.SetDefault()
self.button2 =wx.Button(self, label="Close", pos=(100,y1+dy*4))
self.Bind(wx.EVT_BUTTON, self.OnClose, self.button2)
self.button.SetDefault()
self.Bind(wx.EVT_KEY_UP, self.OnKeyUP)
self.label1 = wx.StaticText(self, label="Input Number:", pos=(x1,y1+dy*1))
self.Input = wx.TextCtrl(self, value="1.001", pos=(x2,ddy+y1+dy*1), size=(boxlength,-1))
self.label0 = wx.StaticText(self, label="Round to closest: 1/", pos=(x1,y1+dy*0))
self.Denominator = wx.TextCtrl(self, value="64", pos=(x2,ddy+y1+dy*0), size=(boxlength,-1))
self.label2 = wx.StaticText(self, label="Output Number:", pos=(x1,y1+dy*2))
self.display = wx.TextCtrl(self, value="1.0", pos=(x2,ddy+y1+dy*2), size=(boxlength,-1))
self.display.SetBackgroundColour(wx.Colour(232, 232, 232))
self.label3 = wx.StaticText(self, label=" ", pos=(x2+7,y1+dy*2+20)) #Copied
self.label4 = wx.StaticText(self, label="Type value and hit Enter", pos=(x1-5,y1-dy*1.5))
self.label5 = wx.StaticText(self, label="Output is copied", pos=(x1-5,y1-dy*1))
font = wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.NORMAL)
self.label4.SetFont(font)
self.label5.SetFont(font)
def OnKeyUP(self, event):
keyCode = event.GetKeyCode()
if keyCode == wx.WXK_ESCAPE:
sys.exit(0)
def OnClose(self, event):
print "Closed"
sys.exit(0)
def OnClick(self,event):
print "You clicked the button!"
def openClipboard():
try:
win32clipboard.OpenClipboard()
except Exception, e:
print e
pass
def closeClipboard():
try:
win32clipboard.CloseClipboard()
except Exception, e:
print e
pass
def clearClipboard():
try:
openClipboard()
win32clipboard.EmptyClipboard()
closeClipboard()
except TypeError:
pass
def setText(txt):
openClipboard()
win32clipboard.EmptyClipboard()
win32clipboard.SetClipboardText(txt)
closeClipboard()
Denominator = float(self.Denominator.GetValue())
Input=float(self.Input.GetValue())
Output=round(Input*Denominator,0)/Denominator
self.display.SetValue(str(Output))
setText(str(Output))
self.label3.SetLabel("Copied")
self.Update()#force redraw
sleep(.5)
wx.Timer
self.label3.SetLabel(" ")
if __name__=="__main__":
app = wx.App(redirect=False) # Error messages don't go to popup window
frame = MainFrame("RRESI Rounder")
frame.Show()
app.MainLoop()
This sorta works ... albiet with some issues
[edit]ok EVT_CHAR_HOOK works much better than EVT_KEY_UP
import wx
class Test(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, -1, title='Event Test',
size=(200, 200))
panel = wx.Panel(self)
panel.SetFocus()
self.Bind(wx.EVT_CHAR_HOOK, self.OnKeyUP)
def OnKeyUP(self, event):
print "KEY UP!"
keyCode = event.GetKeyCode()
if keyCode == wx.WXK_ESCAPE:
self.Close()
event.Skip()
class App(wx.App):
"""Application class."""
def OnInit(self):
self.frame = Test()
self.frame.Show()
self.SetTopWindow(self.frame)
self.frame.SetFocus()
return True
if __name__ == '__main__':
app = App()
app.MainLoop()
Probably an easier way is to set the frame up as a dialogue with a cancel button (which you can hide):
class MainFrame(wx.Dialog):
...
def __init__(self, ...):
...
# the frame must have a cancel button
cancel_button = wx.Button(..., id=wx.ID_CANCEL)
# it still works if you hide it
cancel_button.Hide()
This seems to provide the default handling for the escape key. You could even bind it to an event handler to perform some actions before closing - if you do the handler must use event.Skip(True) to propagate the event or event.Skip(False) to stop the cancel operation.

How to link multiple wx.Dialogs in wxPython

I want to make a game in wxPython (no other modules) and I want to make it so that you can enter some values in popup screens before the game starts, and then the game will be drawn on a canvas which in turn is drawn on a panel, which is bound to the main game.
I made the gamescreen with all fancy stuff (works solo)
I made the input screens
But I cannot link them.
How do I start the game so it will open a dialog box, then on the closure of it open another one, and then open the game ?
I tried the following, but it will not open my canvas:
# makes a game by showing 2 dialogs
# after dialogs have been answered, starts the game by drawing the canvas.
# imports
import wx
import Speelveld3
# globals
SCRWIDTH = 950
SCRHEIGHT = 700
# dialogbox class
class MyDialog1(wx.Dialog):
def __init__(self, parent):
wx.Dialog.__init__(self, parent)
self.username = wx.TextCtrl(self)
self.okButton = wx.Button(self, wx.ID_OK, "OK")
class MyDialog2(wx.Dialog):
def __init__(self, parent):
wx.Dialog.__init__(self, parent)
self.canvasWidth = wx.TextCtrl(self)
self.okButton = wx.Button(self, wx.ID_OK, "OK")
# main class
class Game(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, -1, title='My game', size=(SCRWIDTH, SCRHEIGHT))
self.username = ""
self.canvasWidth = 10
# hide the frame for now
self.Hide()
def OnInit(self):
#Make your dialogs
dlg1 = MyDialog1(self)
#if the user pressed "OK" (i.e. NOT "Cancel" or any other button you might add)
if dlg1.ShowModal() == wx.ID_OK:
#get the username from the dialog
self.username = dlg1.username.GetValue()
#clean up the dialog (AFTER you get the username)
dlg1.Destroy()
dlg2 = MyDialog2(self)
#if the user pressed "OK" (i.e. NOT "Cancel" or any other button you might add)
if dlg2.ShowModal() == wx.ID_OK:
#get the username from the dialog
self.canvasWidth = dlg2.canvasWidth.GetValue()
#clean up the dialog (AFTER you get the username)
dlg2.Destroy()
# Now that you have your settings, Make the gameboard
# THIS PART IS STILL BROKEN!
# I can paste the whole board class (structure of it is taken from the tetris tutorial)
# but that seems a bit much tbh...
self.gameBoard = Board.Board(self)
self.gameBoard = SetFocus()
self.gameBoard.start()
self.Centre()
self.Show(True) #show the frame
if __name__ == '__main__':
# how can I start the game here?
app = wx.App()
frame = Game()
board = Speelveld3.Speelveld(frame)
board.start()
frame.Show()
app.MainLoop()
You've double posted, and the lack of any wx.Dialog in your sample code suggests to me that you haven't even looked at a tutorial yet, but I will give you the benefit of the doubt.
First, if you want to return information from a dialog, the easiest way is to define a custom dialog. Define a new class that inherits from wx.Dialog and then set it up just like you would a normal panel or a frame. It seems to me that you will need two of these. They'll look something like this:
class MyDialog1(wx.Dialog):
def __init__(self, parent):
wx.Dialog.__init__(self, parent)
self.username = wx.TextCtrl(self) #this is where users will enter their username
self.okButton = wx.Button(self, wx.ID_OK, "OK") #Note that I'm using wx.ID_OK. This is important
Now, for the logic you want. Pretty much every object in wxPython that you actually see has the functions Show() and Hide() (API here). You don't want to show your frame until AFTER the dialogs are finished, so in your __init__(), call Hide(). I'm also initializing a variable, username, which is where I will store the data from my dialog.
class Game(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, id, title, size=(SCRWIDTH, SCRHEIGHT))
self.username = ""
self.Hide() #don't show the frame just yet
#self.Hide() is the exact same as self.Show(False)
Now, for your dialogs. Like Mike Driscoll suggested, you call your dialogs BEFORE making your canvas. wx.Dialogs are launched using ShowModal(). By setting the ID of self.okButton to the constant wx.ID_OK, wxPython recognizes that the dialog should be closed after the button in clicked. You should also be aware of wx.ID_CANCEL.
def OnInit(self):
#Make your dialogs
dlg1 = MyDialog1(self)
if dlg1.ShowModal() == wx.ID_OK:
#if the user pressed "OK" (i.e. NOT "Cancel" or any other button you might add)
self.username = dlg1.username.GetValue() #get the username from the dialog
dlg1.Destroy() #clean up the dialog (AFTER you get the username)
#do this again for your second dialog
#Now that you have your settings, Make the gameboard
self.gameBoard = Board.Board(self)
self.gameBoard = SetFocus()
self.gameBoard.start()
self.Centre()
self.Show(True) #show the frame
In your OnInit you just need to call your dialogs and show them modally BEFORE you create your Board instance. Then it should work correctly.
EDIT (6-28-12): Here's some code:
import wx
########################################################################
class MyDlg(wx.Dialog):
""""""
#----------------------------------------------------------------------
def __init__(self):
"""Constructor"""
wx.Dialog.__init__(self, None, title="I'm a dialog!")
lbl = wx.StaticText(self, label="Hi from the panel's init!")
btn = wx.Button(self, id=wx.ID_OK, label="Close me")
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(lbl, 0, wx.ALL, 5)
sizer.Add(btn, 0, wx.ALL, 5)
self.SetSizer(sizer)
########################################################################
class MyPanel(wx.Panel):
""""""
#----------------------------------------------------------------------
def __init__(self, parent):
"""Constructor"""
wx.Panel.__init__(self, parent)
# show a custom dialog
dlg = MyDlg()
dlg.ShowModal()
dlg.Destroy()
self.Bind(wx.EVT_PAINT, self.OnPaint)
def OnPaint(self, evt):
pdc = wx.PaintDC(self)
try:
dc = wx.GCDC(pdc)
except:
dc = pdc
rect = wx.Rect(0,0, 100, 100)
for RGB, pos in [((178, 34, 34), ( 50, 90)),
(( 35, 142, 35), (110, 150)),
(( 0, 0, 139), (170, 90))
]:
r, g, b = RGB
penclr = wx.Colour(r, g, b, wx.ALPHA_OPAQUE)
brushclr = wx.Colour(r, g, b, 128) # half transparent
dc.SetPen(wx.Pen(penclr))
dc.SetBrush(wx.Brush(brushclr))
rect.SetPosition(pos)
dc.DrawRoundedRectangleRect(rect, 8)
########################################################################
class MyFrame(wx.Frame):
""""""
#----------------------------------------------------------------------
def __init__(self):
"""Constructor"""
wx.Frame.__init__(self, None, title="Example frame")
# show a MessageDialog
style = wx.OK|wx.ICON_INFORMATION
dlg = wx.MessageDialog(parent=None,
message="Hello from the frame's init",
caption="Information", style=style)
dlg.ShowModal()
dlg.Destroy()
# create panel
panel = MyPanel(self)
if __name__ == "__main__":
app = wx.App(False)
frame = MyFrame()
frame.Show()
app.MainLoop()

Categories