Python: What is the difference between calling a method with () and without? - parentheses

It must be something very basic and obvious, because I just can't find the answer through google or on here...
What difference do the parentheses make in Python when I call methods?
Example code with pygame and parentheses:
import pygame
import sys
pygame.init()
screen = pygame.display.set_mode((640, 480))
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
pygame.display.update()
When I click the cross of the window, it closes with sys.exit() being the last thing called in the Traceback.
When I change it to this:
import pygame
import sys
pygame.init()
screen = pygame.display.set_mode((640, 480))
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit
pygame.display.update()
It still quits but with a display error as last item in the Traceback.
I came across this when I followed this tutorial for Panda3D here:
http://www.mygamefast.com/volume1/
In several of the issues (e.g. here in the "keyboardSetup" method of the "ArcadeFlightGame" class: http://www.mygamefast.com/volume1/issue5/4/) he calls "sys.exit" instead of "sys.exit()" and the game terminates correctly. If I change it to "sys.exit()" it causes some error when starting.
This seems to be so very basic that nobody really explained it anywhere... I would really appreciate it if somebody could enlighten me a little on this :/

If you don't use parenthesis, you aren't calling the function. It's just that simple. sys.exit does absolutely nothing, sys.exit() calls the function.
That being said, sometimes the name of a function without parenthesis will be passed to some other function, or bound to an event. In such a case, parenthesis aren't used because you are telling this other function or event "call this at the appropriate time".
For example, in the tutorial you linked to is this line of code:
self.accept("escape", sys.exit)
This is not calling sys.exit. Instead, it is telling the event system "when you detect the escape key, call this function". At the time this code is called, sys.exit is not called, but rather registered to be called later. When the escape key is pressed, the underlying framework will actually call the function using parenthesis.
So, there is a difference between immediately calling a function (using ()) and registering a function (using the name only, no ()).

Related

Continuous calls of the <Configure> event in tkinter

I am trying to write a function to dynamically resize an image displayed in a tkinter window.
Therefore I bound this function to the Configure event:
connroot.bind( "<Configure>", connresiz)
My problems are:
That the connresiz() function gets called 3 times (why 3?) at program start, and
More troublesome, that dynamically resizing the window calls the function continuously as I drag the mouse! How can avoid this?
I thought about checking at the simultaneous presence of a <Configure> and <ButtonRelease-1> events, but I don't know how to code it.
1) We don't know that, since we can't see your code...
2) Short answer is: you can't, because that's exactly what <Configure> event does! Long answer, you can, with a little trick/hack. Since anytime the window is changing, it will call all the binded functions to <Configure>, and the same happens anytime as the mouse button released (right after the last <Configure> call) we can create a flag/switch which will tell us, if the window was "configured" then we can check that switch anytime the mouse button is released, and switch it back to the default value after we ran some actions.
So if you want the image to resized only, when the mouse was released and the window was changed this is the code you need:
from tkinter import *
class Run:
def __init__(self):
self.root = Tk()
self.clicked = False
self.root.bind('<ButtonRelease-1>', self.image_resize)
self.root.bind('<Configure>', lambda e: self.click(True))
def image_resize(self, event):
if self.clicked:
print("I'm printed after <Configure>.") # the action goes here!
self.click(False)
def click(self, value):
self.clicked = value
app = Run()
app.root.mainloop()
According to the official tk documentation, <Configure> events fire "whenever its size, position, or border width changes, and sometimes when it has changed position in the stacking order." This can happen several times during startup.
It is called continuously while you resize the window because the size of the widget is changing. That's what it's defined to do. You can't prevent it from being called, though you can certainly modify what you do in the callback. For example, you could delay resizing the image until you've not received another <Configure> event for a second or two -- which likely means the user has stopped interactive resizing.

PyQt4: Using a QPushButton widget to delete an item from QList widget

I am learning PyQt4 (I am using version 4.4.4) and I'm pretty new to Python (Python 2.5). I have a GUI with a QListWidget and a QPushButton. I want a user to be able to click to select an entry in the list and then click the QPushButton and have the selected entry go away (be deleted from the QList). I've been banging my head against this problem for over a week and I would deeply appreciate some help.
Currently, my GUI comes up and I can select different list items (only one at a time right now), but when I click the QPushButton, nothing happens. The selection color goes from blue to grey, but the entry is not removed. No error is shown in Command Prompt (Windows 7).
I have defined a function, remove(),which I am using as the slot for the QPushButton. I believe the QPushButton.connect is defined correctly for a Qt Signal to Python Slot, based on what I've seen of answers to similar problems, but the items are not being deleted. However, the remove function is not even being triggered. I have a print statement within the function, but it is not being called when I click the QPushButton, which is how I know that the function is not being called.
Here is my most recent code: (I read a very rant-y post on meta-SO about big blocks of code, so I've cut this down to the bits I think are relevant: the list creation, the button creation and the remove function, which I'm trying to use as a slot. I've left in comments that indicate what the other sections are, so if you think I've left out something that could help, let me know and I'll add it back in)
class questionGUI(QtGui.QWidget):
#This class is the window of the gui.
def __init__(self):
super(questionGUI,self).__init__()
#Layout
grid = QtGui.QGridLayout()
grid.setSpacing(10)
#Labels Needed
...
#Question List
self.qList = QtGui.QListWidget()
#print self.qList
self.qList.setSelectionMode(QtGui.QAbstractItemView.SingleSelection)
entries = ['[Pick Image] <Default>','[Slider Question] <Default>', '[Comment Box] <Default>']
for i in entries:
item = QtGui.QListWidgetItem(i)
self.qList.addItem(item)
#Type select
...
#Text insert Needed
...
#Buttons Needed
deleteButton = QtGui.QPushButton('Delete Question')
deleteButton.connect(deleteButton,QtCore.SIGNAL('itemClicked(clicked)'),lambda: self.remove)
addQuestionButton = QtGui.QPushButton('Add Question')
...
doneButton = QtGui.QPushButton('Done')
...
#Parameters Needed
...
#Layout Placement and Window dimensions
...
def addQuestion(self):
...
def remove(self):
print 'remove triggered'
print self.qList.currentItem()
self.qList.removeItemWidget(self.qList.currentItem())
...
I tried to post an image, but I don't have enough reputation. If you think an image would be useful, let me know and I can send it to you.
You mixed the signals:
deleteButton.connect(deleteButton,QtCore.SIGNAL('itemClicked(clicked)'),lambda: self.remove)
deleteButton is a QPushButton, but itemClicked(clicked) looks like the signal from QListWidget with wrong signature. Since, QPushButton doesn't have this signal, no connection is made. Qt doesn't raise errors for failed connections, but .connect method has a bool return value indicating success/failure of the attempted connection.
Also, lambda: self.remove as a slot doesn't make sense. Slot should be a callable that is called upon signal emit. Sure, lambda creates a function, but all you do is reference the method self.remove. lambda will be called, self.remove not. Just self.remove as a slot is enough.
You should use clicked() signal (or clicked(bool), if you care about the checked value) from button:
deleteButton.connect(deleteButton, QtCore.SIGNAL('clicked()'), self.remove)
Edit
Another problem: Your remove method doesn't do what you want. removeItemWidget doesn't remove the item, it removes the widget inside the item (if you set one). It's counterpart to setItemWidget.
You should use takeItem to remove items.
def remove(self):
self.qList.takeItem(self.qList.currentRow())

LIBDBUSMENU-GLIB-WARNING

I created recently a piece of code that always showed me a message like this twice when I closed it:
(python:11712): LIBDBUSMENU-GLIB-WARNING **: Trying to remove a child that doesn't believe we're it's parent.
What I want is to get rid from that warning.
This piece of code reproduce such behaviour (the message appears once when closed):
import wx
class MyFrame(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__(self, parent, title="Sample")
menuBar = wx.MenuBar()
filemenu = wx.Menu()
filemenu.Append(wx.ID_ANY,"&Pass")
menuBar.Append(filemenu,"&File")
self.SetMenuBar(menuBar)
app = wx.PySimpleApp()
frame = MyFrame(None)
frame.Show()
app.MainLoop()
It works perfectly, yet the warning message appears when I close the app.
That's a Linux-only message, nothing appears when I tried it on Windows.
A work around I used was to bind a close event handler in my frame
def __init__(self, parent):
... # Previous code here
self.Bind(wx.EVT_CLOSE, self.OnClose)
And make such event handler as
def OnClose(self, evt):
for menu in self.GetMenuBar().GetMenus(): # (wx.Menu, caption) tuples
menu[0].Destroy() # Bad parents won't remove you, you'll DIE before!!!
evt.Skip()
That worked ok in that simple app on Linux, however it crashed when I tried on Windows. So I wanted to see what was happening in the runtime while on Linux, replacing the line
menu[0].Destroy()
to
print menu[0].Parent
And it showed me "None" as answer. However I couldn't make that:
menu[0].Parent = self
And neither:
menu[0].Parent = self.GetMenuBar()
Since both raises TypeError:
TypeError: in method 'Menu_SetParent', expected argument 2 of type 'wxMenu *'
This is a GTK warning. You could debug it (with gdb and a debugging variant of your Gtk and Glib libraries - e.g. libgtk-3-0-dbg and libglib2.0-0-dbg packages on Ubuntu or Debian) by running with the environment variable
export G_DEBUG=fatal-warnings
I have no idea if the bug is in Gtk itself, in WxWidget, in the C glues for Python, or in your Python code.

Building a gui app using wxPython

Am building a gui app using wxpython,i have created two separate windows in two different files,i.e app1.py and app2.py,I want to open the 2nd window(app2.py) using a button click on first window(app1.py). How do i achieve this. It would be great if someone can help,Thanks!!
I am assuming you're using wxPython's definition of "window" (i.e. anything that is actually viewable in the GUI), not the regular definition of "separate box with stuff in it and an X button in the corner" (which wxPython calls a "frame")
When I was writing my first wxPython GUI I was faced with a similar probem. I wanted actions in one panel to affect the data shown in another. My first solution was to write methods that blindly passed the request to the panel's parent until it reached the top level (my "main frame", if you will). This worked, but obviously it's a terrible solution.
My second solution was to use wxPython Events, just like catching button presses for a wx.Panel. My idea was I would create a button in one frame and bind wx.EVT_BUTTON with that button's ID in another. I made custom Events and CommandEvents. While trying to implement this solution I discovered that do not propogate and that CommandEvents will only propogate through the parents. So, if left uncaught a CommandEvent will eventually hit your "main frame" but it will never hit the second panel unless that panel happens to be a parent of where the Event came from. Obviously, this won't work for you since the parent can't be hidden but a child be visible. Plus it would leave your main frame cluttered with code and methods to delegate commands.
Finally, I found the answer! wx.lib.pubsub! Basically, you bind the button press in app1.py, just like normal. Now, in the handler you use pubsub to publish a custom message. Next, in the init for app2.py, you use pubsub to subscribe to your custom message (I like having a "message.py" where I declare all my messages as constants). When you subscribe to a message you assign a handler method, just like for events.\
Read this: http://wiki.wxpython.org/WxLibPubSub
Since you said you wanted the window to APPEAR, maybe in the init method for app2.py you call the Hide() method then when you receive the message, call Show().
When I implemented this in my application I was using wxPython2.8. I am now using 2.9 so I don't know if this is still necessary but I found that I need the top import in order to call pubsub.subscribe() and pubsub.sendMessage(). I kept getting errors otherwise. I can't remember how I figured this out, I think I saw it in a code sample and added it in a desperate attempt to make my code work. I suggest you read the documentation I linked above and try to implement your code WITHOUT that import first.
import wx
from wx.lib.pubsub import setupkwargs #I need this to force pubsub to work. I don't know why.
from wx.lib.pubsub import pub
ID_MYBUTTON = wx.NewId()
class App1(wx.Panel):
def __init__(self, parent):
wx.Panel.__init___(self, parent)
button = wx.Button(self, ID_MYBUTTON, "Show App2")
self.Bind(wx.EVT_BUTTON, self.handleButton, id=ID_MYBUTTON
def handleButton(self, event):
pubsub.sendMessage("mybutton.pressed") #send the message
class App2(wx.Window):
def __init__(self, parent):
wx.Window.__init__(self, parent)
self.Hide() #I don't want to be seen yet
pubsub.subscribe(self.gotMessage, "mybutton.pressed") #listen for the message
def gotMessage(self):
self.Show() #Now I want to be seen!
-----EDIT-----
I found this SO question that might help: Creating child frames of main frame in wxPython
Please tell us in detail what you're trying to do? wxPython also has "dialogs" which would be better than a frame if all you're doing is showing the user a message or asking for a bit more information. http://wxpython.org/docs/api/wx.Dialog-class.html
It really depends on what you're trying to accomplish. We can't help you unless you explain what problem you're trying to solve.
-----EDIT AGIAN-----
It's looking like the person asking the question did indeed want a wx.Dialog. For a tutorial, see http://zetcode.com/wxpython/dialogs/ Also see Python WX - Returning user input from wx Dialog

Create a PyGTK GUI with event to reload itself

I'm prototyping GUI layout with PyGTK, sometimes using glade/builder sometimes not, and the following scene repeats endlessly:
Modify the code
Run the GUI script
Judge the result
Modify again
Run again...
So, since I heard that Python allows reloading of modules, I would like to know if it is possible to modify the code WITHOUT CLOSING THE WINDOW, and then, from the window itself, say, clicking on a button, "reload" the window reflecting the changes in code.
Since it is a conceptual question, I don't have any specific code to show.
Thanks for the attention
I think it is possible if you do the following:
Identify and isolate the widget W that you want to see updated when you press the button (if you want to see the whole window updated, then make it whatever you add in the window, not the window itself).
Write a function (or class) that creates and returns this widget
Put this function or class in a module that you will reload
Create your button outside W and connect it to a function that does the following
Remove current W from window
Reload the module
Create new instance of W
Add it to the window
Of course, the critical step here is "reload the module". I guess you have to make sure no code from the module is running and no other module depends on variables defined on this module.
EDIT: I had some time, so I made a little prototype. Change the label in widget_module.py and then hit Update
gui.py
# Load in pygtk and gtk
import pygtk
pygtk.require('2.0')
import gtk
import widget_module
# Define the main window
class Whc:
def __init__(self):
# Window and framework
self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
self.window.connect("destroy", self.destroy)
# A Button, with an action
# Add it to the geometry
# show the button
self.button = gtk.Button("Update")
self.button.connect("clicked", self.update, None)
self.vbox = gtk.VBox()
self.vbox.pack_start(self.button)
self.widget = widget_module.get_widget()
self.vbox.pack_start(self.widget)
self.window.add(self.vbox)
# Show the window
self.window.show_all()
# Callback function for use when the button is pressed
def update(self, widget, data=None):
print "Update"
self.vbox.remove(self.widget)
reload(widget_module)
self.widget = widget_module.get_widget()
self.vbox.pack_start(self.widget)
self.widget.show()
# Destroy method causes appliaction to exit
# when main window closed
def destroy(self, widget, data=None):
gtk.main_quit()
# All PyGTK applicatons need a main method - event loop
def main(self):
gtk.main()
if __name__ == "__main__":
base = Whc()
base.main()
widget_module.py
import pygtk
import gtk
def get_widget():
return gtk.Label("hello")

Resources