• Still the return problem

    From Luc@21:1/5 to All on Sun Nov 6 03:03:41 2022
    I am back to the old problem.

    Even if I make a "plain" page instead of a proc, I'd still need to be
    able to output something and exit - exit the proc/function, not the
    entire application. So the [exit] command is verboten.

    Now, either way, there is a part of the proc/application where a new
    widget pops up. That widget has to receive input, return it to the
    parent application (the one I'm working on) so the parent can proceed.

    I wrote this small prototype. Can you make the button return its
    output and destroy this entire window?

    Please remember this is supposed to be a child window. The parent
    window must be kept alive.


    namespace eval ::ops {}

    proc ::ops::run {} {
    # ----------------- MAKE WINDOW -----------------------
    package require Tk
    wm withdraw .
    eval destroy [winfo children .]
    catch {destroy .ops}
    set ::ops::w [toplevel .ops]
    wm resizable $::ops::w 1 1
    # -------------- TEXT BOX --------------
    text $::ops::w.textbox
    set ::ops::TextBox $::ops::w.textbox
    pack $::ops::TextBox -fill both -expand 1 -side left

    $::ops::TextBox configure -background #ffffff -foreground #000000
    $::ops::TextBox configure -width 30 -height 20
    $::ops::TextBox configure -wrap none -font "Freesans 16" -padx 10 -pady 10
    $::ops::TextBox configure -cursor arrow
    $::ops::TextBox insert end "Some text that is invisible because the box is so small.\n"
    $::ops::TextBox insert end "I don't know why the text box is so small."
    focus $::ops::TextBox

    button $::ops::w.textbox.button
    $::ops::w.textbox.button configure -width 5 -height 2
    $::ops::w.textbox.button configure -font "Freesans 16" -padx 4 -pady 4
    $::ops::w.textbox.button configure -text "Push"
    $::ops::w.textbox.button configure -command {return "Boom!"}
    pack $::ops::w.textbox.button

    bind $::ops::w <Escape> {exit 0}
    wm protocol $::ops::w WM_DELETE_WINDOW {exit 0}
    }

    puts [::ops::run]

    --
    Luc


    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Robert Heller@21:1/5 to [email protected] on Sun Nov 6 13:10:12 2022
    At Sun, 6 Nov 2022 04:35:07 -0800 (PST) fr <[email protected]> wrote:


    On Sunday, November 6, 2022 at 7:03:49 AM UTC+1, Luc wrote:
    I am back to the old problem.

    Even if I make a "plain" page instead of a proc, I'd still need to be
    able to output something and exit - exit the proc/function, not the
    entire application. So the [exit] command is verboten.

    Now, either way, there is a part of the proc/application where a new
    widget pops up. That widget has to receive input, return it to the
    parent application (the one I'm working on) so the parent can proceed.

    Hi Luc,
    my untested suggestion:
    catch {unset ::ops::result}
    ... -command {set ::ops::result Boom}
    and at end of proc instead of the 2 last lines - that end the process -
    vwait ::ops::result
    destroy $::ops::w
    return $::ops::result

    there is tk_dialog too, a modal dialog, that blocks interaction with other gui elements, so you won't need to hide the main window.
    Roland

    The source code for tk_dialog should be located someplace like:

    /usr/share/tcltk/tk8.6/dialog.tcl

    on a typical Linux installation.

    To vaugely misquote Obi Wan Knobie:

    "Use the Source Luc"

    The source code for tk_dialog is very verbosely documented and is very instructive about how to do exactly what Luc wants to do.






    --
    Robert Heller -- Cell: 413-658-7953 GV: 978-633-5364
    Deepwoods Software -- Custom Software Services
    http://www.deepsoft.com/ -- Linux Administration Services
    [email protected] -- Webhosting Services

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From fr@21:1/5 to Luc on Sun Nov 6 04:35:07 2022
    On Sunday, November 6, 2022 at 7:03:49 AM UTC+1, Luc wrote:
    I am back to the old problem.

    Even if I make a "plain" page instead of a proc, I'd still need to be
    able to output something and exit - exit the proc/function, not the
    entire application. So the [exit] command is verboten.

    Now, either way, there is a part of the proc/application where a new
    widget pops up. That widget has to receive input, return it to the
    parent application (the one I'm working on) so the parent can proceed.

    I wrote this small prototype. Can you make the button return its
    output and destroy this entire window?

    Please remember this is supposed to be a child window. The parent
    window must be kept alive.


    namespace eval ::ops {}

    proc ::ops::run {} {
    # ----------------- MAKE WINDOW -----------------------
    package require Tk
    wm withdraw .
    eval destroy [winfo children .]
    catch {destroy .ops}
    set ::ops::w [toplevel .ops]
    wm resizable $::ops::w 1 1
    # -------------- TEXT BOX --------------
    text $::ops::w.textbox
    set ::ops::TextBox $::ops::w.textbox
    pack $::ops::TextBox -fill both -expand 1 -side left

    $::ops::TextBox configure -background #ffffff -foreground #000000 $::ops::TextBox configure -width 30 -height 20
    $::ops::TextBox configure -wrap none -font "Freesans 16" -padx 10 -pady 10 $::ops::TextBox configure -cursor arrow
    $::ops::TextBox insert end "Some text that is invisible because the box is so small.\n"
    $::ops::TextBox insert end "I don't know why the text box is so small."
    focus $::ops::TextBox

    button $::ops::w.textbox.button
    $::ops::w.textbox.button configure -width 5 -height 2 $::ops::w.textbox.button configure -font "Freesans 16" -padx 4 -pady 4 $::ops::w.textbox.button configure -text "Push"
    $::ops::w.textbox.button configure -command {return "Boom!"}
    pack $::ops::w.textbox.button

    bind $::ops::w <Escape> {exit 0}
    wm protocol $::ops::w WM_DELETE_WINDOW {exit 0}
    }

    puts [::ops::run]

    --
    Luc

    Hi Luc,
    my untested suggestion:
    catch {unset ::ops::result}
    ... -command {set ::ops::result Boom}
    and at end of proc instead of the 2 last lines - that end the process -
    vwait ::ops::result
    destroy $::ops::w
    return $::ops::result

    there is tk_dialog too, a modal dialog, that blocks interaction with other gui elements, so you won't need to hide the main window.
    Roland

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Robert Heller@21:1/5 to [email protected] on Sun Nov 6 12:59:35 2022
    At Sun, 6 Nov 2022 03:03:41 -0300 Luc <[email protected]> wrote:


    I am back to the old problem.

    Even if I make a "plain" page instead of a proc, I'd still need to be
    able to output something and exit - exit the proc/function, not the
    entire application. So the [exit] command is verboten.

    Now, either way, there is a part of the proc/application where a new
    widget pops up. That widget has to receive input, return it to the
    parent application (the one I'm working on) so the parent can proceed.

    I wrote this small prototype. Can you make the button return its
    output and destroy this entire window?

    Please remember this is supposed to be a child window. The parent
    window must be kept alive.


    namespace eval ::ops {}

    proc ::ops::run {} {
    # ----------------- MAKE WINDOW -----------------------
    package require Tk
    wm withdraw .
    eval destroy [winfo children .]
    catch {destroy .ops}
    set ::ops::w [toplevel .ops]
    wm resizable $::ops::w 1 1
    # -------------- TEXT BOX --------------
    text $::ops::w.textbox
    set ::ops::TextBox $::ops::w.textbox
    pack $::ops::TextBox -fill both -expand 1 -side left

    $::ops::TextBox configure -background #ffffff -foreground #000000
    $::ops::TextBox configure -width 30 -height 20
    $::ops::TextBox configure -wrap none -font "Freesans 16" -padx 10 -pady 10
    $::ops::TextBox configure -cursor arrow
    $::ops::TextBox insert end "Some text that is invisible because the box is so small.\n"
    $::ops::TextBox insert end "I don't know why the text box is so small."
    focus $::ops::TextBox

    button $::ops::w.textbox.button
    $::ops::w.textbox.button configure -width 5 -height 2
    $::ops::w.textbox.button configure -font "Freesans 16" -padx 4 -pady 4
    $::ops::w.textbox.button configure -text "Push"
    $::ops::w.textbox.button configure -command {return "Boom!"}
    pack $::ops::w.textbox.button

    bind $::ops::w <Escape> {exit 0}
    wm protocol $::ops::w WM_DELETE_WINDOW {exit 0}
    }

    puts [::ops::run]


    OK, what you are creating is a clasic [modal] dialog box -- a popup toplevel that "waits" for user input (and may process that input) and then when the dialog box is done it is withdraw (to be re-used) or destroyed (if it is not going to be reused) and finally returns some result to the calling program.

    include this:

    namespace eval ops {
    variable w
    variable result
    }

    include at the beginning of the proc:

    variable w
    variable result

    Change the -command bound to the button to:

    $::ops::w.textbox.button configure \
    -command {set ::ops::result "Boom!"; destroy $::ops::w}

    and replace the last two lines of the proc with:

    bind $::ops:w <Escape> [list destroy $::ops::w]
    set ::ops::result ""
    tkwait window $::ops::w
    return $::ops::result


    Optional: look at the documentation for focus and grab -- the grab command
    can be used to make your dialog box have exclusive control.

    What happens is:

    the proc ::ops::run *waits* for the toplevel to be destroyed (closing it by default destroys it, as does <Escape> and your button). then returns whatever is stored in the ::ops::result variable -- this would be the result you want
    to return.

    You can't randomly "return" a value directly from a button press inside a dialog box (or really any sort of GUI effect -- keypress, mouse click, etc,.). The way a "dialog box" type of thing works (has to work), the GUI action sets
    a "global" variable (generally protected in a namespace or something), and
    then the dialog box is destroyed. The invoking code *waits* for the dialog box to finish either using "tkwait window ..." to wait for the dialog box to be destroyed or "tkwait variable ..." to wait for the result variable (or a flag variable) to be set or changed. The processing continues from the tkwait command -- the proc encompansing the dialog box can then return a result to
    the parent code.





    --
    Robert Heller -- Cell: 413-658-7953 GV: 978-633-5364
    Deepwoods Software -- Custom Software Services
    http://www.deepsoft.com/ -- Linux Administration Services
    [email protected] -- Webhosting Services

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Luc@21:1/5 to All on Tue Nov 8 09:08:57 2022
    Hello guys. I've been busy with work and had to put the Tcl/Tk project
    in the back burner for a few days, but I'd like to thank you for the
    generous assistance. The solutions did help, that old problem is solved,
    the project made more progress and I will be back to it as soon as I can.

    Thank you again.

    --
    Luc

    **************************
    On Sun, 6 Nov 2022 04:35:07 -0800 (PST), fr wrote:

    On Sunday, November 6, 2022 at 7:03:49 AM UTC+1, Luc wrote:
    I am back to the old problem.

    Even if I make a "plain" page instead of a proc, I'd still need to be
    able to output something and exit - exit the proc/function, not the
    entire application. So the [exit] command is verboten.

    Now, either way, there is a part of the proc/application where a new
    widget pops up. That widget has to receive input, return it to the
    parent application (the one I'm working on) so the parent can proceed.

    I wrote this small prototype. Can you make the button return its
    output and destroy this entire window?

    Please remember this is supposed to be a child window. The parent
    window must be kept alive.


    namespace eval ::ops {}

    proc ::ops::run {} {
    # ----------------- MAKE WINDOW -----------------------
    package require Tk
    wm withdraw .
    eval destroy [winfo children .]
    catch {destroy .ops}
    set ::ops::w [toplevel .ops]
    wm resizable $::ops::w 1 1
    # -------------- TEXT BOX --------------
    text $::ops::w.textbox
    set ::ops::TextBox $::ops::w.textbox
    pack $::ops::TextBox -fill both -expand 1 -side left

    $::ops::TextBox configure -background #ffffff -foreground #000000 $::ops::TextBox configure -width 30 -height 20
    $::ops::TextBox configure -wrap none -font "Freesans 16" -padx 10 -pady
    10 $::ops::TextBox configure -cursor arrow
    $::ops::TextBox insert end "Some text that is invisible because the box
    is so small.\n" $::ops::TextBox insert end "I don't know why the text
    box is so small." focus $::ops::TextBox

    button $::ops::w.textbox.button
    $::ops::w.textbox.button configure -width 5 -height 2 $::ops::w.textbox.button configure -font "Freesans 16" -padx 4 -pady 4 $::ops::w.textbox.button configure -text "Push"
    $::ops::w.textbox.button configure -command {return "Boom!"}
    pack $::ops::w.textbox.button

    bind $::ops::w <Escape> {exit 0}
    wm protocol $::ops::w WM_DELETE_WINDOW {exit 0}
    }

    puts [::ops::run]

    --
    Luc

    Hi Luc,
    my untested suggestion:
    catch {unset ::ops::result}
    ... -command {set ::ops::result Boom}
    and at end of proc instead of the 2 last lines - that end the process -
    vwait ::ops::result
    destroy $::ops::w
    return $::ops::result

    there is tk_dialog too, a modal dialog, that blocks interaction with
    other gui elements, so you won't need to hide the main window. Roland
    ************************

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)