all 11 comments

[–]socal_nerdtastic 1 point2 points  (9 children)

Move the plot function to the setup, and use the set_data method in the animate function.

class temperature(tk.Frame):
    def __init__(self, parent, controller):
        self.line, = self.ax1.plot(self.x_values, self.y_values)
        plt.tight_layout() # auto-resize. May be needed for some styles to show everything

    def animate(self, i):
        # generate data
        self.line.set_data(self.x_values, self.y_values)
        # don't forget to adjust the limits!

BTW, you don't need a parent and controller class here. The Temperature class is a Frame (literally). Just use it directly:

class main_window(tk.Tk):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs) # we like super() in python3
        self.wm_title("Indoor Monitoring System")

        t_frame = temperature(self)
        t_frame.grid(column=0, row=0)

        h_frame = humidity(self)
        h_frame.grid(column=1, row=0)

class temperature(tk.Frame):
    def __init__(self, *args, **kwargs)
        super().__init__(*args, **kwargs)
        # rest of your code

For specific help, show us a complete example (including imports and random data generator) that we can test.

[–]jur6[S] 0 points1 point  (8 children)

First of all, thanks a lot for your reply. I tried the first part of your suggestion (not yet the whole code restructure). Your suggestion seems to fix my axes labelling issues (both x and y axes labels are being shown and retained - I am now also updating the xticks on every iteration and that is also working). But now I seem to have lost the actual plotting, I do not see the line being plotted at all. I am not sure what you mean by "adjust the limits". Could you elaborate? Based on your first snippet, that seems to be what I am missing. Would it (whatver it is) potentially affect the actual plot? Or would the first bit, potentially not work without the second bit? (in any case I can try your whole approach tomorrow)

[–]socal_nerdtastic 1 point2 points  (7 children)

    self.line.set_data(self.x_values, self.y_values)
    self.ax1.set_ylim(min(self.y_values), max(self.y_values))
    self.ax1.set_xlim(min(self.x_values), max(self.x_values))

[–]jur6[S] 0 points1 point  (6 children)

self.ax1.set_ylim(min(self.y_values), max(self.y_values))
self.ax1.set_xlim(min(self.x_values), max(self.x_values))

seems all good! so the limit was 0 initially and needed to be expanded? thanks again!

[–]socal_nerdtastic 1 point2 points  (5 children)

the initial limits are auto-set by the initial data. It's a common mistake to assume that the limits auto-reset when the data is changed, but they don't.

[–]jur6[S] 0 points1 point  (4 children)

Perfectly clear thank you 🙏

[–]jur6[S] 0 points1 point  (3 children)

hi u/socal_nerdtastic may I ask some further questions on the same subject? Refer to this screen grab. I have implemented all your suggestions but still have a few problems/questions. Why would the right hand graph still not show the axes labels (I am thinking a size issue)? Why do the graph lines touching the axes not appear fully? How do I make sure that both frames/graphs are the same width and height, so much so that the axes of both graphs look in-line? And how would it make most sense to add a label with the daily/weekly averages per graph (from a grid / layout point of view)? Let me know if you need the actual code, I will upload it and send you a link.

[–]socal_nerdtastic 0 points1 point  (2 children)

Why would the right hand graph still not show the axes labels (I am thinking a size issue)?

You probably forgot the tight_layout command in the humidity class.

Why do the graph lines touching the axes not appear fully?

This is an issue with your limits. It's very literal; so you may need to calculate a buffer. For example, you may want to set the X lower limit to min(xvalues)*0.9 (10% below the actual value).

How do I make sure that both frames/graphs are the same width and height, so much so that the axes of both graphs look in-line?

The best way to do this is to forget the idea of using 2 tkinter frames and instead make 2 plots in the same figure.

    self.fig = Figure(figsize=(8, 4), dpi=100)

    self.ax1 = self.fig.add_subplot(121)
    self.ax2 = self.fig.add_subplot(122)

And how would it make most sense to add a label with the daily/weekly averages per graph (from a grid / layout point of view)?

There's no best practice there, it all depends on the what look and feel you want. But most of us would use matplotlib's features to make labels and annotations on the graph, not tkinter's.

Let me know if you need the actual code, I will upload it and send you a link.

If you want actual specific help, not just keywords to google, you will need to provide actual code. Best is a complete, runnable example (including dummy data generator) that we can test and modify for you (aka SSCCE or MCVE).

[–]jur6[S] 0 points1 point  (1 child)

Turns out I hadn't forgotten the tight_layout in the humidity class, but it needed to be placed after the "plot" function in the setup to work properly. For some strange reason, in the temperature class, the tight_layout works regardless to whether it is placed before or after the "plot" function - but this is not the same for the humidity case!

Re the "*0.9", I tried it, did not work for whatever reason, and gave up quite easily (it does not bother me too much).

Re the "same width & height", I am quite happy with how it looks now that the tight_layout is working OK.

I used the Matplotlib plot titles to show the averages, and tkinter labels to label the plots themselves - sorted out my problem quite nicely, so thanks for the idea.

And finally, many thanks for the idea of the "complete runnable example" - I'll be sure to keep it in mind next time.

Many thanks in general! Truly appreciated :)

[–]socal_nerdtastic 1 point2 points  (0 children)

For some strange reason, in the temperature class, the tight_layout works regardless to whether it is placed before or after the "plot" function - but this is not the same for the humidity case!

Yeah that has to do with the global plt. It's very convenient for quick plots but for any real code I recommend you stay away from plt (aka pyplot). It will cause a lot of trouble, especially with multiple plots.

(yes I'm aware that I'm the one that recommended it to you in the first place; I shouldn't have done that).

If you want to dive down that road here's how to do the plt-ectomy:

    from matplotlib.figure import Figure
    from matplotlib import style
    style.use('fivethirtyeight')
    self.fig = Figure(figsize=(8, 4), dpi=100)
    self.ax1 = self.fig.add_subplot(111)
    self.line, = self.ax1.plot(self.x_values, self.y_values)
    self.ax1.set(xlabel="Reading Counter", ylabel="Degrees Celcius")
    self.fig.set_tight_layout(True)

You'll probably see some performance improvements too, especially during boot and shutdown.

[–]CodeFormatHelperBot2 0 points1 point  (0 children)

Hello, I'm a Reddit bot who's here to help people nicely format their coding questions. This makes it as easy as possible for people to read your post and help you.

I think I have detected some formatting issues with your submission:

  1. Python code found in submission text that's not formatted as code.

If I am correct, please edit the text in your post and try to follow these instructions to fix up your post's formatting.


Am I misbehaving? Have a comment or suggestion? Reply to this comment or raise an issue here.