برنامه‌نویسی گرافیکی در پایتون با ماژول Tkinter – درس سوم

Python GUI - Tkinter | Part 3

1 1,012

Button ها

در مبحث قبلی از مجموعه درس های GUI در پایتون Button ها را مورد بررسی قرار دادیم و فهمیدیم که Button ها تعدادی صفت دارند، مانند صفت quit که در مبحث قبلی عمل خروج از برنامه را توسط کلیک کاربر بر روی دکمه ایجاد شده انجام می داد.

برخی از صفات مهم این کنترل عبارنتد از:

text. این صفت را در Label نیز مشاهده کردیم (Label = یک متن نوشتاری یا یک عکس را می افزود). در دکمه ها نیز عمل ثبت متن دیداری دکمه ها را بر عهده دارد.

font. فونت مورد استفاده در صفت text را مشخص می کند.

width & height. به ترتیب پهنای دکمه را تنظیم می کنند.

bitmap. تصویری را در زمینه دکمه قرار می دهد.

background & foreground. یا به اختصار bg & fg در کدنویسی رنگ پیش زمینه و پس زمینه را مشخص می کند.

تا به الان یاد گرفتیم که چگونه برنامه نویسی دیداری را برای دکمه ها انجام دهیم (به آن ها رنگ بدهیم و متن آنها را عوض کنیم و موارد دیگر). این بار می خواهیم که برنامه نویسی پنهان یا back-end را برای کنترل های خود انجام بدهیم؛ برای مثال با کلیک کاربر بر روی یک دکمه، یک عمل تعیین شده ای رخ دهد.

صفت command

در مباحث قبلی از command بصورت زیر استفاده می کردیم. (command: دقیقا دربرگیرنده مفهوم لغتی آن ، «در معنی دستور») :

در خط کد بالا، یک متغیر از نوع Button با صفات text و command تعیین کردیم و صفتی که به دستور خود دادیم، صفت خروج از برنامه بود (quit) که یک عمل از قبل تعیین شده ای را انجام می داد (دقیقا همانند کتابخانه ها). حال اگر بخواهیم پیشرفته تر از قبل نرم افزار خود را شخصی سازی کنیم، باید چه کاری انجام دهیم؟

یکی از مرسوم ترین روش ها این است که یک تابع بسازیم و کدهای خود را در آن قرار داده و آن تابع را به Button خود متصل کنیم. یعنی اگر بر روی دکمه کلیک شود، آن دستوراتی که در داخل تابع نوشته شده اند اجرا می شوند.

تابع

پایتون دارای دو نوع تابع است:

توابع کتابخانه ای: این توابع دستورات مشخص شده ، یا به اختصار از پیش تعیین شده ای را انجام می دهد مانند کتابخانه و یا تابع math که برای محاسبات ریاضی در پایتون به کار می رود و بوسیله دستور import مورد استفاده قرار می گیرد.

توابع تولید شده توسط برنامه نویس: توابعی که ما بنا به نیاز خود می نویسیم و تنها در داخل همان سورس کد قابل استفاده هستند و با دستور def ساخته می شوند.

توابع مورد نیاز ما در این مبحث توابع شخصی سازی شده یا نوع دوم هستند.

برای اینکه ما از این قابلیت منحصربه فرد استفاده کنیم:

خط اول: ماژول tkinter را به همراه تمام کتابخانه های آن import کرده ایم.
خط دوم: یک فرم با نام four ساخته ایم (با استفاده از کلاس Tk).
خط سوم: یک تابع نوع دوم ساخته و نام آن را fun قرار داده ایم.
خط چهارم: در این خط که زیرمجموعه ی تابع تعریف شده است، یک Button با نام but3 ساخته ایم.
خط پنجم: یک Button داریم که نقش آن ، اجرای یک تابع است که نام تابع را در مقابل command قرار داده ایم.
خط ششم: یک دکمه ساخته ایم.
خط هفتم: فرم مورد نظر را ، مورد انتظار قرار داده ایم (برای کلیک و…).

توجه: برای اینکه به خطا برنخورید باید ابتدا تابع را تعریف کنید تا سیستم قبل از ایجاد Button ، آن را بشناسد.

اگر سورس کد بالا را اجرا کنید، با کلیک کردن بر روی دکمه اول یک Button دیگر نیز بوسیله تابع مورد نظری که به صفات دکمه اولی داده ایم ساخته می شود. کدها را برای درک بهتر در سیستم خود اجرا کنید.

شما می توانید بوسیله تابع configure ، تغییراتی را بر روی یک هدف مشخص شده انجام بدهید، برای مثال:

این کدها نیز مانند مثال بالا ، but1 را به یک تابع هدایت می کنند و تابع configure باعث تغییر متن Label می شود (در but2)

توجه: طبق بررسی زودهنگامی که خودم انجام دادم ، configure در پایتون نسخه 3 کار نمی کند.

تنظیم رنج یک فرم با geometry

با استفاده از این تابع می توانیم برای محیط گرافیکی خود یک سایزی را در نظر بگیریم (مانند 300 در 200).

یک نمونه تنظیم geometry:

طبق دستور بالا ما در فرم four رنج را مساوی با 200 در 500 قرار داده ایم.


منبع: سایت Geeks for Geeks

ترتیبی که روکسو برای یادگیری مطالب سری برنامه‌ نویسی گرافیکی در پایتون به شما توصیه می‌کند:
1 نظر
  1. zahra asadpour

    سلام وقتتون بخیر ممنون از اطلاعات خوبتون. ببخشید من یه برنامه دارم که با فایل انگلیسی کار می کنه می خوام برای فایل های فارسی تغییرش بدم فکر کنم باید encoding اش را تغییر بدم ولی نمی دونم چه جوری امکانش هست یه راهنمایی کنید ؟ممنون از لطفتون.
    برنامه را با jupyter اجرا کردم . فایل ورودی را می گیره و با deep learning اموزش می بینه تا بتونه در یک جمله کلمات بعدی را حدس بزنه . با فایل فارسی اجراش می کنم این error را میده

    UnicodeDecodeError Traceback (most recent call last)
    in
    5 from IPython import display
    6 plt.style.use(‘seaborn-white’)
    —-> 7 data = open(‘input farsi.txt’, ‘r’).read()
    8
    9 chars = list(set(data))

    c:\python36.6\lib\encodings\cp1252.py in decode(self, input, final)
    21 class IncrementalDecoder(codecs.IncrementalDecoder):
    22 def decode(self, input, final=False):
    —> 23 return codecs.charmap_decode(input,self.errors,decoding_table)[0]
    24
    25 class StreamWriter(Codec,codecs.StreamWriter):

    UnicodeDecodeError: ‘charmap’ codec can’t decode byte 0x81 in position 85: character maps to

    اینم خود برنامه

    import numpy as np
    %matplotlib inline
    import numpy as np
    import matplotlib.pyplot as plt
    from IPython import display
    plt.style.use(‘seaborn-white’)
    data = open(‘input farsi.txt’, ‘r’).read()

    chars = list(set(data))
    data_size, X_size = len(data), len(chars)
    print(“data has %d characters, %d unique” % (data_size, X_size))
    char_to_idx = {ch:i for i,ch in enumerate(chars)}
    idx_to_char = {i:ch for i,ch in enumerate(chars)}

    H_size = 100 # Size of the hidden layer
    T_steps = 25 # Number of time steps (length of the sequence) used for training
    learning_rate = 1e-1 # Learning rate
    weight_sd = 0.1 # Standard deviation of weights for initialization
    z_size = H_size + X_size # Size of concatenate(H, X) vector

    def sigmoid(x):
    return 1 / (1 + np.exp(-x))

    def dsigmoid(y):
    return y * (1 – y)

    def tanh(x):
    return np.tanh(x)

    def dtanh(y):
    return 1 – y * y

    class Param:
    def __init__(self, name, value):
    self.name = name
    self.v = value #parameter value
    self.d = np.zeros_like(value) #derivative
    self.m = np.zeros_like(value) #momentum for AdaGrad

    class Parameters:
    def __init__(self):
    self.W_f = Param(‘W_f’,
    np.random.randn(H_size, z_size) * weight_sd + 0.5)
    self.b_f = Param(‘b_f’,
    np.zeros((H_size, 1)))

    self.W_i = Param(‘W_i’,
    np.random.randn(H_size, z_size) * weight_sd + 0.5)
    self.b_i = Param(‘b_i’,
    np.zeros((H_size, 1)))

    self.W_C = Param(‘W_C’,
    np.random.randn(H_size, z_size) * weight_sd)
    self.b_C = Param(‘b_C’,
    np.zeros((H_size, 1)))

    self.W_o = Param(‘W_o’,
    np.random.randn(H_size, z_size) * weight_sd + 0.5)
    self.b_o = Param(‘b_o’,
    np.zeros((H_size, 1)))

    #For final layer to predict the next character
    self.W_v = Param(‘W_v’,
    np.random.randn(X_size, H_size) * weight_sd)
    self.b_v = Param(‘b_v’,
    np.zeros((X_size, 1)))

    def all(self):
    return [self.W_f, self.W_i, self.W_C, self.W_o, self.W_v,
    self.b_f, self.b_i, self.b_C, self.b_o, self.b_v]

    parameters = Parameters()

    def forward(x, h_prev, C_prev, p = parameters):
    assert x.shape == (X_size, 1)
    assert h_prev.shape == (H_size, 1)
    assert C_prev.shape == (H_size, 1)

    z = np.row_stack((h_prev, x))
    f = sigmoid(np.dot(p.W_f.v, z) + p.b_f.v)
    i = sigmoid(np.dot(p.W_i.v, z) + p.b_i.v)
    C_bar = tanh(np.dot(p.W_C.v, z) + p.b_C.v)

    C = f * C_prev + i * C_bar
    o = sigmoid(np.dot(p.W_o.v, z) + p.b_o.v)
    h = o * tanh(C)

    v = np.dot(p.W_v.v, h) + p.b_v.v
    y = np.exp(v) / np.sum(np.exp(v)) #softmax

    return z, f, i, C_bar, C, o, h, v, y

    def backward(target, dh_next, dC_next, C_prev,
    z, f, i, C_bar, C, o, h, v, y,
    p = parameters):

    assert z.shape == (X_size + H_size, 1)
    assert v.shape == (X_size, 1)
    assert y.shape == (X_size, 1)

    for param in [dh_next, dC_next, C_prev, f, i, C_bar, C, o, h]:
    assert param.shape == (H_size, 1)

    dv = np.copy(y)
    dv[target] -= 1

    p.W_v.d += np.dot(dv, h.T)
    p.b_v.d += dv

    dh = np.dot(p.W_v.v.T, dv)
    dh += dh_next
    do = dh * tanh(C)
    do = dsigmoid(o) * do
    p.W_o.d += np.dot(do, z.T)
    p.b_o.d += do

    dC = np.copy(dC_next)
    dC += dh * o * dtanh(tanh(C))
    dC_bar = dC * i
    dC_bar = dtanh(C_bar) * dC_bar
    p.W_C.d += np.dot(dC_bar, z.T)
    p.b_C.d += dC_bar

    di = dC * C_bar
    di = dsigmoid(i) * di
    p.W_i.d += np.dot(di, z.T)
    p.b_i.d += di

    df = dC * C_prev
    df = dsigmoid(f) * df
    p.W_f.d += np.dot(df, z.T)
    p.b_f.d += df

    dz = (np.dot(p.W_f.v.T, df)
    + np.dot(p.W_i.v.T, di)
    + np.dot(p.W_C.v.T, dC_bar)
    + np.dot(p.W_o.v.T, do))
    dh_prev = dz[:H_size, :]
    dC_prev = f * dC

    return dh_prev, dC_prev

    def clear_gradients(params = parameters):
    for p in params.all():
    p.d.fill(0)

    def clip_gradients(params = parameters):
    for p in params.all():
    np.clip(p.d, -1, 1, out=p.d)

    def forward_backward(inputs, targets, h_prev, C_prev):
    global paramters

    # To store the values for each time step
    x_s, z_s, f_s, i_s, = {}, {}, {}, {}
    C_bar_s, C_s, o_s, h_s = {}, {}, {}, {}
    v_s, y_s = {}, {}

    # Values at t – 1
    h_s[-1] = np.copy(h_prev)
    C_s[-1] = np.copy(C_prev)

    loss = 0
    # Loop through time steps
    assert len(inputs) == T_steps
    for t in range(len(inputs)):
    x_s[t] = np.zeros((X_size, 1))
    x_s[t][inputs[t]] = 1 # Input character

    (z_s[t], f_s[t], i_s[t],
    C_bar_s[t], C_s[t], o_s[t], h_s[t],
    v_s[t], y_s[t]) = \
    forward(x_s[t], h_s[t – 1], C_s[t – 1]) # Forward pass

    loss += -np.log(y_s[t][targets[t], 0]) # Loss for at t

    clear_gradients()

    dh_next = np.zeros_like(h_s[0]) #dh from the next character
    dC_next = np.zeros_like(C_s[0]) #dh from the next character

    for t in reversed(range(len(inputs))):
    # Backward pass
    dh_next, dC_next = \
    backward(target = targets[t], dh_next = dh_next,
    dC_next = dC_next, C_prev = C_s[t-1],
    z = z_s[t], f = f_s[t], i = i_s[t], C_bar = C_bar_s[t],
    C = C_s[t], o = o_s[t], h = h_s[t], v = v_s[t],
    y = y_s[t])

    clip_gradients()

    return loss, h_s[len(inputs) – 1], C_s[len(inputs) – 1]

    def sample(h_prev, C_prev, first_char_idx, sentence_length):
    x = np.zeros((X_size, 1))
    x[first_char_idx] = 1

    h = h_prev
    C = C_prev

    indexes = []

    for t in range(sentence_length):
    _, _, _, _, C, _, h, _, p = forward(x, h, C)
    idx = np.random.choice(range(X_size), p=p.ravel())
    x = np.zeros((X_size, 1))
    x[idx] = 1
    indexes.append(idx)

    return indexes

    def update_status(inputs, h_prev, C_prev):
    #initialized later
    global plot_iter, plot_loss
    global smooth_loss

    # Get predictions for 200 letters with current model

    sample_idx = sample(h_prev, C_prev, inputs[0], 200)
    txt = ”.join(idx_to_char[idx] for idx in sample_idx)

    # Clear and plot
    plt.plot(plot_iter, plot_loss)
    display.clear_output(wait=True)
    plt.show()

    #Print prediction and loss
    print(“—-\n %s \n—-” % (txt, ))
    print(“iter %d, loss %f” % (iteration, smooth_loss))

    def update_paramters(params = parameters):
    for p in params.all():
    p.m += p.d * p.d # Calculate sum of gradients
    #print(learning_rate * dparam)
    p.v += -(learning_rate * p.d / np.sqrt(p.m + 1e-8))
    import signal

    class DelayedKeyboardInterrupt(object):
    def __enter__(self):
    self.signal_received = False
    self.old_handler = signal.signal(signal.SIGINT, self.handler)

    def handler(self, sig, frame):
    self.signal_received = (sig, frame)
    print(‘SIGINT received. Delaying KeyboardInterrupt.’)

    def __exit__(self, type, value, traceback):
    signal.signal(signal.SIGINT, self.old_handler)
    if self.signal_received:
    self.old_handler(*self.signal_received)

    # Exponential average of loss
    # Initialize to a error of a random model
    smooth_loss = -np.log(1.0 / X_size) * T_steps

    iteration, pointer = 0, 0

    # For the graph
    plot_iter = np.zeros((0))
    plot_loss = np.zeros((0))

    while True:
    try:
    with DelayedKeyboardInterrupt():
    # Reset
    if pointer + T_steps >= len(data) or iteration == 0:
    g_h_prev = np.zeros((H_size, 1))
    g_C_prev = np.zeros((H_size, 1))
    pointer = 0

    inputs = ([char_to_idx[ch]
    for ch in data[pointer: pointer + T_steps]])
    targets = ([char_to_idx[ch]
    for ch in data[pointer + 1: pointer + T_steps + 1]])

    loss, g_h_prev, g_C_prev = \
    forward_backward(inputs, targets, g_h_prev, g_C_prev)
    smooth_loss = smooth_loss * 0.999 + loss * 0.001

    # Print every hundred steps
    if iteration % 100 == 0:
    update_status(inputs, g_h_prev, g_C_prev)

    update_paramters()

    plot_iter = np.append(plot_iter, [iteration])
    plot_loss = np.append(plot_loss, [loss])

    pointer += T_steps
    iteration += 1
    except KeyboardInterrupt:
    update_status(inputs, g_h_prev, g_C_prev)
    break

    from random import uniform

    def calc_numerical_gradient(param, idx, delta, inputs, target, h_prev, C_prev):
    old_val = param.v.flat[idx]

    # evaluate loss at [x + delta] and [x – delta]
    param.v.flat[idx] = old_val + delta
    loss_plus_delta, _, _ = forward_backward(inputs, targets,h_prev, C_prev)
    param.v.flat[idx] = old_val – delta
    loss_mins_delta, _, _ = forward_backward(inputs, targets,h_prev, C_prev)

    param.v.flat[idx] = old_val #reset

    grad_numerical = (loss_plus_delta – loss_mins_delta) / (2 * delta)
    # Clip numerical error because analytical gradient is clipped
    [grad_numerical] = np.clip([grad_numerical], -1, 1)

    return grad_numerical

    def gradient_check(num_checks, delta, inputs, target, h_prev, C_prev):
    global parameters

    # To calculate computed gradients
    _, _, _ = forward_backward(inputs, targets, h_prev, C_prev)

    for param in parameters.all():
    #Make a copy because this will get modified
    d_copy = np.copy(param.d)

    # Test num_checks times
    for i in range(num_checks):
    # Pick a random index
    rnd_idx = int(uniform(0, param.v.size))

    grad_numerical = calc_numerical_gradient(param,
    rnd_idx,
    delta,
    inputs,
    target,
    h_prev, C_prev)
    grad_analytical = d_copy.flat[rnd_idx]

    err_sum = abs(grad_numerical + grad_analytical) + 1e-09
    rel_error = abs(grad_analytical – grad_numerical) / err_sum

    # If relative error is greater than 1e-06
    if rel_error > 1e-06:
    print(‘%s (%e, %e) => %e’
    % (param.name, grad_numerical, grad_analytical, rel_error))

    gradient_check(10, 1e-5, inputs, targets, g_h_prev, g_C_prev)

ارسال نظر

توجه:‌ آدرس ایمیل شما منتشر نخواهد شد.

mezitli escort
mezitli escort