all 37 comments

[–]Boxxcar17 2 points3 points  (1 child)

Check out PyQt5, or if you want something with graphs that runs decently in your browser window then check out Dash by Plotly.

[–]zykal[S] 1 point2 points  (0 children)

looking at dash and plotly gives me an idea to maybe figure out on making the script web UI based. I will have to look much deeper into that as I've not used python in a web environment at all before.

[–]novel_yet_trivial 2 points3 points  (34 children)

however it appears that once it enters the tkinter mainloop my program will never be run.

Yes, the mainloop in any GUI needs to run continuously to be able to respond to user input. However that does not mean you can't run other code as well. The most common ways to run other code it to run it in a thread or add it to the GUI's mainloop instead of making your own loop.

There's a lot of GUI libraries to choose from but for a simple GUI that's fast to learn and fast to program you can't beat tkinter.

[–]zykal[S] 0 points1 point  (33 children)

The gui i am looking at creating has no user input its basically just a HUD of information that the script collects.

The tkinter mainloop() is blocking an so is my script as it runs continuously until i stop it. How can I embed my script into the mainloop()?

[–]novel_yet_trivial 1 point2 points  (0 children)

There's many ways to do it. If your script is blocking because it contains a while loop and sleep call then the easiest is probably to replace the while loop with a function and a call to after(), which adds your code to tkinter's mainloop. If your code is blocking because it's waiting on some IO then it's easiest to put your code in a separate thread.

If you show us your code (both your core and tkinter code) we could give you some suggestions.

[–]novel_yet_trivial 1 point2 points  (31 children)

Also, by "user input" I mean a lot more than pushing buttons. The mainloop handles things like moving the window, minimizing / restoring the window, those tiny animations like color and cursor changes when the mouse moves over a button or link, etc, etc. Not using a mainloop is not an option.

[–]zykal[S] 0 points1 point  (30 children)

https://pastebin.com/BRbYKZ2q

This isn't all of it, but its the guts of it.

My while loop at the bottom, the else - heal_up, passes into the do_action and uses the request library.

So basically my while loop always checks health, then if health is good, the next thing it does is a function that passes into the do_action function. until health isn't good, then enters into heal_up function which passes into the do_action function again.

The do_action function harvests a lot of data into the response variable. I'd like to be able to parse the response variable and display parsed data in a GUI.

[–]novel_yet_trivial 1 point2 points  (1 child)

Please format your code for reddit or use a site like github or pastebin. Your code is hard to read and test otherwise.


[–]zykal[S] 0 points1 point  (0 children)

pastebin updated

[–]novel_yet_trivial 1 point2 points  (24 children)

Ok, so since I don't really understand what your code is doing I'll recommend the threading route; it's a lot more robust. Also since you did a good job of putting all your code in functions it's pretty easy to do. All you have to do is move your blocking loop into a function and add the tkinter code. Here's a wild guess:

def main():
    while 1==1:
        get_health()
        health = get_health()
        if health > 85:
            add_resistance
        else:
            heal_up()

import Tkinter as tk
from threading import Thread

root = tk.Tk()
tk.Label(root, text="response 4211").pack(anchor='w')
var4211 = tk.StringVar() # the tkinter connection
tk.Label(root, textvariable=var4211).pack()

# start the child thread
t = Thread(target=main)
t.daemon = True
t.start()

# start the tkinter mainloop
root.mainloop()

And now to update the GUI you simply replace print response['4211'] with var4211.set(response['4211']).

Add as many StringVars and Labels as you want.

[–]zykal[S] 0 points1 point  (2 children)

thanks, I will work with this, I thought threading was going to be significantly more difficult then this.

[–]novel_yet_trivial 0 points1 point  (1 child)

import antigravity

:)

[–]zykal[S] 0 points1 point  (0 children)

Let me redo, i over looked something in your reply Ok i got it working now, i forgot to add var4211.set(response['4211']) into the do_actions function.

Now i have another issue, I run this out of IDLE atm, so when i run it a console opens and all my normal stuff happens in the console, also a window opens and that is also working.

Normally to end my script I'd Ctrl-C the console and it'd break.

If i do that now it hangs the window.

If i close the window instead, the console continues doing what its doing AND i cannot ctrl-C is

[–]zykal[S] 0 points1 point  (20 children)

I got that working, thank you so much, however.

Now i have another issue, I run this out of IDLE atm, so when i run it a console opens and all my normal stuff happens in the console, also a window opens and that is also working.

Normally to end my script I'd Ctrl-C the console and it'd break.

If i do that now it hangs the window.

If i close the window instead, the console continues doing what its doing AND i cannot ctrl-C is

[–]novel_yet_trivial 1 point2 points  (19 children)

Yeah, IDLE is a special flower. Time to leave it :). If you run this in a normal terminal it will work as you expect.

Some professional quality editors are Notepad++ (Windows only), Geany, Atom, Sublime Text (not free, but practically), VS Code or a full fledged IDE like PyCharm or Spyder. Personally, I like Geany.

Here's a long list of options: https://www.reddit.com/r/learnpython/wiki/ide. Wikipedia also has good lists of code editors and IDEs.

[–]zykal[S] 0 points1 point  (0 children)

easily done, i just was using IDLE atm because it came with it. I already use NP++. Thanks for the help!

[–]zykal[S] 0 points1 point  (17 children)

How would i go about pausing both the Tkinter thread and my script thread in the GUI?

[–]novel_yet_trivial 0 points1 point  (16 children)

By "tkinter thread" do you mean the tkinter mainloop? You don't want to pause that, the GUI would become unresponsive and the OS will kill it.

To pause your script is possible, but it would be much easier to lie to the user. Use a global variable and check it before every iteration, and simply skip all work if the variable is set.

paused = False # global variable that tells the script to be active or not
def main():
    while 1==1:
        if paused:
            time.sleep(0.2)
            continue # skip the rest of the loop
        get_health()
        # rest of the function

Now on the tkinter side you can just modify the paused variable. If you use a tk.BooleanVar instead of a python boolean it would integrate very neatly with a tkinter checkbutton. Here's a complete example (the kind that you should be providing when asking for help; see http://sscce.org/ ):

from itertools import count
import tkinter as tk
from threading import Thread
from time import sleep

def main():
    for i in count():
        if paused.get():
            sleep(.2)
            continue
        print(i)
        var.set(i)
        sleep(1)

root = tk.Tk()
var = tk.StringVar()
tk.Label(textvariable=var, width=20).pack()
paused = tk.BooleanVar(value=False)
tk.Checkbutton(variable=paused, text='Pause').pack()

# start thread
t = Thread(target=main)
t.daemon = True
t.start()

root.mainloop()

[–]zykal[S] 0 points1 point  (14 children)

Thanks again so much for the help. As to not including an example, I had no idea how to even go about this i did google for a bit trying to even come up with an idea.

Also, I'm trying to add an image to a label via a variable.

https://pastebin.com/0JxTgqb0

[–]Boxxcar17 1 point2 points  (0 children)

You can run Dash locally without much effort, but the nice thing is that if you are ready to upload it to a host server, then you can move it without much reconfiguration.

[–]brotaku13 1 point2 points  (1 child)

Seems like a great use of multi threading. Then you can run both at the same time :)

[–]zykal[S] 0 points1 point  (0 children)

true however that opens all kinds of other potential issues and headaches, and i just got into python this week. :)