experchange > python

Paulo da Silva (12-06-18, 09:02 AM)
Hi!

Does anybody know why this code does not expand the text widget when I
increase the window size (with mouse)? I want height and width but as
minimum (or may be initial) size.

import tkinter as tk

class App:
def __init__(self,master):
self.tboard=tk.Text(master,height=40,width=50)
self.tboard.grid(row=1,column=1,sticky="nsew")
self.tboard.grid_rowconfigure(1,weight=1)
self.tboard.grid_columnconfigure(1,weight=1)

root=tk.Tk()
app=App(root)

root.mainloop()

Thanks
Peter Otten (12-06-18, 10:24 AM)
Paulo da Silva wrote:

> Does anybody know why this code does not expand the text widget when I
> increase the window size (with mouse)? I want height and width but as
> minimum (or may be initial) size.
> import tkinter as tk
> class App:
> def __init__(self,master):
> self.tboard=tk.Text(master,height=40,width=50)
> self.tboard.grid(row=1,column=1,sticky="nsew")


You have to set the column/row weight of the /master/:

master.grid_columnconfigure(1, weight=1)
master.grid_rowconfigure(1, weight=1)

Also, columns and rows usually start with 0.
[..]
Paulo da Silva (12-06-18, 04:52 PM)
Ās 08:24 de 06/12/18, Peter Otten escreveu:
> Paulo da Silva wrote: ....
> You have to set the column/row weight of the /master/:
> master.grid_columnconfigure(1, weight=1)
> master.grid_rowconfigure(1, weight=1) Ok. That works!


> Also, columns and rows usually start with 0. Yes, I know that. I have other stuff there.


Thank you very much Peter.
Rick Johnson (12-06-18, 11:15 PM)
Paulo da Silva wrote:

[..]
> root=tk.Tk()
> app=App(root)
> root.mainloop()


In Tkinter, if you have a "container"[1] that only has a
single widget stuffed inside, and, you want that single
widget to expand to fill the extents of its parent
container, then, the pack geometry manager is the simplest
approach.

w = create_a_widget()
w.pack(fill=X|Y|BOTH, expand=YES)

But beware not to mix pack and grid in the same "container",
as Tkinter is too dense to handle the resulting logic
catastrophe. Which is coincidentally one of the (many)
design flaws of Tkinter. A better approach would have been
to use "layout boxes", which, are nothing but frames that
are designed to stack widgets in one of two directions
(either vertically or horizontally).

I kinda have a love/hate relationship with Tkinter and IDLE.
On one hand i find them to be practical[2] and simple[3] and
on the other, i find them to be poorly designed and
unintuitive. And it's a real shame, because, both of these
libraries have tons of potential, *IF*, they were designed
probably and the shortcomings of TclTk were abstracted away
behind a more Pythonic interface.
Paulo da Silva (12-07-18, 04:00 AM)
Ās 21:15 de 06/12/18, Rick Johnson escreveu:
> Paulo da Silva wrote: ....


> In Tkinter, if you have a "container"[1] that only has a
> single widget stuffed inside, and, you want that single
> widget to expand to fill the extents of its parent
> container, then, the pack geometry manager is the simplest
> approach.
> w = create_a_widget()
> w.pack(fill=X|Y|BOTH, expand=YES)

Yes, I am aware of pack. Unfortunately the code fragment I posted is a
very small part of a larger widget.

....

> I kinda have a love/hate relationship with Tkinter and IDLE.
> On one hand i find them to be practical[2] and simple[3] and
> on the other, i find them to be poorly designed and
> unintuitive. And it's a real shame, because, both of these
> libraries have tons of potential, *IF*, they were designed
> probably and the shortcomings of TclTk were abstracted away
> behind a more Pythonic interface.


I fully agree. Nevertheless, what I miss more is the lack of more
complex mega widgets - scrollable list of widgets with insert, append
and remove methods and perhaps a spreadsheet like widget are two big
ones. There are others smaller, like a single scrollable text with two
scroll bars that hide when not needed, tab multi-choice container, etc ...

Unfortunately I rarely need gui programming and don't have the expertise
to address such task. Being tk so old, I wonder why no one developed
those expansions - continuing tix, for example. There are some
implementations but they seem not being maintained.

Pmw has some of the later, but it is not much stable for python3.

Thanks for responding
Paulo
Christian Gollwitzer (12-07-18, 09:11 AM)
Am 07.12.18 um 03:00 schrieb Paulo da Silva:
> Ās 21:15 de 06/12/18, Rick Johnson escreveu:


hahaha...
I'm using Tk from both Tcl and Python, and to me it seems like exactly
the other way around. Tkinter feels clumsy compared to the "original"
Tcl/Tk, because of some overzealous OOP-wrapping. "grid" is a good
example; in Tcl, it is not a member of the widgets but instead a free
function. It can take more than one slave, so, for instance

grid .x .y .z
grid .a x .b

creates a 3x2 grid of widgets with the lower middle cell empty. No
fiddling with row and column counting. For some strange reason the
Tkinter designers decided that grid should be a method of the slave,
which makes it feel much more clumsy.

> I fully agree. Nevertheless, what I miss more is the lack of more
> complex mega widgets - scrollable list of widgets with insert, append
> and remove methods and perhaps a spreadsheet like widget are two big
> ones. There are others smaller, like a single scrollable text with two
> scroll bars that hide when not needed, tab multi-choice container, etc ...


These widgets do exist for Tcl/Tk. You can use a tablelist for both a
list of widgets or a multi-column listbox



For the spreadsheet, TkTable is another solution which is more close to
Excel:


"Tab multi-choice container" sounds to me like a ttk::notebook widget


Another handy extension is TkDnD, which brings support for native
Drag'n'drop, i.e. you can drop files from a file manager into your
application:



- not to be confused with a cheap substitute
which only supports drag/drop within
one application instance.

The "problem" with these pacakges, they are written in Tcl and/or C, is
that they are not distributed along the Tk core and consequently there
are no well-maintained Python wrappers availabe. In the Tcl community,
these packages are considered "essential" for more complex GUI
programming. So instead of complaining about lacking support in Tk, the
Python community should do their homework and provide wrappers to the
most common Tk extensions.

Christian
Paulo da Silva (12-07-18, 07:29 PM)
Ās 07:11 de 07/12/18, Christian Gollwitzer escreveu:
> Am 07.12.18 um 03:00 schrieb Paulo da Silva:
>> Ās 21:15 de 06/12/18, Rick Johnson escreveu:      ....


> So instead of complaining about lacking support in Tk, the
> Python community should do their homework and provide wrappers to the
> most common Tk extensions.


That was what I did. When I referred tk was in the context of python.
I left tcl/tk long time ago and by that time the problems were the same
as tkinter's today, not to mention the angels sex discussions/wars about
which oop paradigm to use or if use any at all :-)

Regards
Rick Johnson (12-09-18, 01:27 AM)
Paulo da Silva wrote:

> Yes, I am aware of pack. Unfortunately the code fragment I
> posted is a very small part of a larger widget.


And i figured that. But i wanted to make sure you were
aware. Sure, pack is only good in limited use cases, but,
it's one of those feature that can save you a lot of
boilerplate if the know _where_ and _when_ to use it.

And while some folks are in love with w.grid(...), it can be
a real pain sometimes, and not just because you have to be
explicit about the row and column weights *AND* the cell
stickiness, but also, because you have enumerate the rows!

In my initial days with Tkinter's grid method, i would drive
myself bonkers when creating complicated grid layouts
because, the consequence of adding one new widget in the
middle of a chunk of code that is creating a massive grid
layout, is that you'd have to go through every downstream
call to "w.grid(row=N, ...)" and increment the row number.
Well, as you can imagine, one will grow weary of that
tedious little chore rather quickly. Now i use a itertools
counter and let it do all the mundane enumerations for me.

rowcounter = itertools.count(0)
w1.grid(row=rowcounter.next(), ...)
w2.grid(row=rowcounter.next(), ...)
w3.grid(row=rowcounter.next(), ...)
w4.grid(row=rowcounter.next(), ...)
w5.grid(row=rowcounter.next(), ...)
etc...

Now i can insert a new widget anywhere i want, and never
need to worry about mucking-up the downstream row indices.

But, there is also an argument to made for _encapsulation_.

Oh, indeed!

If your layouts are becoming too complicated, then it's
probably time to extend from tk.Frame and start packaging
that random.scatter(pile_of_widgets(name="Legos")) into
larger "building blocks". Which, not only offers the
opportunity to create a nice interface for a related set of
widgets, but, it also makes the layout code easier to read.
It's about creating abstraction layers..

> I fully agree. Nevertheless, what I miss more is the lack
> of more complex mega widgets - scrollable list of widgets
> with insert, append and remove methods and perhaps a
> spreadsheet like widget are two big ones. There are others
> smaller, like a single scrollable text with two scroll bars
> that hide when not needed, tab multi-choice container, etc


I think most of those widgets already exist, but,
unfortunately, they are spread across multiple packages. For
instance: some are in obscure corners of the stdlib (see
idlelib); some are in the Tix package; and some are just out
there like some burned-out old bit-rotten spector, haunting
sparsely-populated regions of the internet...

Unfortunately i find Tix to be a total headache. It looks
like someone tried to do a good thing there, but, the
documentation is not good and, i find that the Tix widgets
don't "feel" the same as the old Tkinter widgets. They seem
to require much more work than should be necessary.

But, the worst part about Tix is that it makes the same
mistakes that Tkinter makes. For example: Why create a
scrolled window as a whole new widget? Why not extend Tk,
or, better yet, make a new widget called Root, and then
extend from that and make a Toplevel that -- surprise! --
will have a scrollable capability by default.

But that's just the tip of the iceburg!

The things about Tkinter that really grind my gears are the
little things. Like why in the *HELL* do you need to create
an String/Int/Float var just to get/set the contents of
certain widgets? Is it really that much trouble to add a
get/set method to each of these widgets? I mean, really???

"But Rick... what's the big deal about Tkinter Control
Variables? I mean, it's a good way to reuse code,
dontchathink?"

Oh sure! And it's also a good way to introduce fatal errors
into your program, just so you can get or set a value.
That's really wise... dontchathink??? Of course, there are
"legitimate use cases" for Control Variables. But
setting/getting the value of: One. Single. *WIDGET*! Is not
~one~ of them.

Other gripes include the Tkinter Entry still not having an
undo/redo feature; there is no concept of application
windows nor any ubiquitous way to handle documents; there is
no support for opengl (short of the ancient togl widget!);
there are no native scrolled widgets (you have to roll your
own or use Tix or idelib); etc... and i could go on and on.

Hell, i forgotten more about Tkinter deficiencies than i
could ever remember. And i'm on no way suggesting that
Tkinter should grow into another massive GUI libray (a la
WxPython, or the like), but what i am suggesting, is that
the *CORE* widgets of Tkinter (and *ALL* of idlelib) is
~long~ overdue for a complete re-write that will present
these widgets with a unified and intuitive API.

> Unfortunately I rarely need gui programming and don't have
> the expertise to address such task. Being tk so old, I
> wonder why no one developed those expansions - continuing
> tix, for example. There are some implementations but they
> seem not being maintained. Pmw has some of the later, but
> it is not much stable for python3.


To be honest with you, i have no idea why Tkinter and
idlelib have been allowed to rot for so long. I know Terry
and some other folks have been working to rectify some of
the old warts, but it's not enough, and it hasn't been
happening fast enough. And even though i know that these
libraries are not used by a ~majority~ of Python
programmers, the fact remains that many do use them. And
being that these are stdlib packages, their continued
existence in such an abysmal state is an embarrassment to
the reputation of this language.
Rick Johnson (12-09-18, 03:44 AM)
Christian Gollwitzer wrote:
[...]
> hahaha... I'm using Tk from both Tcl and Python, and to me
> it seems like exactly the other way around. Tkinter feels
> clumsy compared to the "original" Tcl/Tk,


True. But it's not fair to judge Tkinter from that angle.
The TclTk folks are all about brevity. So, python's
verbosity will never measure up to that standard.

> because of some overzealous OOP-wrapping. "grid" is a good
> example; in Tcl, it is not a member of the widgets but
> instead a free function.


Oh, and it's not just grid, either. It seems the "Original
Gansta's" of Tkinter took the Misc object and proceeded to
open-up a can of heavily-salted Reductio ad absurdum on dat-
azz! Hell, they threw in everything *INCLUDING* the kitchen
sink!

> It can take more than one slave, so, for instance
> grid .x .y .z
> grid .a x .b
> creates a 3x2 grid of widgets with the lower middle cell
> empty. No fiddling with row and column counting. For some
> strange reason the Tkinter designers decided that grid
> should be a method of the slave, which makes it feel much
> more clumsy.


And while i agree that placement methodologies should never
have been implemented as methods of the _child_ widget, i
don't agree that a free function is the best solution. The
best solution (for me) is to have layout objects which
handle that short of thing. For instance, it's plenty easy
work to take a Tkinter.Frame and use it as a pseudo
horizontal or vertical "LayoutBox". Here is code to produce
a horizontal layout of 3 button widgets:
import Tkinter as tk
from Tkconstants import LEFT, X, YES

root = tk.Tk()
hbox = tk.Frame()
for x in xrange(3):
w = tk.Button(hbox, text='Button'+str(x))
w.pack(side=LEFT, fill=X, expand=YES)
hbox.pack(fill=X, expand=YES)

root.mainloop()

But, because padding is implicitly tied to individual
widgets, and individual widgets are incapable of "seeing the
bigger layout picture", when it comes time to start using
padding, you get undesirable results. Consider the same code
from above, but modified to use padding:

import Tkinter as tk
from Tkconstants import LEFT, X, YES

root = tk.Tk()
hbox = tk.Frame()
for x in xrange(3):
w = tk.Button(hbox, text='Button'+str(x))
w.pack(side=LEFT, fill=X, expand=YES, padx=10, pady=10)
hbox.pack(fill=X, expand=YES)

root.mainloop()

Now, if you look closely, you will see that the padding
_between_ the buttons is twice as large as the padding to
the left of the leftmost button, and likewise, to the right
of the rightmost button. That's not what we want! And heck,
it may even qualify as bad GUI-juju. But folks, that's what
happens when control over "big picture aspects" of GUI
layout is given to children, who, cannot see beyond the tip
of their own little noses.

> These widgets do exist for Tcl/Tk. [snip: list of
> extension widgets] The "problem" with these packages, they
> are written in Tcl and/or C, is that they are not
> distributed along the Tk core and consequently there are no
> well-maintained Python wrappers available. In the Tcl
> community, these packages are considered "essential" for
> more complex GUI programming. So instead of complaining
> about lacking support in Tk, the Python community should do
> their homework and provide wrappers to the most common Tk
> extensions.


Personally, i would go a step further than that. Not only
has the Python community _not_ held up its end of the TclTk
bargain by providing wrappers for these "advanced widgets",
we have failed to create (after all of these decades might i
add!!!) a clean wrapper around the *CORE* TclTk widgets. One
that presents these widgets in an intuitive, consistent and
Pythonic manner.

So, at this time, I would like to propose a complete
restructuring of Tkinter/IDLE/Tix/etc libraries, and for me,
i would like to have one basic *core* library, and probably
two or more extension libraries.

(1) The first level would be the basic set of Tkinter
widgets we have now, except, highly polished and feature
rich!

For instance, there is no reason why Text, Listbox and
Canvas should not *EACH* have a constructor argument
named "scrollbars" (or whatever!), that, when True, will
inject a frame into <master> before packing the
respective widget into that frame along with scrollbars;
linking the scrollbars, and then dynamically adding some
instance methods so that clients can set the visibility
of these scrollbars at will. The beauty here, is that,
except in the case of some code monkey deciding to hard-
code a node-path to some distant ancestor widget (which
BTW is a *REEKING* code smell!!!) this would be
perfectly backwards compatible.

Another sore spot for me is the complete lack of
ON_CONTENT_CLEAN, ON_CONTENT_DIRTY and ON_VIEW_CHANGED
notifications. This is not 1993 anymore folks. In the
year 2018, every widget that has editable content should
expose a callback feature to notify clients of these
events. And sure, IDLE has the WidgetRedirector which
can be "borrowed" and utilized to catch modification
events easily enough, but, why the *HELL* has this
module not been moved to the main Tkinter package? Not
to mention the much-needed-hooks added to the Text and
Entry widgets? All it requires is the movement of one
module, and few lines of code in the Text and Entry
classes.

Entry needs Undo/Redo capability. Sure, you can extend
from Text and monkey patch a few methods to strip
newlines from the inserted value, but, all that extra
baggage that Text brings along seems excessive if all
you need is undo/redo capability. Besides, it is
inconceivable to me that any editable widget would not
have a undo/redo feature.

And i can't tell you how many times i've had to explain
to the noobs that root.quit() doesn't do what they
"assume" it does. :-) If ~only~ the Tkinter designers
would have chosen more intuitive names, like oh, i
dunno.... "start_event_loop" and "suspend_event_loop",
then perhaps -- *PERHAPS*!!! -- by some stroke of blind
luck, we could have avoided all these little confusions,
for all these ~long~ years.

Oh, i could go on for hours about the deficiencies of
Tkinter. But, for now at least, i'll stop this blathering
and see if anyone else has war stories to share or nits to
pick...
lizhollinshead5 (12-10-18, 09:26 PM)
On Thursday, 6 December 2018 07:02:50 UTC, Paulo da Silva wrote:
[..]
> app=App(root)
> root.mainloop()
> Thanks


Others here have commented about Tkinter. I'm not a professional programmer, and I struggled with Python2 and Tkinter for a while. It worked, but it was a struggle.
*
A few years ago I started using Glade and Python3 (and gi.repository). Much easier, much less Python code, much easier to maintain.
*
Not that I'm much of a critic of Tkinter, just that the alternative is simpler and easier.
Similar Threads