Одиночное окно Tkinter, которое перемещается через кадры, выводя каждый кадр на передний план. Один кадр должен быть разделен на два субкадра - PullRequest
0 голосов
/ 22 февраля 2020

Потребность в двух разных графометрах c возникает из-за того, что я хочу отобразить сложные GUI с текстом, полями ввода, изображениями, кнопками, а также с анимированным графиком matplotlib на FigureCanvasTkAgg с NavigationToolbar2Tk. NavigationToolbar2Tk не работает, когда используется любой геометрический плоттер c, кроме pack (). В течение недели я пробовал несколько разных способов поместить NavigationToolbar2Tk в его собственный фрейм, но в примерах существует только один фрейм. Я пришел к выводу, что в идеале нужно разделить мой кадр ~ PageOne ~ на два подкадра или создать два кадра, составляющих первую страницу.

У меня есть несколько фреймов, как показано в моем коде ниже, и мои знания python являются элементарными, поэтому я не обладаю воображением или не знаю, как обойти эту проблему. Я выпотрошил свой код, чтобы показать проблему кратко и включил мой импорт.

import matplotlib
matplotlib.use("TkAgg")

from   matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
from   matplotlib.figure import Figure
from   matplotlib.pylab  import *
from   matplotlib        import style
import matplotlib.animation as animation
import matplotlib.pyplot    as plt
import matplotlib.dates     as dates
import matplotlib.ticker    as mticker

import tkinter as tk
from tkinter import ttk
from tkinter import *

from PIL import Image, ImageTk
from mpl_toolkits.axes_grid1 import host_subplot
from gpiozero import CPUTemperature

import time
import datetime as dt
import pandas   as pd        
import numpy    as np


#************************************************************************#
# Format Graph_1 [ax1] onto fig1 at subplot [ row = 1, col = 1, index = 1 ]

# Set Figure Text 
font = {'size' : 9}
matplotlib.rc('font', **font)

# Setup Figure
fig1 = Figure()

# Define Axis 1 for Vin and Vout 
ax1 = fig1.add_subplot(1, 1, 1)
#subplots_adjust(left=0.05, bottom=0.10, right=0.55, top=0.8, wspace=0.2)
ax1.minorticks_on()
ax1.grid(b=True, which='major', color='k', linestyle='-')
ax1.grid(b=True, which='minor', color='k', linestyle=':')
ax1.set_title("PI3740 Paramaters", fontsize = 12)
ax1.set_xlabel("Relative Time (s)", fontsize = 10)
ax1.set_ylabel("Voltage (V)", fontsize =10)

# Define Axis 2 for Iout Which is tied to Axis 1's X-Axis
ax2 = ax1.twinx() 
ax2.set_ylabel("Output Current (A)")

# Parameters
x_len = 500                         # Resolution [Number of Points in Window]
x_max = 2                          # X-Axis Range [ (Step)ms Samp^-1 * (x_len)Samp = X_Range]  
y_range = [0, 50]                   # Range of possible Y values to display

# Create figure for plotting
steps = (x_max/x_len)
stepms = steps * 1000
xs = np.arange(0, x_max, steps)     # xs is a list from 0 to 10 in steps of 0.01 [A list refers to a 1D Array]
ys1 = [0] * x_len                   # ys is a list indexed from ys[0] to ys[999] all containing 0 # Vin
ys2 = [0] * x_len                   # ys is a list indexed from ys[0] to ys[999] all containing 0 # Vout
ys3 = [0] * x_len                   # ys is a list indexed from ys[0] to ys[999] all containing 0 # Iout
ax1.set_ylim(y_range)               # Y-Axis Voltage Range Set
ax2.set_ylim(0, 10)                 # Y-Axis Current Range Set
ax1.set_xlim(0, x_max)              # X-Axis Shared Relative Time Range Set

# Create a blank line. We will update the line in animate
line1, = ax1.plot(xs, ys1, 'b-', label = "Vin")
line2, = ax1.plot(xs, ys2, 'g-', label = "Vout")
line3, = ax2.plot(xs, ys3, 'r-', label = "Iout")

# Create a Legend 
ax1.legend([line1, line2],[line1.get_label(), line2.get_label()])
ax1.legend(bbox_to_anchor = (0.,0.99,1.,.102), loc = 3, ncol = 2, borderaxespad = 0., frameon = False)
ax2.legend([line3],[line3.get_label()])
ax2.legend(bbox_to_anchor = (1.00,0.99), loc = 'lower right', borderaxespad = 0., frameon = False)

#************************************************************************#
#**********************Animation Function********************************#

# This function is called periodically from FuncAnimation
def updateData(self):

    # Drop down menu event flags
    global ChartLoad

    # Graph variables
    global xs
    global ys1
    global ys2
    global ys3

    if ChartLoad == True:
        # Read temperature (Celsius) from TMP102
        temp_c = cpu.temperature
        temp_c1 = temp_c + 5.0
        temp_c2 = temp_c - 35.0
        # Add y to list
        ys1.append(temp_c)
        ys2.append(temp_c1)
        ys3.append(temp_c2)

        # Limit y list to set number of items
        ys1 = ys1[-x_len:]
        ys2 = ys2[-x_len:]
        ys3 = ys3[-x_len:] 

        # Update line with new Y values
        line1.set_ydata(ys1)
        line2.set_ydata(ys2)
        line3.set_ydata(ys3)

    return line1, line2, line3,

#************************************************************************#
#*******************Tkinter Window Initalization*************************#

class MyApp(tk.Tk):                                               
    def __init__(self, *args, **kwargs):                       

        tk.Tk.__init__(self, *args, **kwargs)                          
        tk.Tk.wm_title(self,"EMEA Vicor Charging Application ")
        img=tk.PhotoImage(file='/home/pi/Pictures/Vicor_Icon1.png')
        self.tk.call('wm','iconphoto',self._w,img)

        container = tk.Frame(self)                                                

        container.pack(side="top", fill="both", expand = True)
        container.grid_rowconfigure(0, weight=1)               
        container.grid_columnconfigure(0, weight=1)

    #*********************************************************
    #******Function Required to Display Seperate Pages********
        self.frames = {}
        for F in (StartPage, HomePage, PageOne):                  
            frame = F(container, self)
            self.frames[F] = frame
            frame.grid(row=0, column=0, sticky="nsew")
        self.show_frame(StartPage)

    def show_frame(self, cont):

        frame = self.frames[cont]
        frame.tkraise()

    #*********************************************************
    #*********************************************************

#Start Page - Agreement
class StartPage(tk.Frame):                                            

    def __init__(self, parent, controller):                        
        tk.Frame.__init__(self, parent)

#Page One - Primary Terminal 
class PageOne(tk.Frame):                                            

    def __init__(self, parent, controller):                        
        tk.Frame.__init__(self, parent)
        tk.Frame.__init__(self, parent, bg = "white")

        # Two Frames Need to be Established on Page One (Which is a “Higher Order Frame”)

        my_window = Tk()
        frame_name = Frame(my_window)
        frame_addr = Frame(my_window)

        label_f = Label(frame_name, text = "Check")
        label_f.grid(row = 0, column = 0)

        label_g = Label(frame_addr, text = "Correct")
        label_g.grid(row = 0, column = 0)

        frame_name.grid(row = 0, column = 0)
        frame_addr.grid(row = 0, column = 1)

        #my_window.mainloop()



app = MyApp()
app.geometry("1010x700")
ani = animation.FuncAnimation(fig1, updateData, blit = True, interval = stepms)
app.mainloop()

Страница первая будет содержать мой холст для графика и панели инструментов. однако, чтобы упростить задачу до ее фундаментального значения, нужно получить два кадра, составляющих кадр «высшего порядка» PageOne, причем каждый подкадр содержит метку. Когда я запускаю код, открывается другое окно с двумя отображаемыми метками. Это больше прогресса, чем от других решений, которые я не могу реализовать / не понимаю, создавая сообщения об ошибках, на которые я не могу ответить. Я самоучка в python, и я следую инструкциям от сообщества. Мне просто нужна помощь в реализации решения. Если я много потрошил свой код, я могу предоставить более полный фрагмент кода. Но суть проблемы заключается в том, что при отображении одного из нескольких кадров в окне Tkinter, которые по запросу перемещаются на передний план, как разделить один из этих кадров «высокого порядка» на два кадра, чтобы получить две разные геометрии c плоттеры, которые будут использоваться для структурирования каждого из них.

Используемые ресурсы: https://www.youtube.com/watch?v=Mxk4cMBaH3g&list=PL6lxxT7IdTxGoHfouzEK-dFcwr_QClME_&index=37&t=0s [Самая последняя попытка - попытка упростить проблему]

как сделать два разделенных экрана (холст) внутри окна python tkinter

http://www.openbookproject.net/courses/python4fun/tkphone1.html

Ошибка панели навигации matplotlib У объекта 'FigureCanvasTkAgg' нет атрибута 'manager' в tkinter

Отображение панели инструментов Matplotlib Navigation в Tkinter через сетку [Решить ту же проблему - один мастер-кадр разделен на два субкадра] [Эта ссылка, вероятно, содержит ответ, и если это так, извиняюсь за повторение вопроса, уже задаваемого по переполнению стека)

РЕДАКТИРОВАТЬ. Чтобы далее расширить для ясности, возьмите код ниже:

import tkinter as tk                # python 3
from tkinter import font  as tkfont # python 3
#import Tkinter as tk     # python 2
#import tkFont as tkfont  # python 2

class SampleApp(tk.Tk):

    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)

        self.title_font = tkfont.Font(family='Helvetica', size=18, weight="bold", slant="italic")

        # the container is where we'll stack a bunch of frames
        # on top of each other, then the one we want visible
        # will be raised above the others
        container = tk.Frame(self)
        container.pack(side="top", fill="both", expand=True)
        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)

        self.frames = {}
        for F in (StartPage, PageOne, PageTwo):
            page_name = F.__name__
            frame = F(parent=container, controller=self)
            self.frames[page_name] = frame

            # put all of the pages in the same location;
            # the one on the top of the stacking order
            # will be the one that is visible.
            frame.grid(row=0, column=0, sticky="nsew")

        self.show_frame("StartPage")

    def show_frame(self, page_name):
        '''Show a frame for the given page name'''
        frame = self.frames[page_name]
        frame.tkraise()


class StartPage(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.controller = controller
        label = tk.Label(self, text="This is the start page", font=controller.title_font)
        label.pack(side="top", fill="x", pady=10)

        button1 = tk.Button(self, text="Go to Page One",
                            command=lambda: controller.show_frame("PageOne"))
        button2 = tk.Button(self, text="Go to Page Two",
                            command=lambda: controller.show_frame("PageTwo"))
        button1.pack()
        button2.pack()


class PageOne(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.controller = controller
        label = tk.Label(self, text="This is page 1", font=controller.title_font)
        label.pack(side="top", fill="x", pady=10)
        button = tk.Button(self, text="Go to the start page",
                           command=lambda: controller.show_frame("StartPage"))
        button.pack()


class PageTwo(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.controller = controller
        label = tk.Label(self, text="This is page 2", font=controller.title_font)
        label.pack(side="top", fill="x", pady=10)
        button = tk.Button(self, text="Go to the start page",
                           command=lambda: controller.show_frame("StartPage"))
        button.pack()


if __name__ == "__main__":
    app = SampleApp()
    app.mainloop()

как мне заставить PageTwo составить два разных фрейма, чтобы я мог использовать два разных графометра c плоттеров (pack () и grid ()) ,

...