This is related to another question I found here that seems to be inactive for a few months, so I think it's worth asking again.
I have created a simple QDialog that has a QTextEdit and a QPushButton. This pops up in my application when a user right-clicks and selects the option to "add comments". I want them to be able to write free-form text and I'll just save whatever they write as a long string with no concern for new lines, etc.
When the user clicks the button, it executes code like this:
self.connect(accept_button,QtCore.SIGNAL('clicked()'),lambda arg=str(view_textedit.toPlainText()): self.updateGroupComments(arg))
def updateGroupComments(self,new_comment_str):
print "Updating user comment to have new string: " + new_comment_str
self.group_entry.list_of_user_comments[self.currentFrameCounter] = new_comment_str
This is not detecting the TextEdit text that is visible (it only detects whatever the text edit text is set to when it is created). How do I make a simple command that returns the currently visible text from a QTextEdit. Again, the function
toPlainText()
is not working correctly... it doesn't find the currently visible text, only whatever text was on screen before changes or additions started being made by the user.
If this can't be done without subclassing and appealing to cursor positions, it makes the whole thing seem worthless... so please keep suggestions only to those implemented without subclassing or manipulating cursors. It should be really simple and straightforward to just return all currently visible text... what am I missing?
Objects that are being bound to default arguments are evaluated at the definition time. The function is working correctly, it returns whatever was in the text field when it was executed. Your code simply calls it at the wrong moment. If you want to use lambda, then do:
self.connect(
accept_button, QtCore.SIGNAL('clicked()'),
lambda: self.updateGroupComments(str(view_textedit.toPlainText()))
)
Or make view_textedit an instance attribute instead, and do simply
self.connect(
accept_button, QtCore.SIGNAL('clicked()'), self.updateGroupComments
)
And change updateGroupComments to call self.view_textedit.toPlainText instead of taking an argument.
BTW, this is not PyQt specific, this is how Python works in general.
To illustrate my last comment, that lambda can very well be replaced with:
def slot():
self.updateGroupComments(str(view_textedit.toPlainText()))
self.connect(accept_button, QtCore.SIGNAL('clicked()'), slot)
Related
So I've created a GUI for a program I'm writing, and what I'm currently stuck on is the running of the calculations I want it to perform. I've done everything in Python 3.5, with a Kivy GUI build string to create the tabs (using tabbed panel and screen manager). I've got a button at the bottom of the tab to which this question pertains which says "Calculate" and should be taking the values of the text entries and operating them as part of the equation I want them to do.
Is the
.get
function going to be helpful in this case for doing this, or do I want to call more like:
class TabSys(TabbedPanel):
def calculate_psc_clicked(self):
#when they click the button which is id'd as "calculate_psc," this function
#will pull the values and perform the calculations
self.Cp_entry = self.Cp_entry.text
self.P_entry = self.P_entry.text
self.lhv_entry = self.lhv_entry.text
The above code is the TabSys class for my build string in kivy language, after it comes the
class nyce_meemApp(App):
def build(self):
return TabSys()
if __name__ == '__main__':
nyce_meemApp().run()
To actually run all the code. I don't want to inundate the question with code, so I'll leave it there, and I can put up any other pieces of code that anybody wants (if need be I can share the file).
Thanks
I am new in Python and in tkinter so the question may seems naive: is it ok to create and place widgets at the same time if I don't need to change them?
It works but is it a good practice? And if not why?
An example of what I mean:
import tkinter as tk
window=tk.Tk()
tk.Label(window,text='Lost Label').pack()
window.mainloop()
To expand upon #Skynet's answer....
Whenever you do Widget(*args, **kwargs).pack() the pack() method returns None as would other geometry managers, so if you tried to assign this to a variable the variable would be None.
In this case then probably not, since you probably actually want to be storing the reference to the widget.
If you don't need a reference then there's not really a problem with it. As the other answer notes you don't need a definitve reference to every single widget in your GUI unless you plan to use this reference in some way. Unless I plan on changing the label text / modifying it in someway then I typically use your method to save some space. No need to write more code than you have to!
For example you're creating a Button widget.
btn = Button(blabla, text="Button1")
This returns a button object and if you need later to configure it or get information about it you can do it by through the btn variable.
But if you use something like btn = Button(blabla, text="Button1").pack() it returns None and not a button object so you won't be able to change anything about the button or get information about it later.
Another example is with the Entry widget
entry = Entry(blabla)
Using that later you can do entry.get() to get the text inside the entry
but you won't be able to do it if you use entry = Entry(blabla).pack() since it doesn't return an entry object, it just packs the widget and you won't be able to access it for later use.
There is nothing wrong with that approach and I have already seen it quite a few times. You don't have to keep a reference to every widget in your GUI.
I'm reading Programming Python by Mark Lutz, and I came across this bit of code that I don't get.
buttons = []
def onpress(i):
global state
state = i
for btn in buttons:
btn.deselect()
buttons[i].select()
I get what it's doing, but I don't get where these select and deselect methods are coming from. I've never seen these list methods before (I and the book are using Python 3). Are these builtin methods? And what do they do? I tried using my Google-fu to figure it out, but to no avail.
http://www.java2s.com/Tutorial/Python/0360__Tkinker/Deselectforradiobuttonssimplysetsthebuttonsassociatedvaluetoanullstring.htm
So a quick google, if you are doing this it means you are most likely using tkinter in which case you have missing relevant code somewhere.
Those methods .deselect() and .select() are actually tkinter Radiobuttons() methods. If you're tutorial reverences tkinter. "from tkinter import *" will import those class's. If not i have no idea why its being taken out of context.
But what this code does is, it takes 'i', which is a button you click, then it sets 'state' to 'i', making 'state' 'global' over writing the last 'state', then it deselects all buttons, and selects 'i' which is your new choice. In effect this means you'll only ever select 1 button
If you wonder why state is an empty string, its because an empty string is the first button in tkinter. When you pass a new string in, it gives the new item being something like "I001" or something.
I am trying to code a program with a regular file menu. (e.g. File, Edit, View, etc).
I want the action they take in that menu to update my status bar (a label).
The problem is, the way I have it setup now, I believe it's executing the command and then trying to take the result as what it should do.
Currently a menu item is defined like so:
fileMenu.add_command(label="Insert", command=self.statusUpdater(statusLabel,"Insert Triggered")
And the function statusUpdater is defined as such:
def statusUpdater(self,status,commandName):
status.config(text=commandName)
status.update_idletasks()
So the problem is, right at the start of the program, the status changes to "Insert Triggered". What I want is for that to only happy once I have actually clicked "Insert"
From hints I've seen elsewhere it seems like I need some way to pass and handle the event of Insert being clicked.
Could someone supply a generic and basic function that does what I ask? I think the problem lies in the () attached to the command function, but I don't know any other way to pass arguments.
All i need is a function that is called on the click event, and knows which fileMenu command triggered it.
Thanks!
Commands take a reference to a function. You can se a lambda if you want to pass it arguments:
...command=lambda l=statusLabel, self.statusUpdater(l, "Insert Triggered"))
My app has a GtkFileChooserButton that you can use to open a chooser widget and pick a single file .. and then perform operations on that file. This works.
I've added drag & drop functionality to the button as well. It works, but it's buggy.
In short, the first dnd to the FileChooserButton triggers the file-set signal and appears to have worked, -- the name changes from "( None )" to the file's name and if you then click on the button, it pops up a chooser widget showing the proper file selected; HOWEVER, as you can see from the debug output below, get_filename() does not return the filename! Not the first time, anyway.
The second time we dnd a file onto the button (whether it's a different file or the same file again), all goes well and get_filename() returns the file's name. Why?
Here's the debug output from my program when I drag three files on to the button, one at a time:
[on_file-set] FileChooserButton.get_filename() output:
None
[on_file-set] FileChooserButton.get_filename() output:
'/home/ryran/Desktop/priv.txt'
[on_file-set] FileChooserButton.get_filename() output:
'/home/ryran/Desktop/kinamppost'
PS: When I did this, the 1st and 2nd dnd were actually the same file.
If you want to see the full app in action, it's at http://github.com/ryran/pyrite, and I'd love to post code, but there's not really anything to post!! I'm not doing drag_dest_set() because FileChooserButton already supports dnd. So ALL I'm doing is defining a cb for the FileChooserButton's file-set signal. So uhh.. here's that:
def action_chooserbtn_file_set(self, widget):
print "[on_file-set] FileChooserButton.get_filename() output:\n{!r}\n".format(widget.get_filename())
For the record I also tried doing all this in concert with defining drag_dest_set, but came up with the same results.
What else to say? I'm starting to think this is a bug.
Turns out this really is a GTK+ bug. Talked to a developer on IRC. He helped me realize that and then encouraged me to post a bug report, which I did -- https://bugzilla.gnome.org/show_bug.cgi?id=669718