Scrollable Columns - NEW Feature!

This commit is contained in:
MikeTheWatchGuy 2018-09-03 10:51:54 -04:00
parent 6115a00e30
commit ccd3e4c797
2 changed files with 112 additions and 23 deletions

View File

@ -7,18 +7,55 @@ import PySimpleGUI as sg
# sg.ChangeLookAndFeel('BlueMono')
# Column layout
col = [[sg.Text('col Row 1', text_color='white', background_color='blue')],
[sg.Text('col Row 2', text_color='white', background_color='blue'), sg.Input('col input 1')],
[sg.Text('col Row 3', text_color='white', background_color='blue'), sg.Input('col input 2')]]
layout = [[sg.Listbox(values=('Listbox Item 1', 'Listbox Item 2', 'Listbox Item 3'), select_mode=sg.LISTBOX_SELECT_MODE_MULTIPLE, size=(20,3)), sg.Column(col, background_color='blue')],
[sg.Input('Last input')],
[sg.OK()]]
def ScrollableColumns():
# sg.ChangeLookAndFeel('Dark')
# Display the form and get values
# If you're willing to not use the "context manager" design pattern, then it's possible
# to collapse the form display and read down to a single line of code.
button, values = sg.FlexForm('Compact 1-line form with column').LayoutAndRead(layout)
sg.MsgBox(button, values, line_width=200)
column1 = [[sg.Text('Column 1', justification='center', size=(20, 1))],
[sg.Spin(values=('Spin Box 1', '2', '3'), initial_value='Spin Box 1', key='spin1', size=(30,1))],
[sg.Spin(values=('Spin Box 1', '2', '3'), initial_value='Spin Box 2', key='spin2')],
[sg.Spin(values=('Spin Box 1', '2', '3'), initial_value='Spin Box 2', key='spin2')],
[sg.Spin(values=('Spin Box 1', '2', '3'), initial_value='Spin Box 2', key='spin2')],
[sg.Spin(values=('Spin Box 1', '2', '3'), initial_value='Spin Box 2', key='spin2')],
[sg.Spin(values=('Spin Box 1', '2', '3'), initial_value='Spin Box 2', key='spin2')],
[sg.Spin(values=('Spin Box 1', '2', '3'), initial_value='Spin Box 2', key='spin2')],
[sg.Spin(values=('Spin Box 1', '2', '3'), initial_value='Spin Box 2', key='spin2')],
[sg.Spin(values=('Spin Box 1', '2', '3'), initial_value='Spin Box 2', key='spin2')],
[sg.Spin(values=('Spin Box 1', '2', '3'), initial_value='Spin Box 2', key='spin2')],
[sg.Spin(values=('Spin Box 1', '2', '3'), initial_value='Spin Box 2', key='spin2')],
[sg.Spin(values=('Spin Box 1', '2', '3'), initial_value='Spin Box 2', key='spin2')],
[sg.Spin(values=('Spin Box 1', '2', '3'), initial_value='Spin Box 3', key='spin3')]]
column2 = [[sg.T('Table Test')]]
for i in range(50):
column2.append([sg.T(f'{i}{j}', size=(4, 1), background_color='gray25', text_color='white', pad=(1, 1)) for j in range(10)])
layout = [[sg.Column(column2, scrollable=True, size=(400,300)), sg.Column(column1, scrollable=True, size=(200,150))],
[sg.OK()]]
form = sg.FlexForm('Form Fill Demonstration', default_element_size=(40, 1))
b, v = form.LayoutAndRead(layout)
def NormalColumns():
# Column layout
col = [[sg.Text('col Row 1', text_color='white', background_color='blue')],
[sg.Text('col Row 2', text_color='white', background_color='blue'), sg.Input('col input 1')],
[sg.Text('col Row 3', text_color='white', background_color='blue'), sg.Input('col input 2')]]
layout = [[sg.Listbox(values=('Listbox Item 1', 'Listbox Item 2', 'Listbox Item 3'), select_mode=sg.LISTBOX_SELECT_MODE_MULTIPLE, size=(20,3)), sg.Column(col, background_color='blue')],
[sg.Input('Last input')],
[sg.OK()]]
# Display the form and get values
# If you're willing to not use the "context manager" design pattern, then it's possible
# to collapse the form display and read down to a single line of code.
button, values = sg.FlexForm('Compact 1-line form with column').LayoutAndRead(layout)
sg.Popup(button, values, line_width=200)
NormalColumns()
ScrollableColumns()

View File

@ -1059,20 +1059,52 @@ class TkScrollableFrame(tk.Frame):
# create a canvas object and a vertical scrollbar for scrolling it
self.vscrollbar = tk.Scrollbar(self, orient=tk.VERTICAL)
self.vscrollbar.pack(side='right', fill="y", expand="false")
self.canvas = tk.Canvas(self, yscrollcommand=self.vscrollbar.set)
self.canvas.pack(side="left")
self.hscrollbar = tk.Scrollbar(self, orient=tk.HORIZONTAL)
self.hscrollbar.pack(side='bottom', fill="x", expand="false")
self.canvas = tk.Canvas(self, yscrollcommand=self.vscrollbar.set, xscrollcommand=self.hscrollbar.set)
self.canvas.pack(side="left", fill="both", expand=True)
self.vscrollbar.config(command=self.canvas.yview)
self.hscrollbar.config(command=self.canvas.xview)
# reset the view
self.canvas.xview_moveto(0)
self.canvas.yview_moveto(0)
# create a frame inside the canvas which will be scrolled with it
# self.interior = tk.Frame(self.canvas, **kwargs)
# self.canvas.create_window(0, 0, window=self.interior, anchor="nw")
self.TKFrame = tk.Frame(self.canvas, **kwargs)
self.canvas.create_window(0, 0, window=self.TKFrame, anchor="nw")
self.canvas.config(borderwidth=0, highlightthickness=0)
self.TKFrame.config(borderwidth=0, highlightthickness=0)
self.config(borderwidth=0, highlightthickness=0)
# self.bind('<Configure>', self.set_scrollregion)
self.bind('<Configure>', self.set_scrollregion)
self.bind_mouse_scroll(self.canvas, self.yscroll)
self.bind_mouse_scroll(self.hscrollbar, self.xscroll)
self.bind_mouse_scroll(self.vscrollbar, self.yscroll)
def yscroll(self, event):
if event.num == 5 or event.delta < 0:
self.canvas.yview_scroll(1, "unit")
elif event.num == 4 or event.delta > 0:
self.canvas.yview_scroll(-1, "unit")
def xscroll(self, event):
if event.num == 5 or event.delta < 0:
self.canvas.xview_scroll(1, "unit")
elif event.num == 4 or event.delta > 0:
self.canvas.xview_scroll(-1, "unit")
def bind_mouse_scroll(self, parent, mode):
# ~~ Windows only
parent.bind("<MouseWheel>", mode)
# ~~ Unix only
parent.bind("<Button-4>", mode)
parent.bind("<Button-5>", mode)
def set_scrollregion(self, event=None):
""" Set the scroll region on the canvas"""
@ -1083,7 +1115,7 @@ class TkScrollableFrame(tk.Frame):
# Column #
# ---------------------------------------------------------------------- #
class Column(Element):
def __init__(self, layout, background_color = None, pad=None):
def __init__(self, layout, background_color = None, size=(None, None), pad=None, scrollable=False):
self.UseDictionary = False
self.ReturnValues = None
self.ReturnValuesList = []
@ -1093,11 +1125,12 @@ class Column(Element):
self.Rows = []
self.ParentForm = None
self.TKFrame = None
self.Scrollable = scrollable
bg = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR
self.Layout(layout)
super().__init__(ELEM_TYPE_COLUMN, background_color=background_color, pad=pad)
super().__init__(ELEM_TYPE_COLUMN, background_color=background_color, size=size, pad=pad)
return
def AddRow(self, *args):
@ -1763,9 +1796,23 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
element_size = (int(element_size[0] * toplevel_form.Scale[0]), int(element_size[1] * toplevel_form.Scale[1]))
# ------------------------- COLUMN element ------------------------- #
if element_type == ELEM_TYPE_COLUMN:
col_frame = tk.Frame(tk_row_frame)
# col_frame = TkScrollableFrame(tk_row_frame) # do not use yet! not working
PackFormIntoFrame(element, col_frame, toplevel_form)
if element.Scrollable:
col_frame = TkScrollableFrame(tk_row_frame) # do not use yet! not working
PackFormIntoFrame(element, col_frame.TKFrame, toplevel_form)
col_frame.TKFrame.update()
if element.Size == (None, None):
col_frame.canvas.config(width=col_frame.TKFrame.winfo_reqwidth(),height=col_frame.TKFrame.winfo_reqheight())
else:
col_frame.canvas.config(width=element.Size[0],height=element.Size[1])
if not element.BackgroundColor in (None, COLOR_SYSTEM_DEFAULT):
col_frame.canvas.config(background=element.BackgroundColor)
col_frame.TKFrame.config(background=element.BackgroundColor, borderwidth =0, highlightthickness=0)
col_frame.config(background=element.BackgroundColor, borderwidth =0, highlightthickness=0)
else:
col_frame = tk.Frame(tk_row_frame)
PackFormIntoFrame(element, col_frame, toplevel_form)
col_frame.pack(side=tk.LEFT, padx=element.Pad[0], pady=element.Pad[1])
if element.BackgroundColor != COLOR_SYSTEM_DEFAULT and element.BackgroundColor is not None:
col_frame.configure(background=element.BackgroundColor, highlightbackground=element.BackgroundColor, highlightcolor=element.BackgroundColor)
@ -3092,11 +3139,16 @@ def ChangeLookAndFeel(index):
'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0,
'PROGRESS_DEPTH': 0},
'DarkTanBlue': {'BACKGROUND': '#242834', 'TEXT': '#dfe6f8', 'INPUT': '#4f5764',
'DarkTanBlue': {'BACKGROUND': '#242834', 'TEXT': '#dfe6f8', 'INPUT': '#97755c',
'TEXT_INPUT': 'white', 'SCROLL': '#a9afbb', 'BUTTON': ('white', '#063289'),
'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0,
'PROGRESS_DEPTH': 0},
'DarkAmber': {'BACKGROUND': '#2c2825', 'TEXT': '#fdcb52', 'INPUT': '#705e52',
'TEXT_INPUT': '#fdcb52', 'SCROLL': '#705e52', 'BUTTON': ('black', '#fdcb52'),
'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0,
'PROGRESS_DEPTH': 0},
'DarkBlue': {'BACKGROUND': '#1a2835', 'TEXT': '#d1ecff', 'INPUT': '#335267',
'TEXT_INPUT': '#acc2d0', 'SCROLL': '#1b6497', 'BUTTON': ('black', '#fafaf8'),
'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0,