Home > Software engineering >  How to pass or delay getting zero values from the entry fields in tkinter?
How to pass or delay getting zero values from the entry fields in tkinter?

Time:03-03

I am writing a code in tkinter to have a meshed plot. To run the code, you can enter 5 for nx and ny entry boxes, and open a text file containing 25 numbers such as: 1 3 5 6 1 0 3 5 6 4 2 4 7 3 0 9 8 3 1 3 5 7 8 8 1, and then by pressing the Plot, the meshed plot generates. and by moving the sliders, and pressing the Plot again, the axis ranges change.

However, there is one issue, I have entered the max_val=5 for the sliders. I want to get this value from the entry fields like: max_val=data.nx.get(). but when the program runs, my entry fields are initially zero, and it raises an error. Is there a way to pass the execution of the slider widgets, after entering the values in entry boxes?

import tkinter as tk
from tkinter import *
from tkinter import filedialog
import numpy as np
import matplotlib
matplotlib.use('TkAgg')
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib import cm
from matplotlib.colors import ListedColormap
from RangeSlider.RangeSlider import RangeSliderH, RangeSliderV

global nums
class Data:
    def __init__(self):
        self.nx = tk.IntVar()
        self.ny = tk.IntVar()

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

        container = tk.Frame(self)
        container.pack()

        self.data = Data()

        self.frames = {}
        for F in (PageOne, PageTwo):
            frame = F(container, self.data)
            self.frames[F] = frame
            frame.grid(row=0, column=0, sticky="nsew")

        self.frames[PageOne].button3_P1.config(command=self.go_to_page_two)
        self.show_frame(PageOne)

    def go_to_page_two(self):
        self.show_frame(PageTwo)

    def show_frame(self, c):
        frame = self.frames[c]
        frame.tkraise()

class PageOne(tk.Frame):
    def __init__(self, parent, data):
        super().__init__(parent)
        self.data = data

        frame_1 = tk.LabelFrame(self, text="Inputs", labelanchor='n', height=400, width=280)
        frame_1.grid(row=0, column=0, padx=5, sticky='n')

        label_1 = tk.Label(frame_1, text="nx:")
        label_1.grid(row=0, column=0)

        self.entry_1 = tk.Entry(frame_1, textvariable=data.nx, width=7)
        self.entry_1.grid(row=0, column=1)

        label_2 = tk.Label(frame_1, text="ny:")
        label_2.grid(row=1, column=0)

        self.entry_2 = tk.Entry(frame_1, textvariable=data.ny, width=7)
        self.entry_2.grid(row=1, column=1, padx= 10, pady=10)
        global nums

        def opentext():
            global nums
            my_file = filedialog.askopenfilenames(initialdir="/pycharm", title="Select your file")
            for T in my_file:
                import re
                with open(T, 'r') as infile1:
                    lines = infile1.readlines()
                    B = [x for x in lines if not x.startswith('--')]
                    C = " ".join(B)
                    nums = []
                    for n in re.findall(r'\d ', C):
                        split_by_ast = n.split("*")
                        if len(split_by_ast) == 1:
                            nums  = [float(split_by_ast[0])]
                        else:
                            nums  = [float(split_by_ast[1])] * int(split_by_ast[0])

        self.button1 = tk.Button(frame_1, text="Open file", command=opentext, width=10)
        self.button1.grid(row=2, column=0, pady=10, columnspan=2)

        frame_2 = tk.LabelFrame(self, text="Convas", labelanchor='n', height=550, width=800)
        frame_2.grid(row=0, column=1, padx=5)
        frame_2.grid_propagate(0)

        def plot_init():
            global H, V
            x, y = np.mgrid[slice(0, 6, 1), slice(0, 6, 1)]
            z = np.reshape(nums, (5, 5), order='F')

            figure = Figure(figsize=(7.3, 4.8))
            ax = figure.add_subplot(111)

            col_type = cm.get_cmap('rainbow', 256)
            newcolors = col_type(np.linspace(0, 1, 1000))
            white = np.array([1, 1, 1, 1])
            newcolors[:1, :] = white
            newcmp = ListedColormap(newcolors)

            c = ax.pcolormesh(x, y, z, cmap=newcmp, edgecolor='lightgrey', linewidth=0.003)
            ax.figure.colorbar(c)

            ax.set_title('Title', fontweight="bold")
            ax.set_xlabel("X", fontsize=14)
            ax.set_ylabel("Y", fontsize=14)

            canvas = FigureCanvasTkAgg(figure, frame_2)
            canvas.get_tk_widget().place(x=80, y=0)
            figure.patch.set_facecolor('#f0f0f0')

            ax.set_xlim(rs1.getValues())
            ax.set_ylim(rs2.getValues())

            rs1.place(x=150, y=470)
            rs2.place(x=0, y=50)

        hVar1 = IntVar()  # left handle variable
        hVar2 = IntVar()  # right handle variable
        rs1 = RangeSliderH(frame_2, [hVar1, hVar2], Width=500, Height=55, padX=17, min_val=0, max_val=5, font_size=12,
                           show_value=True, digit_precision='.0f', bgColor='#f0f0f0', line_s_color='black',
                           line_color='black', bar_color_inner='black', bar_color_outer='#f0f0f0')

        vVar1 = IntVar()  # top handle variable
        vVar2 = IntVar()  # down handle variable
        rs2 = RangeSliderV(frame_2, [vVar1, vVar2], Width=81, Height=390, padY=11, min_val=0, max_val=5, font_size=12,
                           show_value=True, digit_precision='.0f', bgColor='#f0f0f0', line_s_color='black',
                           line_color='black', bar_color_inner='black', bar_color_outer='#f0f0f0')

        self.button2 = tk.Button(frame_1, text="Plot", command=plot_init, width=10)
        self.button2.grid(row=3, column=0, columnspan=2)

        self.button3_P1 = tk.Button(self, text="Continue")
        self.button3_P1.grid(row=2, column=0, columnspan=4, pady=5)


class PageTwo(tk.Frame):
    def __init__(self, parent, data):
        super().__init__(parent)
        self.data = data

app = SampleApp()
app.mainloop()

currently, I am getting this error.

Traceback (most recent call last):
  File "C:\Users\pymnb\Desktop\pycharm\Test.py", line 145, in <module>
    app = SampleApp()
  File "C:\Users\pymnb\Desktop\pycharm\Test.py", line 30, in __init__
    frame = F(container, self.data)
  File "C:\Users\pymnb\Desktop\pycharm\Test.py", line 122, in __init__
    rs1 = RangeSliderH(frame_2, [hVar1, hVar2], Width=500, Height=55, padX=17, min_val=0, max_val=data.nx.get(), font_size=12,
  File "C:\Users\pymnb\AppData\Local\Programs\Python\Python39\lib\site-packages\RangeSlider\RangeSlider.py", line 107, in __init__
    pos = (value-min_val)/(max_val-min_val)
ZeroDivisionError: division by zero

CodePudding user response:

Assuming input file, nx and ny are mandatory inputs. You should check its correct values, before passing them to plot function.

If nx and ny equals 0 is illegal, You must check if it's higher than 0 and then check if user selected input file.

You should make three changes in Your code:

  • Move Your sliders code inside plot_init method and plot them only once
  • initiate variable nums to None, to make checking if input file was selected possible
  • Check all mandatory values and display error message if conditions are not met

Additionally You might initialize data to default value different than 0:

class Data:
    def __init__(self):
        self.nx = tk.IntVar(value=1)
        self.ny = tk.IntVar(value=1)

Here is modified plot_init method with nums = None before it.

nums = None
self.rs1, self.rs2 = None, None
def plot_init():
    global H, V, nums
    x_max = data.nx.get()
    y_max = data.ny.get()

    if x_max == 0 or y_max == 0:
        tk.messagebox.showerror(title="Entry Error", message="Check Your input, nx > 0 and ny > 0!")
        return
    if nums is None:
        tk.messagebox.showerror(title="Entry Error", message="Check Your input, no file was opened!")
        return

    x, y = np.mgrid[slice(0, 6, 1), slice(0, 6, 1)]
    z = np.reshape(nums, (5, 5), order='F')

    figure = Figure(figsize=(7.3, 4.8))
    ax = figure.add_subplot(111)

    col_type = cm.get_cmap('rainbow', 256)
    newcolors = col_type(np.linspace(0, 1, 1000))
    white = np.array([1, 1, 1, 1])
    newcolors[:1, :] = white
    newcmp = ListedColormap(newcolors)

    c = ax.pcolormesh(x, y, z, cmap=newcmp, edgecolor='lightgrey', linewidth=0.003)
    ax.figure.colorbar(c)

    ax.set_title('Title', fontweight="bold")
    ax.set_xlabel("X", fontsize=14)
    ax.set_ylabel("Y", fontsize=14)

    canvas = FigureCanvasTkAgg(figure, frame_2)
    canvas.get_tk_widget().place(x=80, y=0)
    figure.patch.set_facecolor('#f0f0f0')

    if self.rs1 is None:
        self.rs1 = RangeSliderH(frame_2, [IntVar(), IntVar()], Width=500, Height=55, padX=17, min_val=0, max_val=data.nx.get(),
                           font_size=12,
                           show_value=True, digit_precision='.0f', bgColor='#f0f0f0', line_s_color='black',
                           line_color='black', bar_color_inner='black', bar_color_outer='#f0f0f0')
        self.rs1.place(x=150, y=470)

    if self.rs2 is None:
        self.rs2 = RangeSliderV(frame_2, [IntVar(), IntVar()], Width=81, Height=390, padY=11, min_val=0, max_val=data.ny.get(),
                           font_size=12,
                           show_value=True, digit_precision='.0f', bgColor='#f0f0f0', line_s_color='black',
                           line_color='black', bar_color_inner='black', bar_color_outer='#f0f0f0')
        self.rs2.place(x=0, y=50)

    ax.set_xlim(self.rs1.getValues())
    ax.set_ylim(self.rs2.getValues())
  • Related