Open ghost opened 7 years ago
Definitely interested in adding this.
How do you envisage it working?
Perhaps just a flag that can be set to use ttk if available? This will then import ttk and replace any existing widgets with ttk widgets, as well as make any new widgets available?
Is ttk always part of a Python installation? I seem to remember having issues importing ttk when I first started appJar...
If a user wants ttk, then the config options might need to be changed too?
I imagined using a flag, and then tk/ttk specific functions/options would check for the flag and then use the relevant options. I think the best way to set the flag would be either:
app = gui( useTtk=True )
Or:
app = gui()
app.useTtk()
I'm not sure if tk and ttk widgets can exist together, so if have to check that out.
The x86 Windows installer for python 3.6 has ttk by default, but when I get home I can check some Linux distros. Either way, I think using tk as the default and and requiring ttk to be explicitly asked for would be for the best.
Config options are the biggest issue with this. I remember bg, padx, and pady being the biggest culprits, but it won't be too hard to get the ttk widgets running properly, just some if..else
statements checking for the useTtk
flag.
EDIT: Fixed formatting
Fully updated and (almost) clean VMs of Ubuntu 16.04 LTS 64 bit, Fedora 25 64 bit, and FreeBSD 64 bit all properly import tkinter, and ttk in python 2 and 3 after installing the necessary packages. It looks like every modern pre-built python is linked against tkinter >= 8.5
Great, thanks for investigating that!
OK, I'll add the second option you mention above, and for now simply have that import ttk - that will override any existing widgets.
I'll leave it at that for the current scheduled release (already overdue) - unless it breaks the basic setup - then in the next release we can look at updating config functions, as well as exposing any other widgets/features.
This doesn't really have any effect.
Need to change instantiation to actually be ttk.Button, etc....
Check here for how to set ttk styles: http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/ttk-style-layer.html
And themes: http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/ttk-theme-layer.html
Making progress - need to work out how to subclass using a switch for ttk (for SelectableLabel, AutoCompleteEntry, ajScale)- might not be possible...
Need to go through top-level frames, etc - make sure they are all ttk - might need to have ttk a constructor parameter to achieve this.
Need to look at scrollbars - on list boxes, scroll panes, etc
Just a small note, you may want to use "clam" as default style on Linux, "aqua" for Mac and "vista" for Windows, these are all built-in so shouldn't cause any issues, you could slap it in a try/except to ignore failed style changes.
Have a solution for subclassing:
However, note that a lot of special classes rely heavily on non-ttk supported features - and can't use a ttk.Label
The useTtk flag needs to be moved to the constructor - otherwise the base Frame can't be a ttk frame
useTtk
now available in constructor - the only benefit is that the entire GUI is in a ttk.Frame instead of Frame - gets rid of the white border.
TextArea isn't supported by Ttk.
mark@mark-desktop2:~/dev/git/HS602/hs602util$ python3 gui.py --ttk default
Exception in Tkinter callback
Traceback (most recent call last):
File "/usr/lib/python3.5/tkinter/__init__.py", line 1553, in __call__
return self.func(*args)
File "/usr/lib/python3.5/tkinter/__init__.py", line 599, in callit
func(*args)
File "/home/mark/.local/lib/python3.5/site-packages/appJar/appjar.py", line 1852, in __processEventQueue
func(*args, **kwargs)
File "gui.py", line 103, in error_win
self.addScrolledTextArea('traceback')
File "/home/mark/.local/lib/python3.5/site-packages/appJar/appjar.py", line 6883, in addScrolledTextArea
text = self.__buildTextArea(title, self.getContainer(), True)
File "/home/mark/.local/lib/python3.5/site-packages/appJar/appjar.py", line 6849, in __buildTextArea
text.config(highlightbackground=self.__getContainerBg())
File "/home/mark/.local/lib/python3.5/site-packages/appJar/appjar.py", line 3239, in __getContainerBg
return self.getContainer()["bg"]
File "/usr/lib/python3.5/tkinter/__init__.py", line 1337, in cget
return self.tk.call(self._w, 'cget', '-' + key)
_tkinter.TclError: unknown option "-bg"
mark@mark-desktop2:~/dev/git/HS602/hs602util$ python3 gui.py --ttk default
Exception in Tkinter callback
Traceback (most recent call last):
File "/usr/lib/python3.5/tkinter/__init__.py", line 1553, in __call__
return self.func(*args)
File "/usr/lib/python3.5/tkinter/__init__.py", line 599, in callit
func(*args)
File "/home/mark/.local/lib/python3.5/site-packages/appJar/appjar.py", line 1852, in __processEventQueue
func(*args, **kwargs)
File "gui.py", line 103, in error_win
self.addTextArea('traceback')
File "/home/mark/.local/lib/python3.5/site-packages/appJar/appjar.py", line 6871, in addTextArea
text = self.__buildTextArea(title, self.getContainer())
File "/home/mark/.local/lib/python3.5/site-packages/appJar/appjar.py", line 6849, in __buildTextArea
text.config(highlightbackground=self.__getContainerBg())
File "/home/mark/.local/lib/python3.5/site-packages/appJar/appjar.py", line 3239, in __getContainerBg
return self.getContainer()["bg"]
File "/usr/lib/python3.5/tkinter/__init__.py", line 1337, in cget
return self.tk.call(self._w, 'cget', '-' + key)
_tkinter.TclError: unknown option "-bg"
ValidationEntry using ttk errors :crying_cat_face: .
Exception in Tkinter callback
Traceback (most recent call last):
File "/usr/lib/python3.6/tkinter/__init__.py", line 1702, in __call__
return self.func(*args)
File "/usr/lib/python3.6/tkinter/__init__.py", line 748, in callit
func(*args)
File "/home/mark/.local/lib/python3.6/site-packages/appJar/appjar.py", line 2058, in __processEventQueue
func(*args, **kwargs)
File "gui2.py", line 197, in result
return self.manual()
File "gui2.py", line 238, in manual
self.addValidationEntry('addr', 0, 1)
File "/home/mark/.local/lib/python3.6/site-packages/appJar/appjar.py", line 7370, in addValidationEntry
ent = self.__buildValidationEntry(title, self.getContainer(), secret)
File "/home/mark/.local/lib/python3.6/site-packages/appJar/appjar.py", line 7376, in __buildValidationEntry
vFrame.config(background=self.__getContainerBg())
File "/home/mark/.local/lib/python3.6/site-packages/appJar/appjar.py", line 3422, in __getContainerBg
return self.getContainer()["bg"]
File "/usr/lib/python3.6/tkinter/__init__.py", line 1486, in cget
return self.tk.call(self._w, 'cget', '-' + key)
_tkinter.TclError: unknown option "-bg"
I like the use of validation alerting, but wouldn't it be easier (and less code?) to replace "setEntryValid", "setEntryInvalid", and "setEntryWaitingValidaiton" with a single function? That just flashes the entry (once) & inserts some text indicating the error - disappearing on click/text entry?
The use of the icons next to the entries is a nice touch but it kinda looks odd when you have your form neatly aligned and some are just standard entries. This could be solved with an addOptional(
@mpmc - did a piece of work to get validation entries (sort of) working under ttk. Had to work out ttk styles, but at least now it doesn't crash. The border doesn't work on my mac - need to test on other platforms.
You're right - the validation entry could use lots of work. I will look at refactoring the set functions as part of the general add/set/get refactoring I'm currently doing, and will see what improvements can be made to its look & feel...
@jarvisteach cool, I shall give it a go once I've redone this controller class & report any issues!
Should include support for additional ttk themes: https://github.com/RedFantom/ttkthemes
@jarvisteach I've been trying out ttk on the next release appJar branch, and have found some issues.
The first one I encountered was when I used.setCheckbox("title", ticked=True)
, it would give me AttributeError: 'Checkbutton' object has no attribute 'select'
.
The second issue that I found was that when I used .zoomImage()
, it would give me _tkinter.TclError: unknown option "-bg"
.
I understand that ttk is still in beta, but I thought that it would be good if I let you know of these issues :)
These should both be resolved now, and do please keep them coming!
@jarvisteach Here some more issues (yay!). This time, it's with .addMessage()
. I get _tkinter.TclError: unknown option "-bg"
.
Also, Internationalisation looks like it breaks when using ttk, as I get appJar:WARNING [Line 285->1139/changeLanguage]: Invalid config section: <Widget name here>
for all the widgets that I have used.
Internationalisation looks to be a slightly bigger issue than just ttk - it's broken across the board, as result of the architecture change.
This bit no longer works: kind = vars(gui)[section]
Need to replace that with a lookup in the enum, using the section name - might cause issues due to the capitalisation.
Also, the automated testing should have picked this up - need to actually run some assertions that text has been changed post language switch...
Will raise this/move this to another issue.
@jarvisteach I've found that when using label frames and .setBg()
, the background of the label frame doesn't change, with (as far as I've tested) only images and labels using the correct background colour. Also, regarding internationalisation, I get a warning that says that the Notebook widget is not supported (should this move to #71 ?) and this obviously leads to the notebook tabs not being translated.
@jarvisteach
Do you plan on making ttk widgets the default btw? Once they're all working that is.
@jarvisteach Here are a couple of things that I found that aren't currently being themed by ttk: Spinboxes and Toolbars.
Hey @The-Sleepy-Penguin I don't think there is a ttk spinbox - http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/ttk-widget-set.html
What theming are you trying to achieve with it?
@jarvisteach Oops. My mistake - I didn't realise that there wasn't a ttk spinbox (I was just looking for widgets that would let the user make a selection). Perhaps the Optionbox should be replaced by the Combobox for ttk?
And another thing - Radiobuttons in ttk don't respond to .setBg
(along with Labelframes).
Edit: After a quick search I found this for the ttk spinbox. It looks like it uses the buttons from the ttk scrollbar to change the selection.
@jarvisteach I've read the next_release docs and found how to change the background of most things, but the label in the LabelFrame doesn't change colour when I do: program.ttkStyle.configure("TLabel", background="white")
, and I can't find the name for the checkbox layout, as I've tried to use TCheck
, TCheckbox
and TCheckBox
but all return Layout xxx not found
.
Also, I noticed a typo in the docs - with the code examples, you put background=
as backgroun=
:P
Hi @The-Sleepy-Penguin could you give me some sample code to test out...
@jarvisteach Here is some code that demonstrates the issue with Label Frames and Checkboxes:
from appJar import gui
with gui("appJar", useTtk=True) as app:
app.ttkStyle.configure("TFrame", background="blue")
app.ttkStyle.configure("TLabel", background="blue")
app.ttkStyle.configure("TCheckBox", background="blue")
app.ttkStyle.configure("TCheck", background="blue")
app.setBg("blue")
with app.labelFrame("Text"):
app.setLabelFrameStyle("Text", "TFrame")
app.addCheckBox("Option here...")
app.setCheckBoxStyle("Option here...", "TCheckBox")
app.addCheckBox("Another option...")
app.setCheckBoxStyle("Another option...", "TCheck")
And here is the result:
Hope this helps :)
OK, had a little play, try these:
These set the default styles for the widgets, so you should't need to call .set XXX Style()
I've also discovered this:
ttk styles inherit from one another, so setting background on .
will be inherited by all widgets.
I'm going to use this in appJar...
@jarvisteach Thanks! Those worked a charm.
Okay... just tried this with message boxes and sub windows - app.ttkStyle.configure(".", background="blue")
doesn't seem to work.
I was also wondering if the message box was themed by ttk, because it doesn't use the regular font used by ttk themes, and when I use .setMessageBg()
instead, the background colour changes.
When using label frames and third party ttk themes, unless I use app.ttkStyle.configure("TFrame", background="blue")
and app.setLabelFrameStyle("title", "TFrame")
, it too won't respond to app.ttkStyle.configure(".", background="blue")
.
TopLevel
widget - this doesn't seem to support ttk, I'll do a bit more digging to see if it can, or maybe I'll need to put a Frame inside it that can support ttk...@jarvisteach Is the non-ttk theme your own btw? It looks totally different to what I see elsewhere. The optionbox looks completely different too.
vs
@jarvisteach I've found that .addIconButton()
and .addImageButton()
produce errors only when ttk is set to True, and align is set to None. eg:
from appJar import gui
with gui(useTtk=True) as app:
app.addImageButton("button2", None, "Capture 2.PNG", align=None) # Uncomment this
app.addIconButton("button", None, "md-play", align=None) # Or this
Produces this for .addImageButton()
:
2017-12-28 00:15:51,892 appJar:ERROR [Line 5->1522/__exit__]: ContextManager failed: unknown option "-justify"
Traceback (most recent call last):
File "C:/Users/Penguin/Desktop/icon buttons.py", line 5, in <module>
app.addImageButton("button2", None, "Capture 2.PNG", align=None)
File "C:/Users/Penguin/Desktop\appJar\appjar.py", line 6823, in addImageButton
self.setButtonImage(title, imgFile, align)
File "C:/Users/Penguin/Desktop\appJar\appjar.py", line 6844, in setButtonImage
but.config(image=image, compound=TOP, text="", justify=LEFT)
File "C:\Program Files\Python35\lib\tkinter\__init__.py", line 1338, in configure
return self._configure('configure', cnf, kw)
File "C:\Program Files\Python35\lib\tkinter\__init__.py", line 1329, in _configure
self.tk.call(_flatten((self._w, cmd)) + self._options(cnf))
_tkinter.TclError: unknown option "-justify"
and this for .addIconButton()
:
2017-12-28 00:15:43,907 appJar:ERROR [Line 4->1522/__exit__]: ContextManager failed: unknown option "-justify"
Traceback (most recent call last):
File "C:/Users/Penguin/Desktop/icon buttons.py", line 4, in <module>
app.addIconButton("button", None, "md-play", align=None)
File "C:/Users/Penguin/Desktop\appJar\appjar.py", line 6829, in addIconButton
return self.addImageButton(title, func, icon, row, column, colspan, rowspan, align)
File "C:/Users/Penguin/Desktop\appJar\appjar.py", line 6823, in addImageButton
self.setButtonImage(title, imgFile, align)
File "C:/Users/Penguin/Desktop\appJar\appjar.py", line 6844, in setButtonImage
but.config(image=image, compound=TOP, text="", justify=LEFT)
File "C:\Program Files\Python35\lib\tkinter\__init__.py", line 1338, in configure
return self._configure('configure', cnf, kw)
File "C:\Program Files\Python35\lib\tkinter\__init__.py", line 1329, in _configure
self.tk.call(_flatten((self._w, cmd)) + self._options(cnf))
_tkinter.TclError: unknown option "-justify"
If ttk is set to False or the align parameter is filled, the error will not occur.
@The-Sleepy-Penguin - try setting align="none"
instead of None
@jarvisteach Thanks, that worked.
@jarvisteach When using padding within a frame, the padding doesn't take the colour of the background:
from appJar import gui
with gui("appJar", useTtk=True) as app:
app.setPadding(10, 10)
app.ttkStyle.configure(".", background="white")
app.addButton("Button", func=None)
app.addButton("Button2", func=None)
with app.frame("frame"):
app.setPadding(10, 10)
app.ttkStyle.configure(".", background="white")
app.setBg("white")
app.addButton("Button3", func=None)
app.addButton("Button4", func=None)
And so results in this:
Hi @The-Sleepy-Penguin - I don't know what causes this, it could be a ttk specific thing, where extra style needs to be set (maybe for the padding), or something else. I'll try to look into it in the next few days...
@The-Sleepy-Penguin - OK resolved issue with frames - still can't get dynamic inheritance to work properly, so Frame is now dynamic, and should work with both ttk and regular styling.
@jarvisteach Great! I can confirm that it works :)
@jarvisteach Would it be possible to integrate a themed Dropdown Widget (like OptionBox)? As @TheSleepyPenguin mentioned that the TTK ComboBox could replace the AppJar OptionBox?
Is there any chance you'd be willing to add ttk support, or accept a PR adding ttk support? I personally like the native look a lot more, and I'd love to use ttk widgets with appJar.
List of supported widgets (http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/ttk-widget-set.html)
Basic widgets:
And their other incantations:
Others:
Nice to haves:
[ ] OptionBox?
[x] Also, include support for additional ttk themes