Main Page

Action Page

Above UI we are going to create by Tkinter for encoding and decoding message in our Steganography system desktop application. For that first we create a window and configure its title, size and color. Here we are creating a window (main) at Top Level so we can add this window at the top of any other window.

    

    from tkinter import *
    from tkinter.filedialog import *
    from tkinter import font as tkFont
    from Util.util import Util
    from actions.action_class import ActionClass
    from custom_design.roundBackgroundFrame import RoundBackgroundFrame
    from custom_design.roundedbutton import RoundedButton
    from custom_design.roundedbuttonwithimage import AddActionFrame

    # main program
    main = Tk() #Create window at top level 
    main.title('Steganography')  #Give title to window 
    main.configure(bg="#585858") #Set Background Color 
    main.resizable(width=0, height=0)

    # Set screen size 
    win_width = 1280  
    win_height = int(1280 * 56.25 / 100) # print(1280 * 56.25 / 100)

    main.geometry(str(win_width) + "x" + str(win_height))
    Util.center(main)
    main.attributes('-alpha', 1.0)

    

    

Now Before anything, Lets define few Funtions in util class and Constants in appConstant class in a folder "Util".




##### File name: util.py

import platform
from Util.app_constant import AppConstant


class Util:

    @staticmethod
    def center(win):
        """
        centers a tkinter window
        :param win: the main window or Toplevel window to center
        """
        win.update_idletasks()
        width = win.winfo_width()
        frm_width = win.winfo_rootx() - win.winfo_x()
        win_width = width + 2 * frm_width
        height = win.winfo_height()
        titlebar_height = win.winfo_rooty() - win.winfo_y()
        win_height = height + titlebar_height + frm_width
        x = win.winfo_screenwidth() // 2 - win_width // 2
        y = win.winfo_screenheight() // 2 - win_height // 2
        win.geometry('{}x{}+{}+{}'.format(width, height, x, y))
        win.deiconify()

    @staticmethod
    def set_font_size(screen_width, screen_height, win_width, win_height):
        # Get percentage of screen size from Base size
        percentage_width = screen_width / (win_width / 100)
        percentage_height = screen_height / (win_height / 100)

        # Make a scaling factor, this is bases on average percentage from
        # width and height.
        scale_factor = ((percentage_width + percentage_height) / 2) / 100

        # Set the fontsize based on scale_factor,
        # if the fontsize is less than minimum_size
        # it is set to the minimum size


        AppConstant.FONT_SIZE = int(14 * scale_factor)
        print(AppConstant.FONT_SIZE)
        minimum_size = 8
        if AppConstant.FONT_SIZE < minimum_size:
            AppConstant.FONT_SIZE = minimum_size

        if platform.system() == "Linux":
            AppConstant.FONT_SIZE = 14



##### File name: app_constant.py

    class AppConstant:
        FONT_SIZE = 16









After creation of window,Let's Make a folder "custom_design" and create class "RoundBackgroundFrame" to add a canvas background in the main file.



from tkinter import *
import tkinter as tk
from PIL import Image, ImageTk


class RoundBackgroundFrame(tk.Canvas):

    def __init__(self, parent, width, height, padding, cornerradius, color, bg):
        tk.Canvas.__init__(self, parent, borderwidth=0, relief="flat", highlightthickness=0, bg=bg)
        self.width = width
        self.height = height
        self.padding = padding
        self.cornerradius = cornerradius
        self.color = color

        original = Image.open("images/corner.png")
        resized = original.resize((int(40), int(40)), Image.ANTIALIAS)
        self.image_r_t = ImageTk.PhotoImage(resized)

        original = original.rotate(90, expand=0)
        resized = original.resize((int(40), int(40)), Image.ANTIALIAS)
        self.image_l_t = ImageTk.PhotoImage(resized)

        original = original.rotate(90, expand=0)
        resized = original.resize((int(40), int(40)), Image.ANTIALIAS)
        self.image_l_b = ImageTk.PhotoImage(resized)

        original = original.rotate(90, expand=0)
        resized = original.resize((int(40), int(40)), Image.ANTIALIAS)
        self.image_r_b = ImageTk.PhotoImage(resized)

        self.shape(width, height, padding, cornerradius, color)
        (x0, y0, x1, y1) = self.bbox("all")
        width = (x1 - x0)
        height = (y1 - y0)
        self.configure(width=width, height=height)

    def shape(self, width, height, padding, cornerradius, color):
        self.create_polygon((padding, height - cornerradius - padding, padding, cornerradius + padding,
                             padding + cornerradius, padding, width - padding - cornerradius, padding,
                             width - padding, cornerradius + padding, width - padding,
                             height - cornerradius - padding, width - padding - cornerradius, height - padding,
                             padding + cornerradius, height - padding), fill=color, outline=color)

        self.create_image(width - self.image_r_t.width(), 0, image=self.image_r_t, anchor=NW)
        self.create_image(0, 0, image=self.image_l_t, anchor=NW)
        self.create_image(0, height - self.image_l_b.width(), image=self.image_l_b, anchor=NW)
        self.create_image(width - self.image_r_b.width(), height - self.image_r_b.width(), image=self.image_r_b,
                          anchor=NW





After creating "class RoundBackgroundFrame(tk.Canvas):", we will add a canvas background by importing it from "custom_design" folder

    
    fontl = tkFont.Font(family='Algerian', size=20)
    font_size=AppConstant.FONT_SIZE

    background_frame_width = win_width*90/100
    background_frame_height = win_height*90/100
    cornerradius = 40
    padding = 0
    color = "#FFFFFF"

    bg_canvas = RoundBackgroundFrame(main, background_frame_width, background_frame_height, padding, cornerradius, color, "#585858")
    bg_canvas.place(width=background_frame_width, height=background_frame_height, x=win_width / 2 - background_frame_width / 2, y=win_height / 2 - background_frame_height / 2)
  
    




Now Lets, add class "class AddActionFrame(tk.Canvas):" (roundedbuttonwithimage.py) and "class RoundedButton(tk.Canvas):" (roundedbutton.py) in your "custom_design" folder . and import it into the main class



###  File name: roundedbuttonwithimage.py -->

from tkinter import *
import tkinter as tk
from PIL import Image, ImageTk


class AddActionFrame(tk.Canvas):

    def __init__(self, parent, width, height, bg, text, font, icon_path, command=None):
        tk.Canvas.__init__(self, parent, borderwidth=0, relief="flat", highlightthickness=0, bg=bg)
        self.command = command
        self.width = width
        self.height = height
        self.text = text
        self.font = font

        original = Image.open(icon_path)
        resized = original.resize((int(height * 50 / 100), int(height * 50 / 100)), Image.ANTIALIAS)
        self.image = ImageTk.PhotoImage(resized)

        original = Image.open("images/desk_bg_1.png")
        resized = original.resize((int(width), int(height)), Image.ANTIALIAS)
        self.imagebg = ImageTk.PhotoImage(resized)


        self.shape(width, height)
        (x0, y0, x1, y1) = self.bbox("all")
        width = (x1 - x0)
        height = (y1 - y0)
        self.configure(width=width, height=height)
        self.bind("", self._on_press)
        self.bind("", self._on_release)

    def shape(self, width, height):
        self.create_image(0, 0, image=self.imagebg, anchor=NW)
        self.create_image(width/2-self.image.width() / 2, height / 7, image=self.image, anchor=NW)
        self.create_text(width / 2, height - height / 5, anchor=CENTER, font=self.font, text=self.text, fill="#FFFFFF")

    def shape_press(self, width, height):
        self.create_image(0, 0, image=self.imagebg, anchor=NW)
        self.create_image(width / 2 - self.image.width() / 2, height / 7, image=self.image, anchor=NW)
        self.create_text(width / 2, height - height / 5, anchor=CENTER, font=self.font, text=self.text, fill="#000000")

    def _on_press(self, event):
        self.configure(relief="sunken")
        self.delete("all")
        # self.update()
        self.shape_press(self.width, self.height)

    def _on_release(self, event):
        self.configure(relief="raised")
        self.delete("all")
        self.shape(self.width, self.height )
        if self.command is not None:
            self.command()






#### //File name: roundedbutton.py  -->

from tkinter import *
import tkinter as tk
from PIL import Image, ImageTk


class RoundedButton(tk.Canvas):

    def __init__(self, parent, width, height, bg, icon_path, text, font, command=None):
        tk.Canvas.__init__(self, parent, borderwidth=0, relief="flat", highlightthickness=0, bg=bg)
        self.command = command
        self.width = width
        self.height = height
        self.text = text
        self.font = font

        original = Image.open(icon_path)
        resized = original.resize((int(width), int(height)), Image.ANTIALIAS)
        self.image = ImageTk.PhotoImage(resized)

        self.shape(width, height)
        (x0, y0, x1, y1) = self.bbox("all")
        width = (x1 - x0)
        height = (y1 - y0)
        self.configure(width=width, height=height)
        self.bind("", self._on_press)
        self.bind("", self._on_release)

    def shape(self, width, height):
        self.create_image(0, 0, image=self.image, anchor=NW)
        self.create_text(width / 2, height / 2, anchor=CENTER, font=self.font, text=self.text, fill="#FFFFFF")

    def shape_press(self, width, height):
        self.create_image(0, 0, image=self.image, anchor=NW)
        self.create_text(width / 2, height / 2, anchor=CENTER, font=self.font, text=self.text, fill="#000000")

    def _on_press(self, event):
        self.configure(relief="sunken")
        self.delete("all")
        # self.update()
        self.shape_press(self.width, self.height)

    def _on_release(self, event):
        self.configure(relief="raised")
        self.delete("all")
        self.shape(self.width, self.height)
        if self.command is not None:
            self.command()





Once your window is created with custom background, we will create a frame with some reduced dimensions in the main file.

    

    self.width = self.width * 98 / 100 
    self.height = self.height * 96 / 100 
    self.base_frame = Frame(root, width=self.width, height=self.height, bg=self.color) 
    bg_canvas.create_window(self.width / 100, self.height * 2 / 100, anchor=NW, window=self.base_frame) 



    #### Functions

    def getAction(root,action):
    root.withdraw()
    ActionClass(root).get_action_mode(action)

    def add_heading_label(base_frame, color, font_size, height, width):
    label_heading = Label(base_frame, text="Steganography", anchor=CENTER, bg=color,relief="flat",
                          font=("Lucida Grande", font_size + 6) )
    label_heading.place(width=width * 90 / 100, height=height * 7 / 100, x=width * 5 / 100, y=height * 1 / 100)

    label_dashboard = Label(base_frame, text="Choose Your Action", anchor=CENTER, bg=color,
                            font=("Lucida Grande", font_size - 2))
    label_dashboard.place(width=width * 90 / 100, height=height * 4 / 100, x=width * 5 / 100, y=height * 20 / 100)

    def add_line_border(base_frame, color, height, width):
    line_canvas = Canvas(base_frame, bg=color, borderwidth=0, relief="flat", highlightthickness=0)
    line_canvas.place(width=width - 4, height=5, x=2, y=height * 10 / 100)
    line_canvas.create_line(0, 0, width, 0, fill="#787878")

    line_canvas2 = Canvas(base_frame, bg=color, borderwidth=0, relief="flat", highlightthickness=0)
    line_canvas2.place(width=width - 4, height=5, x=2, y=height * 90 / 100)
    line_canvas2.create_line(0, 0, width, 0, fill="#787878")

    def getActionButtons(main):
    posX=lfbw*3/4
    button_encode = AddActionFrame(labelframe, posX, posX, color, "Encode",
                                     ("Lucida Grande", font_size - 4), "images/encode_icon.png", command=lambda: getAction(main,"encode"))
    button_decode = AddActionFrame(labelframe, posX, posX, color, "Decode",
                                        ("Lucida Grande", font_size - 4), "images/decode_icon.png", command=lambda: getAction(main,"decode"))

    button_encode.grid(row=0, column=2, padx=lfbw * 26.7/ 100, pady=lfbw*13.5/100)
    button_decode.grid(row=0, column=3, padx=lfbw * 15 / 100)


    def exit():
    main.destroy()

    global font_size



    ### Now Create your frames using the above Functions

    width = background_frame_width * 98 / 100
    height = background_frame_height * 96 / 100

    base_frame = Frame(main, width=width, height=height, bg=color)
    bg_canvas.create_window(width / 100, height * 2 / 100, anchor=NW, window=base_frame)

    add_heading_label(base_frame, color, 18, height, width)
    add_line_border(base_frame,color,height,width)


    lfw = width * 35 / 100
    lfbw = lfw * 39 / 100

    labelframe = LabelFrame(base_frame, pady=lfw * 2 / 100, padx=lfw * 2 / 100, bg=color)
    labelframe.place(width=lfw, height=lfbw + lfw * 6 / 100, x=width/2-lfw/2, y=height * 35 / 100)

    getActionButtons(main)

    closebutton = RoundedButton(base_frame, 200, 200 / 1.60, "#ffffff", "images/red button.png", "EXIT", font=("Lucida Grande", 16),command= exit)
    closebutton.place(x=width/2-100, y=height*67/100)

        



Now, There is a method known by the name mainloop() is used when your application is ready to run. mainloop() is an infinite loop used to run the application, wait for an event to occur and process the event as long as the window is not closed. This should be written in the last of main file.

    

    main.mainloop()


                       

Programmer Mirta is for learning and training. Projects might be simple to improve learning. Projects are constantly reviewed to avoid errors, but we cannot assure full correctness of all content. While using Programmer Mitra, you agree to have read and accepted our terms of use, cookie and privacy policy.

Copyright 2021 by Programmer Mitra. All Rights Reserved.