问题
I am writing a GUI FTP client app in python ttk. I can't seem to get the text Entries the way I wanted them to.
The text Entries have the "SUNKEN" effect. I want to adjust the height and get the text entries to have a "FLAT" look, more like this program:
I got the buttons to look flat from here, I am struggling to get the Entries to look flat.
How do I get the Entries to look flat?
I don't want a tk solution, I know how to set relief FLAT in tk.
回答1:
Trivia:
Appereance of ttk widgets heavily depends on theme in use and/or platform. On windows I can reproduce this depressive gray style with a classic
theme, so let's assume that this theme in use. List of themes you can find here (note the 'clam'
theme, wich is most similar to your wishes), just if you wonder.
Next stop, our layout or, in other words, a structure of widget's theme.
You can easily print this structure to see available options. Enough words, let's try a structure of an ttk.Entry
widget.
>>> print(s.layout('TEntry'))
# formatted result, actual result is one-line string
[('Entry.highlight', {
'sticky': 'nswe',
'children': [(
'Entry.field', {
'sticky': 'nswe',
'children': [(
'Entry.padding', {
'sticky': 'nswe',
'children': [(
'Entry.textarea', {
'sticky': 'nswe'})]
})],
'border': '1'})]
})]
As you can see, noone of structure elements has a relief
option, hence relief='flat'
has no effect on our entry!
>>> print(s.element_options('Entry.field'))
('-bordercolor', '-lightcolor', '-darkcolor', '-fieldbackground')
Workaround:
However, we can edit the layout of desired widget, and replace one element with another, wich able to recognize a relief
option (note a removed Entry.field
, replaced with an Entry.border
).
So try out this little snippet:
try:
import tkinter as tk
import tkinter.ttk as ttk
except ImportError:
import Tkinter as tk
import ttk
# root
root = tk.Tk()
# declare style variable
s = ttk.Style()
# assume that classic theme in use
s.theme_use('classic')
# configure relief
s.configure('SOExample.TEntry', relief='flat')
# lets try to change this structure
s.layout('SOExample.TEntry', [
('Entry.highlight', {
'sticky': 'nswe',
'children':
[('Entry.border', {
'border': '1',
'sticky': 'nswe',
'children':
[('Entry.padding', {
'sticky': 'nswe',
'children':
[('Entry.textarea',
{'sticky': 'nswe'})]
})]
})]
})])
# let's find some differences between this two
print(s.layout('SOExample.TEntry'))
print(s.layout('TEntry'))
# packing
frame1 = tk.Frame(root)
label1 = tk.Label(frame1, text='Flat Entry')
entry1 = ttk.Entry(frame1, style='SOExample.TEntry')
label1.pack()
entry1.pack()
frame1.pack(side='left')
frame2 = tk.Frame(root)
label2 = tk.Label(frame2, text='Default Entry')
entry2 = ttk.Entry(frame2)
label2.pack()
entry2.pack()
frame2.pack(side='right')
# mainloop
root.mainloop()
...and final appereance is:
Also, on my machine default theme is vista
and there I can't even recognize an entry:
And also a structure of an Entry
depends on theme, so with vista
it's:
# formatted result, actual result is one-line string
[('Entry.field', {
'sticky': 'nswe',
'children': [(
'Entry.background', {
'sticky': 'nswe',
'children': [(
'Entry.padding', {
'sticky': 'nswe',
'children': [(
'Entry.textarea', {
'sticky': 'nswe'})]
})]
})]
})]
...and if we replace a field
with border
element in this structure, the appearence is very close to your demands (also try groove
relief in this case):
Conclusion:
Unfortunately, this widget will lack options of field and border color, so another option is create own element for this purpose, but that is another question.
So, basicly I tryied to answer not "how to workaround this", but "why a relief has no effect on Entry", anyway as you can see, a flat relief for an Entry is achievable.
来源:https://stackoverflow.com/questions/44383730/how-to-get-flat-relief-entry-widget-in-python-ttk