Im making GUI with PyGTK. Im stuck with updating content in gtk.TreeView(), its reading from json. I want to add a new position in json and update the set_model(new content). I will update the file from three places (add content, delete content, rename content). So problem occurs when the changing is made in different modules. Don't know how to access the set_model from another module, so when I change the content the gtk.ScrolledWindow (it is placed in gtk.Window) it displays the updated content. I think the problem is associated with autorefreshing(timer?) or iterating (forgot the names of functions) but not for sure. When the whole program was in one class it was easy to implement changes but hard to read, now (many modules) it is easy to read but hard to maintain. I will appreciate any answer.
Update:
class Catalogs(object):
def _init_(self):
self.the_tree = gtk.TreeView()
<read from json>
self.new_list.append(output from json)
self.the_tree.set_model(self.new_list)
print'new_list content will be printed but not displayed in window'
self.window = gtk.ScrolledWindow()
self.window.add(self.the_tree)
Related
I am trying to implement a little application that logs in a user and the user after log in can add/update/delete contents to/of a textfile. Here's a rough sketch of the code I have so far:
class admin():
def __init__(self):
self.app = Tk()
.
self.name=StringVar()
update = Button(self.app,....,command=self.update)
.
.
.
def update():
#Function to take different entries using Entry widget of tkinter in another window
anotherapp = Tk()
nameentry = Entry(anotherapp,textvariable = self.name)
submitbutton = Button(anotherapp,....,command=submit)
.
.
def submit():
#Opens a file and adds entries to a textfile.
namevar = self.name.get()
# code to append to file
To explain the above, I have a class admin. Creating an instance of this class would open a window with buttons that say create, update, delete and so on. On clicking one of the buttons, the respective functions (defined in the same class) would be called (I use lambda: in case the function has arguments, but so far, it doesn't).
So in the code I've mentioned, say I click on the Update button, it should call the update function which opens another window and takes the text that has to be updated in the text file (via the Entry widget). So according to the code it'll update the value of name. On clicking submit, the function submit uses .get() to get the string value of name, and appends it to the text file.
The code executes with no error but it DOES NOT read the input from the user. Blank lines get appended to my textfile when I click on the submit button.
Now I don't understand why this isn't working. The name variable is defined in init and can be updated by the functions of the same class. I have tried a lot of things to make this work, including adding parameters in the button commands, defining name elsewhere, etc. Even though I've solved the error, I get the same result: the file gets appended with blank lines. I've also tried to make name a class variable but that doesn't work since it is declared using StringVar() which needs it to be part of a tkinter window. I think I've also tried nesting submit function inside the update function, but I don't know why that didn't work out or if I hadn't implemented it correctly.
I don't know if it has to do with the working of tkinter's StringVar() and .get() function.
I can't think of any other way to implement the situation I have at hand. I am open to taking suggestions on changing the structure of the code, as long as it is not something major major and manages to achieve the functionality that I've described.
I am sorry if I've missed something basic, cause I've only started trying out OOP in python recently. And thanks in advance for any help.
I am trying to make a copy of Notepad. Here, I want to get the name of the title of the tkinter window.
I need it because if the title of the window is Untitled - Notepad then I want to quit the program directly but if the title name is not Untitled - Notepad then I want to display message if you want to really quit the program.
How can I do so?
You can just use:
if root.title() == "Untitled - Notepad":
# do something
But that might not be the best way to do it.
#tobias_k put it well:
Don't read the title of your window to determine whether the file you are currently editing is "unnamed", or has already been saved, or has been changed since the last save. Instead, keep this information in some dedicated attributes of your editor class, and use those to determine the title of the editor window. Otherwise, it will be a mess if you ever decide to change the format of the title. Also, what if the file is literally named "Untitled"?
I am beginning to work on a program in which i want multilingual support, but since it is pretty modular (and i want it to be even more in the future), a language change means "destroy what you had of interface and build again with the content which language modules have". (You can see the source as of now on GitHub)
This full-modular approach may give many problems, but i still want it, and so the problem is: Whenever i destroy the widgets i had, until i am alone with the raw Gtk.Window itself, i am not able to assign once again widgets to it. They won't get displayed at all, sometimes silently, sometimes with errors depending on my approach.
Lets suppose the class window, which inherits from a Gtk.Window.
This class is the raw window, and i assign to it a Gtk.Box -
self.interface.
self.interface itself, has two Gtk.Box's, one sidebar and one stack of contents.
To rebuild i tried to:
Change the language variable
Use the method destroy on self.interface, which removes the widget and its child's.
Reuse the function to build the widgets stack on top of self.interface
Re-add self.interface to self (window).
This approach returns:
g_object_unref: assertion 'G_IS_OBJECT (object)' failed
Gtk.main()
Pointing to the .show_all() method in this file.
I've already tried to leave interface without using .destroy on it, applying only on its child's, and then creating them again over it, but didn't worked. The window was left blank with no error at all.
The code i am trying right now is:
#Remember, self is a Gtk.Window()
def __init__(self):
[...]
self.interface = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
self.stack = None
self.add(interface)
self.build_interface()
def build_interface(self):
self.interface.pack_start(
self.create_side_navigation(
self.interface_data["menu"][self.language]["name"])
, False, False, 0
)
self.stack = self.create_content_stack(self.interface_data["menu"][self.language])
self.interface.pack_start(self.stack, True, True, 0)
###Code to rebuild(this is a question dialog):
if response == Gtk.ResponseType.OK:
self.language = self.new_language["Index"]
self.new_language = None
self.stack.destroy()
self.interface.destroy()
self.interface = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
self.build_interface()
self.add(self.interface)
This code will cause the previously told "g_object_unref" error.
What is causing this? Why can't i add anything once deleted?
Feel free to clone the repo and try, the code is well commented(yet i am not sure if poorly written, i am a python newbie) and its quite easy to understand where is the problematic part. Its not too big.
PS: It should need GTK+3.12 because of the popovers.
As a GTK Dev showed to me, GTK has by default all the widgets invisible.
The error was caused in the line which declared the whole interface visibility (windowclass.show_all()), but since the interface changed since when it was applied, it threw that warning.
He pointed me to .remove() instead of .destroy(), and to set .show_all() to the new elements after set up.
The next commit(or the following) on that git, has the solution.
The best way to be multilingual is to keep your widgets the same and merely change the text of labels and titles. This can be done without disturbing the overall setup. For example:
s='Stop'
if lang=='fr': s='Arret'
...
somelabel.set_label(s)
I am trying to create a program in tkinter that allows people to rename a log file to whatever is typed into a text entry box. However this is not going to plan.
EDITED Thanks to Bryan Oakley.
I have slaved the rename function to a button however my new issue is that the values for contents are a weird set of numbers. These appear to be randomly generated every time I run the rename function.
These numbers look like
44499952get
44452520get
46401376get
46400496get
44688048get
44697440get
Can anyone please help or explain what these numbers mean?
Look at this code:
newname_ent = Entry(self,width = 50,)
contents = newname_ent.get()
It seems highly unlikely that the user will be able to type in something in the millisecond or so between creating the widget and getting the value.
You need to create a button or set an event binding that will call a function after the user has the chance to enter some information. That function is where you will put the code to do the rename.
First time poster, found the site very helpful before registering though.
I am having issues using Tkinter on Python 2.7 (Windows7):
The code (I have truncated it because the whole thing is massive) looks something like this:
-------------------------------------------------------
CODE:
#set up stuff, importing variables, etc, then we have:
class App:
global RXSerial
RXSerial=''
#The following lines define the topFrame, lays out the widgets.
def __init__(self, master):
topFrame = Frame(master)
topFrame.pack()
middleFrame = Frame(master)
middleFrame.pack()
#--------------defining state variables------------
self.inputConsole = Text(middleFrame)
self.inputConsole.insert(INSERT,"Data recieved from Serial:")
self.inputConsole.config(width=100,height=20)
self.inputConsole.pack(side=LEFT,padx=20,pady=20)
#blah blah blah, insert a bunch of stuff (buttons etc.) here:
#The following lines define the functions to be called when the buttons are pressed.
def engineFire(self,engineUse,pwm):
RXSerial='this should pop up in the text called inputConsole'
print RXSerial
self.inputConsole.insert(INSERT, RXSerial)
---------------------------------------------------
so yeah, basically RXSerial is a string (that I have checked that is working, the print RXSerial line successfully prints when called by a button. The problem is that the self.inputConsole.insert(INSERT,RXSerial) line is not working. Can anybody please help? I have tried a bunch of combinations of stuff but cant seem to get it working. Thank you.
If you're trying to insert the text from another thread it may fail to work. Also, if at some point you configured the text widget to be in the disabled state then inserting will fail. If that's the case (widget is disabled), setting the state to "normal" temporarily will solve the problem.
Without more information it's impossible to say for sure.