Example #1
0
class DoubleSlider(ttk.Frame):
    def __init__(self, parent, controller):
        ttk.Frame.__init__(self, parent)
        self.controller = controller

        # style
        style = ttk.Style()
        style.configure('Double.Horizontal.TScale', sliderlenght=30)

        self.top_slider = TickScale(self,
                                    style='Double.Horizontal.TScale',
                                    tickinterval=1,
                                    resolution=1,
                                    from_=1,
                                    to=12,
                                    length=400,
                                    labelpos='s',
                                    command=self.update_value)
        self.top_slider.grid(row=0, column=0, sticky=S)
        self.top_slider.set(12)
        self.top_slider.bind("<ButtonRelease-1>", self.update_value)

        self.bot_slider = TickScale(self,
                                    style='Double.Horizontal.TScale',
                                    tickinterval=1,
                                    resolution=1,
                                    from_=1,
                                    to=12,
                                    length=400,
                                    labelpos='n',
                                    command=self.update_value)
        self.bot_slider.grid(row=1, column=0, sticky=N)

    def reset(self):
        self.top_slider.set(12)
        self.bot_slider.set(1)
        # self.update_value(None)

    def update_value(self, event):
        try:
            entries_len = len(self.master.entries) // 14
            total = [0] * (entries_len)

            if self.top_slider.get() <= self.bot_slider.get():
                smaller_slider = int(self.top_slider.get())
                bigger_slider = int(self.bot_slider.get())
            else:
                smaller_slider = int(self.bot_slider.get())
                bigger_slider = int(self.top_slider.get())

            for i in range(1, 13):
                self.master.labels[i].configure(foreground="black")

            for i in range(smaller_slider, bigger_slider + 2):

                if i < bigger_slider + 1 and i >= smaller_slider:
                    self.master.labels[i].configure(foreground="#0099ff")

                if i > smaller_slider:
                    for j in range(1, entries_len + 1):
                        entry = self.master.entries[i, j].get()
                        if ":" in entry:
                            delta = int(entry.split(":")[0]) * 3600 + int(
                                entry.split(":")[1]) * 60
                            total[j - 1] += delta
                        else:
                            total[j - 1] += int(entry) * 3600

            for i in range(1, entries_len + 1):
                self.master.entries[14, i].delete(0, 10)
                self.master.entries[14, i].insert(
                    0,
                    str(int((total[i - 1] // 3600))) + ":" +
                    str(int(total[i - 1] % 3600) // 60).zfill(2))
        except AttributeError:
            pass

    # returns the range of sliders e.g (2,7)
    def get_range(self):
        less = min(int(self.top_slider.get()), int(self.bot_slider.get()))
        more = max(int(self.top_slider.get()), int(self.bot_slider.get()))
        return ((less, more))
Example #2
0
    def test_tickscale_methods(self):
        scale = TickScale(self.window, from_=0, to=10, orient='horizontal')
        scale.pack()
        self.window.update()
        self.assertEqual(scale.cget('digits'), -1)
        self.assertEqual(scale['tickinterval'], 0)
        self.assertEqual(scale['resolution'], 0)
        self.assertTrue(scale.cget('showvalue'))
        self.assertEqual(scale['from'], 0)
        self.assertEqual(scale.cget('to'), 10)
        keys = [
            'command', 'variable', 'orient', 'from', 'to', 'value', 'length',
            'takefocus', 'cursor', 'style', 'class', 'tickinterval',
            'showvalue', 'digits'
        ]
        self.assertTrue(all(key in scale.keys() for key in keys))

        scale.config(from_=-1)
        self.window.update()
        self.assertEqual(scale['from'], -1)

        scale.configure({'to': 20, 'tickinterval': 5, 'digits': 1})
        self.window.update()
        self.assertEqual(scale['to'], 20)
        self.assertEqual(scale['digits'], 1)
        self.assertEqual(scale['tickinterval'], 5)

        scale.configure(tickinterval=0.01, resolution=0.05)
        self.window.update()
        self.assertEqual(scale['digits'], 2)
        self.assertEqual(scale['resolution'], 0.05)
        self.assertEqual(scale['tickinterval'], 0.05)

        scale.set(1.1036247)
        self.assertEqual(scale.get(), 1.10)

        scale['labelpos'] = 's'
        self.window.update()
        self.assertEqual(scale['labelpos'], 's')

        scale['labelpos'] = 'e'
        self.window.update()
        self.assertEqual(scale['labelpos'], 'e')

        scale['labelpos'] = 'w'
        self.window.update()
        self.assertEqual(scale['labelpos'], 'w')

        scale['tickpos'] = 'n'
        self.window.update()
        self.assertEqual(scale['tickpos'], 'n')

        scale['orient'] = 'vertical'
        self.window.update()

        scale['tickpos'] = 'e'
        self.window.update()
        self.assertEqual(scale['tickpos'], 'e')

        with self.assertRaises(ValueError):
            scale.configure(orient='vertical', tickpos='n')

        with self.assertRaises(ValueError):
            scale.configure(orient='horizontal', tickpos='e')

        with self.assertRaises(ValueError):
            TickScale(self.window, labelpos='ne')

        scale.configure(style='my.Vertical.TScale')
        self.window.update()
        scale.style.configure('my.Vertical.TScale',
                              font='TkDefaultFont 20 italic',
                              sliderlength=50)

        scale.x = 0

        def cmd(value):
            scale.x = 2 * float(value)

        scale.configure(command=cmd)
        self.window.update()
        scale.configure(digits=1)
        scale.set(10)
        self.window.update()
        self.assertEqual(scale.x, 20)
        self.assertEqual(scale.label.cget('text'), '10.0')

        scale['showvalue'] = False
        self.window.update()
        self.assertEqual(scale.label.place_info(), {})

        scale['orient'] = 'horizontal'
        self.window.update()
        scale['style'] = ''
        scale['showvalue'] = True
        self.window.update()
        scale['length'] = 200
        scale['digits'] = 3
        scale.style.configure('Horizontal.TScale',
                              font='TkDefaultFont 20 italic',
                              sliderlength=10)
        self.window.update()
        scale.set(0)
        self.window.update()
        scale.set(20)
        self.window.update()
Example #3
0
class App(tk.Tk):
    '''
    Main class, it contains all functions and objects connected to UI.
    '''
    def __init__(self):
        '''
        Create the structure of the UI
        '''
        super().__init__()
        self.data = []  # List that contain the data to sort
        self.select_alg_menu = tk.StringVar()
        self.stop = False
        self.rectangles = []
        self.colors = []
        self.title("Array sorter")
        self.maxsize(MAX_WIDTH, MAX_HEIGHT)
        self.iconphoto(True, tk.PhotoImage(file='sorter_icon.png'))

        # Setup of custom style
        self.style = ttk.Style(self)
        self.tk.call('source', 'Azure-ttk-theme/azure-dark.tcl')
        self.style.theme_use('azure-dark')

        # top_menu contains all the interactive component (button, sliders...)
        self.top_menu = tk.Frame(self,
                                 width=MAX_WIDTH,
                                 height=MAX_HEIGHT / 4,
                                 bg=grey)

        self.top_menu.grid(row=0, column=0, pady=4)

        # drawArea is the Canvas where rectangles'll be drawn
        self.drawArea = tk.Canvas(self,
                                  width=MAX_WIDTH,
                                  height=MAX_HEIGHT,
                                  bg=lightBlue)
        self.drawArea.grid(row=1, column=0)

        # first ROW
        tk.Label(self.top_menu, text="Algorithm: ", bg=grey).grid(row=0,
                                                                  column=0,
                                                                  padx=5,
                                                                  pady=5,
                                                                  sticky='')
        self.algorithm_menu = ttk.Combobox(
            self.top_menu,
            textvariable=self.select_alg_menu,
            values=['SELECTION', 'BUBBLE', 'INSERTION', 'QUICKSORT'])
        self.algorithm_menu.grid(row=0, column=1, padx=15, pady=5)
        self.algorithm_menu.current([0])

        tk.Label(self.top_menu, text="Speed [s]: ", bg=grey).grid(row=0,
                                                                  column=2,
                                                                  padx=15,
                                                                  pady=5,
                                                                  sticky='SW')
        self.speedScale = TickScale(self.top_menu,
                                    from_=0.005,
                                    to=2,
                                    digits=3,
                                    orient='horizontal')
        self.speedScale.grid(row=0,
                             column=3,
                             columnspan=3,
                             padx=15,
                             pady=0,
                             sticky='W')

        # second ROW
        tk.Label(self.top_menu, text="Size: ", bg=grey).grid(row=1,
                                                             column=0,
                                                             padx=15,
                                                             pady=3,
                                                             sticky='SW')
        self.sizeEntry = TickScale(self.top_menu,
                                   from_=1,
                                   to=200,
                                   digits=0,
                                   orient='horizontal')
        self.sizeEntry.grid(row=1, column=1, padx=15, pady=0, sticky='W')

        tk.Label(self.top_menu, text="Min value: ", bg=grey).grid(row=1,
                                                                  column=2,
                                                                  padx=15,
                                                                  pady=3,
                                                                  sticky='SW')
        self.minEntry = TickScale(self.top_menu,
                                  from_=1,
                                  to=200,
                                  digits=0,
                                  orient='horizontal')
        self.minEntry.grid(row=1, column=3, padx=15, pady=3, sticky='W')

        tk.Label(self.top_menu, text="Max Value: ", bg=grey).grid(row=1,
                                                                  column=4,
                                                                  padx=15,
                                                                  pady=3,
                                                                  sticky='SW')
        self.maxEntry = TickScale(self.top_menu,
                                  from_=1,
                                  to=200,
                                  digits=0,
                                  orient='horizontal')
        self.maxEntry.grid(row=1, column=5, padx=15, pady=3, sticky='W')

        ttk.Button(self.top_menu,
                   text="Generate",
                   command=lambda: Generate(self),
                   style='AccentButton').grid(row=1, column=6, padx=15)
        ttk.Button(self.top_menu,
                   text="Start",
                   command=lambda: Thread(target=Start, args=(self, )).start(),
                   style='AccentButton').grid(row=0, column=6, padx=15)
        ttk.Button(self.top_menu,
                   text="Stop",
                   command=lambda: self.Stop(),
                   style='AccentButton').grid(row=0, column=7, padx=15)

    def Draw(self, color=list, generate_flag=False):
        '''
        Creation of rectangles, it takes a color[] list
        because when sorting we need to know which are the
        rectangles to draw
        '''
        if self.stop:
            color = [rectBlue for x in range(len(self.data))]
        total_height = MAX_HEIGHT - (MAX_HEIGHT / 10)  # left some space at top
        # rect_width is calculated knowing that there is
        # some free_space at the start and at the end
        rect_width = (MAX_WIDTH - MAX_WIDTH /
                      (len(self.data))) / (len(self.data))
        free_space = rect_width / 2
        new_arr = []
        for i in self.data:
            # calculating relative height for canvas coordinate
            new_arr.append(i / max(self.data))
        if generate_flag:
            self.drawArea.delete("all")
        for i, height in enumerate(new_arr):
            x_left_top = i * rect_width + free_space
            y_left_top = total_height - height * (total_height - 20)
            x_right_bottom = (i + 1) * rect_width + free_space
            y_right_bottom = total_height
            if generate_flag:
                self.colors = [
                    rectBlue for x in range(int(self.sizeEntry.get()))
                ]
                self.rectangles.append(
                    self.drawArea.create_rectangle(x_left_top,
                                                   y_left_top,
                                                   x_right_bottom,
                                                   y_right_bottom,
                                                   fill=color[i]))
            elif self.colors[i] != color[i] or i == len(new_arr) - 1:
                self.drawArea.delete(self.rectangles[i])
                self.rectangles[i] = self.drawArea.create_rectangle(
                    x_left_top,
                    y_left_top,
                    x_right_bottom,
                    y_right_bottom,
                    fill=color[i])
        for i in range(len(self.colors)):
            self.colors[i] = color[i]
        # self.update_idletasks()

    def Stop(self):
        # print("stopped")
        self.stop = True