Can the colour of text be changed in an Eto GroupBox?

This is more of a curiosity thing than a real need.

I noticed that one of the GroupBox properties is TextColor. Has anyone used that? If so, how would you change the title of a groupbox to another colour?

Also, I notice that the borders of the groupbox are barely visible. Can that colour be changed?




Another question. Is it possible to have the form change based off of user picks? For example, can the form expand if the user selects a certain radio button, or checkbox? I guess I’m wondering if it can behave the way a VB form does.



Yes. I will send you a script that does this. Its a little complicated but it contains the details on how to do this. About 30 min before I get back to office.

Here it is: (332.6 KB)

The mesh trimming part is disabled but the GUI should come up when you run the script. Then you can play with the buttons and see what the form does. And you can hover over the different fields to see the tool tip for that field. The tool tips can be turned off if you push the Show Options button.

Pushing Trim Mesh at the bottom will likely cause an error but the other buttons should be safe. The Eto code starts at line 4974 in the Python editor.


Thanks Terry, this should be very helpful.

Is it possible to have a combo box change based off of a radio button selection?


In this illustration I’d like to have the list change to “first pick B, second pick B”, etc. when the “B” radio button is selected.

Same with “C”.

Is that possible?

BTW… @Terry_Chappell, your example helped me with the colours and the tooltips. Still working on expanding the form. Haven’t quite got that working yet.



You need to put a callback on the radio button that updates the list when the button is selected.
See line 5173 which is near the middle of this section of code:

	def CreateRadioButtonsForOperations(self):
		# Create label for radio buttons.
		self.OperationLabel = forms.Label(
			Text = 'Operation',
			Font = Font('Segoe UI', HeaderFont, FontStyle.Bold),
			TextColor = EtoColors.Blue)
		# Create radio buttons.
		self.TrimHolePit = forms.RadioButtonList(
			DataStore = ['Trim', 'Hole ', 'Pit', 'Split'],
			SelectedIndex = self.Args.TrimHolePit,
			ToolTip = ToolTips['TrimHolePit'],
			Padding = drawing.Padding(0,0,0,0),
			Spacing = Size(1,0))
		# Create callback to change text on Trim button when TrimHolePit is changed.
		self.TrimHolePit.SelectedIndexChanged += self.OnTrimHolePitChanged
		# Create Dynamic layout.
		self.OperationsPanel = forms.DynamicLayout(Spacing = drawing.Size(0,0))
		self.OperationsPanel.LoadComplete += self.radioButtonsLoaded
		return self.OperationsPanel
	def OnTrimHolePitChanged(self, sender, e):
		# If trimming mesh, restore Trim button text to Trim and make sure form is full height.
		f = 0.5
		g = 1.1
		hi = 0.7
		# Update text for TrimLabel.
		self.TrimLabel.Text = self.TrimTexts(self.TrimHolePit.SelectedIndex)

The key line is:

self.TrimHolePit.SelectedIndexChanged += self.OnTrimHolePitChanged

which results in a call to:

def OnTrimHolePitChanged(self, sender, e):

whenever a button in the top row of the form is changed:

Click across this row of radio buttons and notice that the Green text changes, and more.

Does this help?

Getting the Eto form to do what you want takes time. I am sure that I spent a few hundred hours getting this 1,050 line GUI working. A lot of this time was spent guessing as I could not find good examples. And then 20% more was spent finding some of the bugs in the form height commands and trying to find a way to work around them. This is why you will find that the line for changing the form height:

self.ClientSize = drawing.Size(self.ClientSize.Width, floor(self.ClientSize.Height - self.Args.Depth_Height + self.Args.TrimLabel_Height))

contains constants stored in: class TrimMeshArgs(): like these:

	# Constants used to get form height changes to work correctly.
	self.Depth_Height = 32
	self.TrimLabel_Height = 19
	self.BaseOn_Height = 15
	self.BaseMeshType_Height = 14
	self.ShowOptionsPanel_Height = 169

I first tried using the height information for the entry on the form, like this:

self.ClientSize = drawing.Size(self.ClientSize.Width, floor(self.ClientSize.Height - self.Depth.Height + self.TrimLabel.Height))

but this does not work because the height values are only defined if the field is visible on the form. I hope this makes you aware of this rat hole so you do not suffer the frustration that I did. I suggest just going with putting the constants in class TrimMeshArgs(): even though you will have to hunt and peck to find the right values. You can shortcut this by printing out the height when the field is on the form:

print 'Depth.Height = ',self.Depth.Height

and this can get you close.

One other nuance to be aware of, is that when you dynamically change a field that has a callback attached to it, the callback may be invoked and cause undesired side effects. You can prevent this by first disabling the disruptive callback by using a - sign in the line that defines the callback:

self.TrimHolePit.SelectedIndexChanged -= self.OnTrimHolePitChanged

then do your change and after that put back the callback as usual:

self.TrimHolePit.SelectedIndexChanged += self.OnTrimHolePitChanged

This does not come up often, but when it does, this is a neat way to do what you want despite what you told the code to do earlier.

I hope that you can be more productive than I was by using any and all parts of my code that you like. I am retired and have no commercial interest in the scripts I create. My hope is they can help others. And then I will be less alone, the only thing that matters in life.



Hi @Terry_Chappell,

I appreciate your attempts to help, but I think I’m just a little too dense to figure this out. If you don’t mind, and if you have the time, could you taking a look at my code and see where I’m going wrong? It’s a simple little script that doesn’t really do anything, it’s just to provide myself an example I can refer back to.

I hate to ask this of you, but I think it would help me get over this mental block I’m having.

ETO Example (6.1 KB)

Thanks in advance,


Yes, I was thinking the same thing. It is one thing to build a 1000 line Eto script and know how it works but after it is done, it is quite a complicated thing to make sense of. The task of creating the Eto script was made easier by my earlier work on another, bigger Python script that used Microsoft Forms. I really went wild on that one with layered callbacks and fast update of a color scale in the Rhino viewport while swiping a field on the form.

Give me a day to work on your script while finishing helping another user that is using the full script to trim their mesh.


Hi @Terry_Chappell,

I appreciate your help. I’ve learnt a lot this week, mostly from your example script.

Have a great weekend,