0

In Python with gobject, I am having immense issues getting input from the user.

Here is my code:

def get_network_pw(self, e):
        def okClicked(self):
            print(pwd.get_text())
            return pwd.get_text()
            pwDialog.destroy()

        def cancelClicked(self):
            print("nope!")
            pwDialog.hide()
            return None

        #Getting the about dialog from UI.glade
        pwDialog = self.builder.get_object("passwordDialog")
        okBtn = self.builder.get_object("pwdOkBtn")
        cancelBtn = self.builder.get_object("pwdCancelBtn")
        pwd = self.builder.get_object("userEntry")
        # Opening the about dialog.
        #okBtn.connect("clicked", okClicked)
        #cancelBtn.connect("clicked", cancelClicked)
        pwDialog.run()

I am not sure where I am going wrong? It refuses to return the userEntry text. I also tried the code from Python/Gtk3 : How to add a Gtk.Entry to a Gtk.MessageDialog? and Simple, versatile and re-usable entry dialog (sometimes referred to as input dialog) in PyGTK to no avail.

EDIT I have a dialog I made in glade. It contains a GtkTextBox (userEntry), an Ok button (pwdOkBtn) and a cancel button (pwdCancelBtn). When the user clicks OK, it theoretically should return what they entered in the text box (say, 1234). When they click cancel, it should return None. However, when they click Ok, it returns "", and when they click cancel, it returns "". I'm not sure where I am going wrong here.

Extra code tries:

I tried the following code as well:

def get_network_pw(self, e):
        d = GetInputDialog(None, "Enter Password")
        dialog = d.run()
        if dialog is 1:
            print("OK")
        else:
            print("Nope!")
        d.hide()

GetInputDialog:

class GetInputDialog(Gtk.Dialog):
    def __init__(self, parent, title):
        Gtk.Dialog._init(self, title, parent)
        self.response = "Cancel"
        self.setupHeader()
        self.setupUI()

    def setupUI(self):

        wdg = self.get_content_area() #explained bellow

        self.txtSource = Gtk.Entry() #create a text entry
        wdg.add(self.txtSource)
        self.show_all() #show the dialog and all children

    def setupHeader(self, title="Get User Input"):
        hb = Gtk.HeaderBar()
        hb.props.show_close_button = True
        hb.props.title = title
        self.set_titlebar(hb)

        btnOk = Gtk.Button("OK")
        btnOk.connect("clicked", self.btnOkClicked)
        hb.pack_start(btnOk)

        btnCancel = Gtk.Button("Cancel")
        btnCancel.connect("clicked", self.btnCancelClicked)
        hb.pack_start(btnCancel)

    def btnOkClicked(self, e):
        self.response = "Ok" #set the response var
        dst = self.txtSource #get the entry with the url
        txt = dst.get_text()
        return 1

    def btnCancelClicked(self, e):
        self.response = "Cancel"
        return -1
Community
  • 1
  • 1
Cody Dostal
  • 311
  • 1
  • 3
  • 13

1 Answers1

1

I think you're overcomplicating it. The run method returns the id of the button pressed in a dialog:

  1. Don't use the .hide() and .destroy() methods in that way, those are for different situations. .destroy() destroys the widget, so you should not call it unless you know what you're doing.

  2. Place the .hide() after the .run().

  3. Capture the return value of the run(), and setup the buttons in the dialog to a different Response ID in Glade.

The relevant part of the code is:

def _btn_cb(self, widget, data=None):
    """
    Button callback
    """
    ret = self.dialog.run()
    self.dialog.hide()
    if ret == 0:
        self.label.set_text(
            self.entry.get_text()
        )

The full code for this example is here:

https://gist.github.com/carlos-jenkins/c27bf6d5d76723a4b415

Extra: If you want to check a condition to accept the Ok button (don't know, for example that the entry is valid) execute the run() in a while loop, check if button is Cancel then break, else check the validity of the input, if valid do something and break, else continue:

def _btn_cb(self, widget, data=None):
    """
    Button callback
    """
    while True:
        ret = self.dialog.run()
        if ret == -1:  # Cancel
            break

        try:
            entry = int(self.entry.get_text())
            self.label.set_text(str(entry))
            break
        except ValueError:
            # Show in an error dialog or whatever
            print('Input is not an integer!')

    self.dialog.hide()
Havok
  • 5,776
  • 1
  • 35
  • 44
  • I still can't get it to work. I added some more things I tried to the main comment. When I click the OK button, the text entry grays out, but it doesn't send back the response (1) or Ok (I tried checking both, and neither works). – Cody Dostal Aug 23 '14 at 02:29
  • That's not how it works. Again, you should not glue a callback the dialog buttons. What do you think it goes the return value of the button callback? It will magically appear as a return of the `run()` method? NO. Have you even tried the code I sent to you? – Havok Aug 23 '14 at 02:47
  • Sorry, I implemented half of it, and it didn't work, so I tried something else. After looking at the full example (sorry, I didn't notice the link) I was able to get it working. You are a godsend! – Cody Dostal Aug 23 '14 at 09:14