Python Forum
[Tkinter] Threading a Tkinter GUI
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
[Tkinter] Threading a Tkinter GUI
#1
Hi all! I'm working on a GUI to control pulses of alternating current. I've seen many posts that talk about Tkinter being bad in the thread and I've been doing tests and yes, I really can not make it work the right way.
I have a raspberry connected to 5 AD converters( 3 writing and 2 reading), and I want my GUI continues working at the same time that analog values are read and written on the screen through label.

This is my code. I'm not very experienced in python but I'm doing my bests.

The two functions that I want to run on different threads are ValorAnalog and ConfirmarOna.

Thanks!
Reply
#2
Could you describe what those functions are supposed to do? If you're just writing a value out or reading something in, why is it so slow that it needs to be threaded? Or is it doing something else?

Also, this is terrifying:
Quote:
        t=1
        while(t==1):
            x = threading.Thread(target=ConfirmarOna)
            f = threading.Thread(target=ValorAnalog)
            Tiempototal=Tiempo1+Tiempo2+Tiempo3
            time.sleep(Tiempototal)
So you're creating an infinite number of threads, but never start any of them...
Reply
#3
Hi nilamo, first of all, I worked with root.after() and what I see is the following:

[Image: 4MVyMk.jpg]

more focused:

This is what my write function does.
The time that the reading function is taken, is the continuous state of the wave. And what I want is a wave that does not have these stops.

ConfirmarOna is the writer function and ValorAnalog is my reader function.


PD: sorry for that english, I'm spanish ^^'
Reply
#4
Let's start with just the reader, ValorAnalog.

(Nov-09-2018, 04:07 PM)Victor95 Wrote:
    def ValorAnalog():
        data = [0xC0,0x83]
        bus.write_i2c_block_data(0x48,0x01,data)
        time.sleep(0.1)
        data = bus.read_i2c_block_data(0x48, 0x00, 2)
        raw=(data[0] * 256 + data[1])
        rawstr=str(raw)
        LabelVoltage.config(text=rawstr+'V')
        time.sleep(0.1)
        data = [0xD0,0x83]
        bus.write_i2c_block_data(0x48,0x01,data)
        time.sleep(0.1)
        data = bus.read_i2c_block_data(0x48, 0x00, 2)
        raw2=(data[0] * 256 + data[1])
        raw2str=str(raw2)
        LabelIntensidad.config(text=raw2str+'A')

It looks like this function is doing four different things.
First, it writes to a pin:
data = [0xC0,0x83]
bus.write_i2c_block_data(0x48,0x01,data)
I'm guessing this is how you ask the sensor to give you data? It's almost identical (the only difference is the first element of data) to what you do further in the function.

Second, it sleeps for a bit time.sleep(0.1). Is this required? What purpose does this have?

Third, you read data from a pin:
data = bus.read_i2c_block_data(0x48, 0x00, 2)
raw=(data[0] * 256 + data[1])
rawstr=str(raw)
And then finally, you take that value that you read, and write it to some text field.

I think the function should be split into at least two smaller functions, to represent the different things it's doing. And all these magic numbers (0x48, etc) should be constants with meaningful names so it's easier to understand what's going on.

But to your actual question, the time.sleep(0.1) is the important part. If you can remove that, you might not need threads. If you can't (maybe you have to wait for something else to provide data after you ask for it, or something), then I don't think this function should touch the ui at all, and should use a queue (https://docs.python.org/3/library/queue.html) to stream values to the main thread.
Reply
#5
I have deleted the time.sleep and the wave is not bad but the analog values are not refreshed in the GUI.

I do not care if the sliders do not work, as long as the stop button works while the wave writing process is running, it's enough for me.
But that the analog values are displayed in the GUI is indispensable.

Also, I have removed the time.sleep and it has not gone badly. But the labels where the readings are written are not updated.
Now I have it like that:

This is working, but I need to refresh the Labels at the same time that this functions are working.

PD: sorry for late reply.
Reply
#6
Instead of root.after(0, function_name), try root.after_idle(function_name). Maybe the labels aren't being updated because they don't have a chance to, so hopefully by only running the callbacks when tk is idle, that sort of thing will get taken care of.
Reply
#7
Thanks for all Nilamo.

We did it!

At the time to see your post, my bulb went on. I put root.after(0,function) and labels can't update because it. I put root.after(1, function ) and for the reading I put root.after(900, function).
I don't care if I see the labels updating every 0.9 seconds. That's well at the end.

I'm so thanksfully with you!
If I could pay you I would :D

Thank you so much!
Reply
#8
(Nov-12-2018, 05:43 PM)Victor95 Wrote: If I could pay you I would :D
Well, actually... https://python-forum.io/misc.php?page=donations
Reply


Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020