Calling function in different class in Tkinter GUI (Python 3.4) - python

I have a tkinter GUI that I structured based on Bryan Oakley's post here. I have a container class and some other classes. I have a button in my navigation class that is trying to call a function in the container class. For some reason I cant get self.parent... to work and have to type in Container... to get the function to work. The first line of code below works but the second line gets the error you see below.
self.Clear.bind("<Button-1>", lambda event: self.parent.combine_funcs(self.parent.ChangeRange(F_Clear), Container.UpdateToolBar(self, F_Clear)))
self.Clear.bind("<Button-3>", lambda event: self.parent.combine_funcs(self.parent.ChangeRange(F_Clear), self.parent.UpdateToolBar(self, F_Clear)))
TypeError: UpdateToolBar() takes 2 positional arguments but 3 were given
It only has a problem with the UpdateToolBar def...
def UpdateToolBar(self, file):
self.parent.ToolBar1.itemconfigure('toolbar', text=('CalcTime: '+str(self.parent.total)[:5]))
If I change the code to:
self.parent.UpdateToolBar(F_Clear)))
I get:
AttributeError: 'Container' object has no attribute 'parent'
I'm hoping the answer to this will give me more insight into interacting with code in different classes.

Related

Python 3.5 'master' and 'widgetName' in "__init__"

I'm calling another python file from the current file, and using a function that calls all functions in the other file.
def choose1():
def openthis():
import board1
for i in dir(board1):
item = getattr(board1,i)
if callable(item):
item()
if __name__ == '__main__':
openthis()
Note: board1 is a python file.
With this function, I get the error:
TypeError: __init__() missing 2 required positional arguments: 'master' and 'widgetName'
I have looked around, and saw this answer, but it did not mention master and widgetName, and I'm unsure of what they mean and what I should do.
if callable(item):
item()
item is a class, and you're attempting to create an instance of that class, but that class has two required arguments, and you're not passing any arguments at all.
Your file imports all of tkinter and random directly into its own namespace. So, when you iterate over everything in that namespace, you get the objects from those modules too.
One fix would be to not use from ... import *, but import the modules themselves - import tkinter. But really the full fix is not to do what you're doing at all.

Tkinter button linked to function with argument gives TypeError

I'm trying to run a function called password() with argument "t" on pressing a button in Tkinter.
Problem is that this gives me a TypeError even though the code seems alright.
self.Button5.configure(command=lambda t='restart': password(t))
Error:
TypeError: 'str' object is not callable
(here is a link to whole code if necessary, error is on line 372: https://codeshare.io/G8VW6A)
In line 103 of your code you create global variable 'password', which has the same name as your function. Just change the variable names so they don't clash.

How to react on a click in PyQt4 QTreeWidget

I am new to Pyhthon and Qt, hence this basic question. What I want is that when I click an item in a QTreeWidget an event handler is called which tells me which item has been clicked. The code I tried is:
self.dir_tree = QTreeWidget ()
self.dir_tree.setColumnCount (3)
self.dir_tree.setHeaderLabels (("File", "Type", "Size"))
self.dir_tree.connect (dir_tree, SIGNAL ("itemClicked (QTreeWidgetItem*, int)"), self.onClickItem)
def onClickItem (self, column):
print (column)
This does not run, the error code is:
TypeError: arguments did not match any overloaded call:
QObject.connect(QObject, SIGNAL(), QObject, SLOT(),Qt.ConnectionType=Qt.AutoConnection): argument 1 has unexpected type 'function'
QObject.connect(QObject, SIGNAL(), callable, Qt.ConnectionType=Qt.AutoConnection): argument 1 has unexpected type 'function'
QObject.connect(QObject, SIGNAL(), SLOT(), Qt.ConnectionType=Qt.AutoConnection): argument 1 has unexpected type 'function'
What am I doing wrong? And a question related to this: how can I figure out which item was clicked?
I could not find a tutorial for this, any suggestion is welcome.
Thanks for any help.
Question asked too early, I found the answer after a lot of experimenting. The code was wrong in not mentioning self.dirtree and connecting from self.dir_tree instead of self. So the correct code should be:
self.connect (self.dir_tree, SIGNAL ("itemClicked(QTreeWidgetItem*, int)"), self.onClickItem)
And some experimenting led to the following callback:
def onClickItem (self, item, column):
print (item, column)
Item refers to the clicked QTreeWidgetItem itself (in my case it is a derived class with extra information: still works fine) and column to the clicked column.
The last question still stands. I have still not a good grasp of signals/slots. Any pointer to a good tutorial is welcome.

How to refer to a base instance python gtk widget from a function in a module

I am writing a Python GTK application for studying some sort of math data. The main script has a single class with only three methods: __INIT__, main(self) for starting the loop and delete_event for killing it.
__INIT__ creates the GUI, which includes a TextBuffer and TextView widgets so that the analysis functions (defined on a separate functions.py module) can output their results to a common log/message area. A relevant extract follows:
include module functions(.py)
(...)
class TURING:
def __init__(self):
self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
(...)
self.logscroll = gtk.ScrolledWindow()
self.logscroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
self.logbuffer = gtk.TextBuffer()
self.logpage = gtk.TextView(self.logbuffer)
self.logpage.set_editable(gtk.FALSE)
self.logpage.set_cursor_visible(gtk.FALSE)
self.logpage.set_wrap_mode(gtk.WRAP_CHAR)
self.logscroll.add(self.logpage)
self.logscroll.show()
self.logpage.show()
(...)
enditer = self.logbuffer.get_end_iter()
self.logbuffer.insert(enditer, 'Welcome!')
(...)
def main(self):
gtk.main()
if __name__ == "__main__":
turing = TURING()
turing.main()
The intermediate two lines successfully print a welcome message onto the message area defined by self.logpage.
Now, one of the functions in method functions checks whether the database is up to date and if not asks the user to load a new batch of raw data.
One way of doing this is to include a menu item that triggers that function, like this:
item_dataCheck.connect("activate", functions.data_check, '')
functions.data_check runs fine however when it tries to write its output to self.logbuffer an error is thrown complaining that menu item item_dataCheck has no property logbuffer. The offending code is
enditer = self.logbuffer.get_end_iter()
self.logbuffer.insert(enditer, 'Please update the database.')
Obviously the name self is representing the widget that invoked the function, viz., item_dataCheck. My question is how can I from functions.data_check refer directly to logbuffer as a member of the turing instance of the TURING class. I tried to write
enditer = turing.logbuffer.get_end_iter()
turing.logbuffer.insert(enditer, 'Please update the database.')
but that's is not working. I have tried hard to find a solution but with no success.
I believe the matter is quite trivial and I know I still have some serious conceptual problems with Python and OOP, but any help will be heartly appreciated. (I started out card punching Fortran programs on a Burroughs mainframe, so I could count on some community mercy...)
You can provide additional arguments when connecting signals to functions or methods. So your handler functions.data_check can accept extra arguments apart from self:
def data_check(self, logbuffer):
# ...
Then, you can connect with arguments:
item_dataCheck.connect("activate", functions.data_check, logbuffer)
Also, the self parameter is normally used as the first parameter in method definitions. This is a very strong convention so you should use obj or something similar instead. Specially since your signal handlers may be methods too; in which case you could mess it up with its arguments.

Need help with Classes in Python

I'm making a program that imports a custom widget that is a class (it inherits from the Tkinter Frame widget). It all works great until I get to binding. To reduce confusion we'll call the main application app, the module it's importing the widget from lib, and the widget that's being imported into app will be called cwid.
Basically I need to somehow reference a function in app, so that it may be bound to my widget in lib.
The function I'm trying to bind a widget within cwid to is element_click (The function element_click is in app.):
lambda event: element_click(event, elementinfo[3])
So the binding would look something like this in lib (element is a canvas widget within cwid)
element.bind('<ButtonRelease-1>', lambda event: element_click(event, elementinfo[3]))
The above line wont work however seeing as element_click is in app. So I tried a work around which doesn't seem to be working.
import app
loc = app.EOG
element.bind('<ButtonRelease-1>', lambda event: loc.element_click( event, elementinfo[3]))
When I try the above I get the following error:
TypeError: unbound method element_click() must be called with EOG instance as first argument (got Event instance instead)
EOG is a class in app which contains element_click.
Also, all of the above bits of code are snippets.
EDIT:
Tried loc = app.EOG(), and go the following error:
AttributeError: EOG instance has no attribute '__nonzero__'
I think you just want:
loc = app.EOG()
Then, loc is an instance of EOG, and loc.element_click is a bound method, so it works as intended.

Categories