Hello, here I will teach you how to make your first GUI (Graphical User Interface) in python
This tutorial requires basic python knowledge (classes, functions, calls).
We will use:
-The module [url=http://wxpython.org/]wxPython[/url]
Also, please be sure to have installed python version 2.5.x as this will be the version used in this tutorial.
My favourite editor, and the one i always use is [url=http://www.easyeclipse.org/site/distributions/python.html]EasyEclipse for Python[/url], I really suggest it but you can use any editor you want.
The final result of today's tutorial will look like this.
[img]http://img151.imageshack.us/img151/8291/editor1.jpg[/img]
As you can see, it's a basic frame, with a text board inside. Looks kinda like notepad.
[code]import wx
class Frame(wx.Frame):
def __init__(self, name):
wx.Frame.__init__(self, None, -1, name)
edit = wx.TextCtrl(self, -1, "", style=wx.TE_MULTILINE)
app = wx.PySimpleApp()
frame = Frame("My first text editor")
frame.Show()
app.MainLoop()[/code]
The code behind this is very short. I will now proceed to explain it line by line.
[code]import wx[/code]
This is used to import the wx module (wxPython) which is used to create the GUI. You can consider it like cpp's #include <library>, except in python we are talking about libraries.
wx is a python library placed in the folder where you installed python.
The import command imports python files' functions, classes and data in the current workspace (the python file you write the import in) for use. You can import python files from anywhere, starting from the folder of your program to any other existing folder.
[code]class Frame(wx.Frame)[/code]
With this line we tell python to create a new class, derived from the class wx.Frame. A derived class takes all the functions and data of the parent, and those can be accessed from this class as if it was its parent, unless they haven't been overwritten. Also, children class can define their own methods and data to help do their job.
[code]def __init__(self, name):[/code]
This is the init function, the function that is executed when you instance your class. You have to specify the name whenever you instance the class Frame or it wont work. self is not counted as a parameter, so when we call Frame we write the name only. So the class is instanced like this: Frame("Frame name"). "Frame name" is a string. Naturally, if I wouldn't write the name parameter in the init function I could just write Frame() to create an instance of this class (notice the self is ALWAYS necessary, no matter what. Classes won't work without the self. Any function of any class MUST have self as first argument, even if it will be invisible).
[code]wx.Frame.__init__(self, None, -1, name)[/code]
With this line we call the parent class (wx.Frame)'s init function. The first parameter, self, tells the function to trasform our class in a wxWindow class, and allow us to add widgets (like buttons, or text) to the window. The second argument, None, is a Python boolean value, like cpp's NULL, and it tells the function what will be the parent of the frame. The parent of a frame is another window. When the parent is closed, all the children are closed too.
-1 is the id. It can be any number. We specify -1 for wx to create a random ID. name is the title of the window.
[code]edit = wx.TextCtrl(self, -1, "", style=wx.TE_MULTILINE)[/code]
This creates the text box. We create an instance of the class wx.TextCtrl. self is the parent, and refers to the class we are in. It means the textbox is parented to the window and will follow it around. -1 is the id, like I explained before. "" is the default text, or the text that will be written in the textbox when the program start. "" is an empty string so there will be no text. Then we specify the style. I wrote style= ... because there are other arguments between default text and style, like position and size, and since I want to skip them I tell Python to assign what I am writing to style instead of the next argument. wx.TE_MULTILINE is one of the many styles for the textbox. Every style for every widget (that's how buttons, frames, text boxes are commonly called) has a prefix at start that specifies what widget it applies on. Button styles start with BU_, list styles start with LI_ and so on.
[code]app = wx.PySimpleApp()[/code]
Here we create an instance of wx.PySimpleApp(). wx Apps are used to make wx take the control of the mython program and keep it open till all the windows are closed. When all the windows are gone, the App will lose control of the python program, and give it back to python, which will execute the last instructions after the line where the App took control and close.
Also, a wx window can't exist without an App instance, because the App keeps trace of all the events happening and administrates them. A wx window without an app behind is like a person without a heart.
[code]frame = Frame()
frame.Show()
[/code]
After the app is created, we can instance the Frame class so that it will start working.
The Show function will make the frame pop up on screen. If left, you won't be able to see it.
The Show function can be called inside the __init__ too, but keeping it out will give the code more tidyness.
[code]app.MainLoop()[/code]
This is the command that gives the control of the python program to wx, as we discussed above. No instruction below this will be executed untill all the windows are closed or the App is stopped.
So there you have it, enjoy your new window and take care of it :P
[U][I]
[B]Bonus tut before part 2[/B][/I][/U]
[U][I][B]Cookies inside[/B][/I][/U]
So in this tut I'm gonna explain how buttons basically work and how to make a button execute some code.
This tutorial involves the creation of gentleman windows from a window who eats sanvich.
And from now on, we will call windows frames, and the general name for their content (buttons, texts..) will be widget.
The final product will look like this
[img]http://img170.imageshack.us/img170/1143/gentlemenwindow.jpg[/img]
Sorry for the crap image quality, my stamp key broke somehow..
First of, download these 2 images, and put them in the folder where you will make the .py file
[img]http://img245.imageshack.us/img245/1650/gentlemen.jpg[/img]
[img]http://img13.imageshack.us/img13/5329/sandvich.jpg[/img]
This tutorial's code is (for those who want to try)
[code]
import wx
#This is a comment
#Comments in this code are made by the heavy
class Frame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, -1, "Frame who eats sandvich")
panel = wx.Panel(self) #Creating the panel, parented to the frame
panel.SetBackgroundColour((255, 255, 255)) #Making the background white
button = wx.Button(panel, -1, "Click me!", (50, 50)) #Creating a button, with the position X: 50, Y: 50
button.Bind(wx.EVT_BUTTON, self.OnButtonClicked) #Linking the button to a function which is executed on press
self.framecount = 0 #How many tiny coward frames are there? I see here
self.CreateCowardFrame() #I see spy!
self.howmanyframes = wx.StaticText(panel, -1, #Splitting
"There is 1 tiny coward frame", #a function call
(50, 80) #on more lines
)
sandvich = wx.StaticBitmap(panel, -1, wx.Bitmap("sandvich.jpg"), (180,100)) #Creating a sanvich to eat
self.CenterOnScreen() #I see frame is centered on screen!
def CreateCowardFrame(self): #Function to create itty bitty tiny cowards
self.framecount = self.framecount + 1 #I see new coward!
frame = MiniFrame(self, self.framecount) #Instancing the coward
frame.Show() #And showing him
def OnButtonClicked(self, event): #The function executed when heavies press the button
self.CreateCowardFrame() #I make coward frame feel alive
self.howmanyframes.SetLabel("There are %d tiny coward frames"%self.framecount) #And change the text
class MiniFrame(wx.Frame): #Mini coward frame's class!
def __init__(self, parent, num):
wx.Frame.__init__(self, parent, -1, size=(150, 186), style=wx.CAPTION)
self.SetTitle("Gentleman %d"%num) #That spy is not one of us!
panel = wx.Panel(self) #Little panel for tiny cowards
spy = wx.StaticBitmap(panel, -1, wx.Bitmap("gentlemen.jpg")) #I see spy!
app = wx.PySimpleApp() #It is sad day!
frame = Frame() #How could this happen!
frame.Show() #Oh noooo
app.MainLoop() #HELP![/code]
So here's the explanation.
First, as we need it, we import wx.
Then, we make the class for the first frame.
[code]class Frame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, -1, "Frame who eats sandvich")[/code]
These are the first 3 lines in the class. They define the class, its init function and inside it wx.Frame is initialized. First argument is None, as we don't want this frame to be parented to any window. Second is the ID, -1, means generate automatically. Id is an unique integer to identificate a widget, like a button, a text box and so on. Every widget has one. We usually assign them automatically unless we want them to be findable, and we need a fixed ID. Third parameter is the title of the window.
[code] panel = wx.Panel(self) #Creating the panel, parented to the frame
panel.SetBackgroundColour((255, 255, 255)) #Making the background white[/code]
Panels are like covers between the frame and what is inside. They are very useful because they provide TAB navigation and they let you place the items where you want them to be. It's a good idea to use a panel everywhere unless you only have one widget that will fill the entire frame.
In the second line we call the method SetBackgroundColour, with the rgb for white. Notice that I put two pairs of parenthesis. That's because the SetBackgroundColour function takes only a parameter, which is a 3 items tuple (a vector, but python doesn't consider it like that).
To specify transparence, if you are on a system which is capable of it, you can try self.SetTransparent( alpha ). This works on vista but not on XP, so you shouldn't abuse this effect on programs that can be run on old windows versions too.
[code] button = wx.Button(panel, -1, "Click me!", (50, 50))
button.Bind(wx.EVT_BUTTON, self.OnButtonClicked)
[/code]
Here we create a button. As for every widget, first and second parameters are parent and ID, and they are explained above. The third parameter is the label (or text) of the button. It can also be an empty string, but your button will be blank and useless. The last parameter is the position of the button. We give it 50 pixels on X and Y from the upper left corner of the frame.
button.Bind will link the button to a function, and the function will be executed when the button will emit a wx.EVT_BUTTON event. It usually emits it when pressed, but by creating a children class of a button, and editing it, you can make it behave however you want, and even make it emit a wx.EVT_BUTTON event on an interveal of time.
[code] self.framecount = 0[/code]
We initialize the local variable framecount. Notice that this variable has self. before the actual name. This makes it local to the class. If self was not specified, the variable would be local to the function and wouldn't be accessible from other function of the class, which in this case we need to.
Now, let's create a new frame class, that will be the frame created when we press the button.
[code]class MiniFrame(wx.Frame): #Mini coward frame's class!
def __init__(self, parent, num):
wx.Frame.__init__(self, parent, -1, size=(150, 186), style=wx.CAPTION)
[/code]
You should already know about the first line. In the second line we are, instead of only putting self as a parameter of the function call, adding parent and num. These will be specified when we create an instance of the miniframe, like this: MiniFrame(parent, num).
In the third line, as second parameter we wrote parent, as it is an argument to the init function and it will be taken from there. -1 is the id. Then we skip the title and we go for the size. We assign it using equal because we want python to know we skipped some of the arguments that were between. The size is a tuple, like (25, 665), and refers to X and Y. Then, again, we skip some arguments and set the style. We want this frame to have no close button, so we use wx.CAPTION which will only display the caption bar.
[code] self.SetTitle("Gentleman %d"%num) [/code]
Here we set the title. calling it on self is like writing wx.Frame.SetTitle as we are in its child class, but that wouldn't have any effect on the current frame.
[code]panel = wx.Panel(self)
spy = wx.StaticBitmap(panel, -1, wx.Bitmap("gentlemen.jpg"))
[/code]
Here we create a panel and put a bitmap on it.
Now let's go back to the first class.
Under the main indentation, at the same level of __init__ let's write
[code]def CreateCowardFrame(self):
self.framecount = self.framecount + 1
frame = MiniFrame(self, self.framecount)
frame.Show()
def OnButtonClicked(self, event): #The function executed when heavies press the button
self.CreateCowardFrame() #I make coward frame feel alive
self.howmanyframes.SetLabel("There are %d tiny coward frames"%self.framecount) #And change the text
[/code]
These are two new functions added to our class. The first one increments the count of mini frames created, then creates one, and passes two arguments: self, which is the parent, and self.framecount, for the miniframe to show his number on his title. There are more ways of accessing this value inside the miniframe, but I find it simpler to pass it as an argument.
Lastly, we show the new frame created.
In the OnButtonClicked function we call CreateCowardFrame and update the label of the static text widget we are going to write now.
Now let's go back to the __init__ function and let's add
[code]self.CreateCowardFrame()
self.howmanyframes = wx.StaticText(panel, -1,
"There is 1 tiny coward frame",
(50, 80)
)
[/code]
Here we call self.CreateCowardFrame to make a new miniframe appear near the main frame.
Then we create a static text widget, which will show how many miniframes are there. Here we write 1 manually because we know how many they are. But next time we will update it we will use formatting (%d) to make it show the exact value.
Notice the function call is split in 4 lines. This can help keep the code tidy. The 4th argument is the position. We put it right under the button.
Lastly, let's add
[code]sandvich = wx.StaticBitmap(panel, -1, wx.Bitmap("sandvich.jpg"), (180,100))
self.CenterOnScreen()
[/code]
To give our window a bit of beauty and taste, and let's center it on screen.
Now write these lines
[code]app = wx.PySimpleApp()
frame = Frame()
frame.Show()
app.MainLoop()[/code]
To make your GUI run and your done!
Hope this was clear. Please write on the thread or send me an MP if something isn't clear.
thanks
Good on you for making a tutorial
I'm not installing pyton for a window.
[QUOTE=Eleventeen;16736479]I'm not installing pyton for a window.[/QUOTE]
No one is asking you to. Do this if you intend to start learning wx.
And don't act butthurt just to increment your post count.
Great tutorial, I hope you do more of these in the future
[QUOTE=Reg;16736994]No one is asking you to. Do this if you intend to start learning wx.
And don't act butthurt just to increment your post count.[/QUOTE]
I could care less about my post count.
[QUOTE=Eleventeen;16737554]I could care less about my post count.[/QUOTE]
fyi it's "couldn't care less"
"could care less" implies you DO care.
If you're going to use cliches at least KNOW the cliche first.
[QUOTE=RubberDuckeh;16737701]fyi it's "couldn't care less"
"could care less" implies you DO care.
If you're going to use cliches at least KNOW the cliche first.[/QUOTE]
Wow you couldn't be more wrong.
could care less is commonly used in the same sense...
[QUOTE=r4nk_;16737740]Wow you couldn't be more wrong.
could care less is commonly used in the same sense...[/QUOTE]
Uhh.. It's still wrong. To say "could care less" means you care to begin with going against the entire idea of the cliche that you don't care.
[QUOTE=RubberDuckeh;16737762]Uhh.. It's still wrong. To say "could care less" means you care to begin with going against the entire idea of the cliche that you don't care.[/QUOTE]
No shit there are plenty of sayings in the english language that don't make sense. Write a novel about it.
What would I add to make it so the text was savable?
[QUOTE=stone555;16738353]What would I add to make it so the text was savable?[/QUOTE]
Maybe I will write in the next tutorial about making it saveable/openable.
It's simple.
Just tell me if you understood this, because I think it was a bit hard to understand how I've written it.
[editline]06:01PM[/editline]
Oh and tell me if really you want me to make a new tutorial :)
[editline]06:02PM[/editline]
[QUOTE=Eleventeen;16737554]I could care less about my post count.[/QUOTE]
Then don't post at all. Butthurt comments on things that other people could find useful are useless.
[QUOTE=Eleventeen;16736479]I'm not installing pyton for a window.[/QUOTE]
Hurr Durrrr. Python developers don't care about you.
All Linux distros have Python preinstalled, they don't give a shit about Windows honestly.
Even Macs have Python 2.5 out of the box; Windows should get with the times.
Great tutorial, ignore the butthurt faggots.
Thank you for the good comments. I'm using Windows Vista, and it's weird that Microsoft didn't include python as default...
Looks like the words Microsoft and Open source don't go well together. Microsoft and Free in general.
[QUOTE=Reg;16738767]Microsoft and Free in general.[/QUOTE]
Yeah they don't give anything for free, those fuckers.
[url]http://www.microsoft.com/express/[/url]
[url]http://download.live.com/[/url]
[url]http://www.microsoft.com/windows/virtual-pc/[/url]
And they especially hate students, they charge them extra for their shit.
[url]https://www.dreamspark.com/[/url]
That's the bright side.. but for example they sell valve's free dlcs on xbox just to get some little money more.. I find that awful
perl supremacy
Perl is no better and no worse than python
[QUOTE=Reg;16739292]That's the bright side.. but for example they sell valve's free dlcs on xbox just to get some little money more.. I find that awful[/QUOTE]
They do it because the Xbox users are stupid enough to put up with that shit.
Same thing apple does with every single one of their products.
Yes! It worked! Thanks, you should keep making tutorials. They're really helpful.
I will make the next tutorial tomorrow, stay tuned
[editline]07:15PM[/editline]
Also, I think I'll maybe expand the OP instead of making a new thread..
I'm up for suggestions
[QUOTE=Reg;16739611]I will make the next tutorial tomorrow, stay tuned
[editline]07:15PM[/editline]
Also, I think I'll maybe expand the OP instead of making a new thread..
I'm up for suggestions[/QUOTE]
Do something more complex, like a simple calculator, to show how buttons and stuff works.
[url]http://wxlua.sourceforge.net/[/url]
Bindings for wx are present for almost any language
I've come to the conclusion that the people that come to this forum hate it when people try teaching or sharing with everyone. This thread is a good example, the F# thread, the prime finder thread, pretty much any thread where someone does anything sort of cool.
The only thread that has remained pretty civil is the thread where everyone circle jerks at what they are doing and COULDN'T care less about what anyone else does.
So don't feel bad that this thread has turned out the way it has, keep posting stuff, a couple people like it. And try to ignore the "X is a better way than Y" people, you can never please them.
I will, I know about jealous people and to just ignore them..
[QUOTE=Reg;16741149]I will, I know about jealous people and to just ignore them..[/QUOTE]
I wouldn't flatter yourself much. They aren't jealous, they are just twats, they do this to everyone.
The code of the bonus tutorial is there, the explanation is coming tomorrow
Enjoy
Sorry, you need to Log In to post a reply to this thread.