2

I am trying to display a sudoku layout with tkinter grid and ttk entries (maybe, I am not using the right approach to achieve it). I would like to know if the style option of ttk entry has any way to change the border of just one side. I have applied this function:

def grid_layout(parent):
    
    s = ttk.Style()
    s.configure('border.TEntry',borderwidth=3)
    
    for row in range(1,10):
        for column in range(1,10):
            entry = None
            if column % 3 == 0 or row % 3 == 0:
                entry = ttk.Entry(parent, width=3,justify='center'
                                  ,style='border.TEntry')
            else:
                entry = ttk.Entry(parent,width=3,justify='center')
                
            entry.grid(column= column, row = row)

Which produces the following view:

enter image description here

I just need to change the border width shared by colum 3-4, 6-7 and row 3-4 and 6-7 ,as the typical sudoku-like layout. Any recommendations would be appreciated.

Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685

1 Answers1

2

As stated in my comment before, I'd use a stacked layout with the boxes in frames and the entries in these boxes. So there is no need for special styling. Access to the values within the ttk.Entries gives a dictionary that contains tk.StringVar objects, the keys are uppercase letters 'A'..'I' combined with numbers '1'..'9' like in spreadsheet applications:

import tkinter as tk
from tkinter import ttk

mainWin = tk.Tk()
mainWin.title('Sudoku solver')

mainFrame = ttk.Frame(mainWin, borderwidth=10)
mainFrame.grid(column=1, row=1)

# access to entries (of type tk.StringVar)
values = {}

for box_col in range(3):
    for box_row in range(3):
        box = ttk.Frame(mainFrame, borderwidth=1, relief='sunken')
        box.grid(column=box_col+1, row=box_row+1)
        for cell_col in range(3):
            for cell_row in range(3):
                v = tk.StringVar()
                # build spreadsheet key from overall column and row
                col = 'ABCDEFGHI'[3*box_col+cell_col]
                row = '123456789'[3*box_row+cell_row]
                key = col+row
                values[key] = v
                entry = ttk.Entry(box, width=3, justify='center', textvariable=v)
                entry.grid(column=cell_col+1, row=cell_row+1)

# example for accessing the entries
values['A1'].set(1)
values['G3'].set(7)
values['E5'].set(int(values['A1'].get())+4)
values['I9'].set(int(values['E5'].get())+4)

mainWin.mainloop()

Under Windows 8.1, this will look this:

Screenshot of an example configuration

Wolf
  • 9,679
  • 7
  • 62
  • 108
  • I think I will use a numpy array to dump the info and check the integrity of the sudoku. – Juan Villaseca Apr 15 '21 at 13:33
  • @JuanVillaseca maybe this could be of interest: [Adding validation to an Entry widget](https://anzeljg.github.io/rin2/book2/2405/docs/tkinter/entry-validation.html) which probably makes it easier to keep a compact up-to-date container of all 81 numbers and check the entire Sudoku this way. (iterating about all `StringVar`s seems slow to me) – Wolf Apr 15 '21 at 14:40
  • Maybe [this answer to "Interactively validating Entry widget content in tkinter"](https://stackoverflow.com/a/4140988/2932052) is even more helpful. Validating has also the advantage to disallow all edits that cause values beyond `'1'`, `'2'`, `'3'`, `'4'`, `'5'`, `'6'`, `'7'`, `'8'`, `'9'` and `''`. – Wolf Apr 15 '21 at 15:01
  • It is very useful. Nevertheless, I think I will display a clickable dialog when the users click on one cell. By 'check the integrity of the sudoku', I meant checking that there are no numbers repeated within the same box, column and row. – Juan Villaseca Apr 15 '21 at 17:12