Reputation: 85
I am trying to write a data input form in Python 3 on Android (Pydroid3) and cannot get colspan to work as I want it to. The two relevant classes are
class LabelledInput(tk.Frame):
'''A widget combining both a label and an input widget'''
def __init__(
self,
parent,
label='',
input_class=ttk.Entry,
input_variable=None,
sticky=(tk.E + tk.W),
label_position=tk.N,
padding_x=(0, 0),
padding_y=(0, 0),
*args,
**kwargs):
super().__init__(parent, *args, **kwargs)
input_args = {}
grid_position = {}
#Check if label_position is valid and default to tk.N if not
if not (label_position in (tk.N, tk.S, tk.W, tk.E)):
label_position = tk.N
# Set up the grid positions for label and input widget
if label_position == tk.N:
grid_position['label'] = {'row':0, 'col':0}
grid_position['input'] = {'row':1, 'col':0}
elif label_position == tk.S:
grid_position['label'] = {'row':1, 'col':0}
grid_position['input'] = {'row':0, 'col':0}
elif label_position == tk.W:
grid_position['label'] = {'row':0, 'col':0}
grid_position['input'] = {'row':0, 'col':1}
elif label_position == tk.E:
grid_position['label'] = {'row':0, 'col':1}
grid_position['input'] = {'row':0, 'col':0}
if input_class in (ttk.Checkbutton, ttk.Button, ttk.Radiobutton):
input_args["text"] = label
input_args["variable"] = input_variable
else:
self.label = ttk.Label(self, text=label)
self.label.grid(
row=grid_position['label']['row'],
column=grid_position['label']['col'],
sticky=sticky)
input_args["textvariable"] = input_variable
self.input = input_class(self, **input_args)
self.input.grid(
row=grid_position['input']['row'],
column=grid_position['input']['col'],
sticky=sticky)
to give me a combined label and input widget (to reduce repetitive typing) and
class CampaignDetails(tk.Frame):
'''New campaign dialog'''
def __init__(self, parent, *args, **kwargs):
super().__init__(parent, *args, **kwargs)
self.inputs = {}
campaignEntry = tk.LabelFrame(self, text='Campaign Details')
self.inputs['Campaign title'] = LabelledInput(
campaignEntry,
label='Campaign title',
input_variable=tk.StringVar).grid(row=0, column=0, columnspan=2)
self.inputs['Ruleset'] = LabelledInput(
campaignEntry,
label='Ruleset',
input_variable=tk.StringVar).grid(row=1, column=0)
self.inputs['Version'] = LabelledInput(
campaignEntry,
label='Version',
input_variable=tk.StringVar).grid(row=1, column=1)
campaignEntry.grid(row=0, column=0, sticky=tk.E + tk.W)
for the actual form itself. However, no matter what I try, the Campaign title widget is stubbornly one column wide. As written above, it is centered in the frame. If I add sticky=tk.W + tk.E, it left justifies, but remains the same width. If I try any form of campaignEntry.columnconfigure to try and set the weight, the overall width of the form changes, but Campaign title remains one column wide.
Upvotes: 0
Views: 167
Reputation: 385930
Your use of columnspan
is working. You didn't tell the widget to fill the space that was allocated to it, so it remains its natural size and centered in the space.
You need to use the sticky
attribute if you want the widget to fill all of the space it is allocated.
self.inputs['Campaign title'] = LabelledInput(...).grid(..., sticky="ew")
You also need to use columnconfigure
to give a weight to the first column in the LabelledInput
frame so that the column expands to fill unallocated space in the frame.
class LabelledInput(tk.Frame):
def __init__(...):
...
self.grid_columnconfigure(0, weight=1)
...
Upvotes: 1