Αντρω δι Νεξυνω

Esempio 01

« Older   Newer »
  Share  
view post Posted on 24/8/2020, 13:06
Avatar

Nubbio x Sempre

Group:
Moderazione globale
Posts:
7,226

Status:


Esempio di gestione "Bottonica" in tkinter per trescon - procedura per serializzazione di icone e tooltip associati

png



Codice supporto : risorse.py icone utilizzate nella applicazione

CODICE
# -*- coding: utf-8 -*-

icoadddir = '''
iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAAAXNSR0IArs4c6QAAAAlwSFlzAAAJhAA
ACYQBquJjeQAAAAd0SU1FB9sFAgwBIhOliHYAAAAGYktHRAD/AP8A/6C9p5MAAAOwSURBVBgZBcFLiJ
3lGQDg5/3+/8wZTewYDeYmaIOY1ES8LtIWRFDblOKiIBYvCxci3Rm8rFzoThFRIuomG6ltF8FNwRYEN
SCtLbaFQQitlzQQTSYmThJn5py5nPN9r88TAAAAAAAAAF7xS1d47tZdt95ZlDJ/Zv4/bam96BnvOQoA
AACAB174KwAAr3t5z5/35DsLv29HTr6ZR06+mX9c+EPb/97+dNhbEA88/5e/T6qfdUFCEmhSP+gvvfv
8wS0A4LC7h9cMjz3z0yctXzjp8G1HwaH5B12xZbdXP33D+JvR/XHw0Dt5zy9+JbIqEIhQSvHhsU+ymx
lEIJOZHPpo6yHd/rN5w9ps+P60vz08BXf9qZdzu5zcNMnTXyx80q+Ol22sjf331CUZoaC0dN32WXcdu
CWmmUAyzCsdHX/GCXH2iQQAHz88BXEkwma396PlRePVsfW1ka4EWMeXp8YmmWSSKTCoy+zFdwAAABjh
KvqN0ZLRaGyyNtJKWGtAibC6vuriua+troxMpWEbmpnbaeO6M2ZfCxunaa8kiKfD7LW4HhP/6qfC/09
85fS3iyggktSMli548ne/sfv6nRJF8dEXl3mpf1z5MZsvA2DuRja2YcgjKy/s6e88cMDjD91neW0iAB
BoGc6cXfLZ8XMSEWHr5G77zt7r+E0fsES8HMA2bObmrw8afr5jWz8aV5/On1NrkyiIYJoMChlkFAUN/
Ux4dMth7x973b9vfNfKTxbB5ZeuduAfv3X/nqfMlw/0KWUQkSCR6IJpIiElAuvoLh/69R3P+vk3j7r4
v2+VCFfu3G5u33aTvtBSH0km0xa6oKJDRSCTDApaEkFKtfGjXTts2rUDlKS2ptTQ0EO2JFNNYIqAoKA
2pgiUZIqCWlMX1GSKDpmptdS3JDNNswlAoCKSgoZARUWgIpDJFB0qWhaZqZepNTQSGWRSANBQkIigJh
0KJoBERV/IpC8llK4XAvRIJALQI9EDejRUDAANPbrSiQj98VPf+XLxnyIbaEE0FCJJAAiyUQqZQCIQS
ER0lhbO66/aNGPz1XPURgCQKEFLApISZNAaAkFJGgoSXddzfkO/+9qtbtm3V2tNh9qIQjQqIDHoqJVE
V2gNyEIgkA1d50Sc0a+MJ2vnz38/u5Fp0LFe2YRayCSC9UYXRBDJIJkWEoFpQzAIahSLF5ZXgi032Ln
3MaWFVMhChmwFIbMgZBaSiEQjmpCiVCKJRiZdurjwNgAAAAAAAAAAAACAHwA72MYv6XXC8gAAAABJRU
5ErkJggg==
'''

icoaddico = '''
iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAACiklEQVR4Aa3TA4wkQRgF4NmNsbZxtm3
bVnC2bdu2bdsM1ra9OzbfdXW2k8rcdPepkjeeLy9V9Uuo5cek1z/GX+Jg9TcajTaLxQIuZrP5t0N+zx
iDHMLkB2Xl5SivqEBlVRWqpFJIZTLI5HLIFQooSJRKKElUKqioWK1WAg/mhSsqK1lUyqA0SDAWUauhJ
tFooKEiChOUbsmBBGMRrRZaEp0OOio2m00Y5lC2ZXVDAhKMQ/R6PfQGAwxURGEWJXtItWTbURhzyDCZ
THTEYa4pizItuYZ8IHcrRGFHKA3yXTVRmNtTIZRA9gEgDHN76giloVx5FuZ9mIBFnyciR5EuDrOnX72
njlByX0mG3e2FfGk+citzMfPNcHGY3QLuoHhQsp91jwQjuiSaTberdcUHhG7L7SmNVlRWIDY2FjV2B+
B17ismr9H+TC2UlJTA2dmZH6b3lm57P+U+GhysD+8NnghY7436O2rgTvpN3GXS6URDdDxXC31uNMC01
30Nu+LmbfkFpu8r3bbG/ho4G30WR6KP4HjcUZxJOI4zSUdxLvkYLiSdxPmEU1j6fgk6nO6AKR+6GWi4
HwcT1B722OiBWU9mYfrLaVjyaQHWfV+CFT9mYPH3SZjxYQTa3aoH/+OeCNwbiKHPG/PADvZ37bO1cJ/
tDrdpbnCf4YbwxaHo/6wRRr9tiaa7aqHR/hC0PhWJztdqGno9rrnZHna4v9xNIK8LCgogk0nhweCDXz
TB1G8dELnZHxKB1Y8ZDhvTmDfMVbTl5+fbrt+4XuU2zRVt79TEIAYP2+IrCAcyGSwWJycn8tzce56ns
faJGqh7qgYidwcYJP9r1d0VsiVgp68h4lCQoeGZkC323/8Ef+Z3Qv4MtAEAAAAASUVORK5CYII=
'''

icoannulla = '''
iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAADbUlEQVR4AY2VA3BkWRSG37bGngnHtm3
bM2WsbXucUpzi2rbDRuwX27atf/8bp6dfulP1VS6/Pn3POdUSgHFpunHDvt3be2P3118fF7R7eW1sev
99e2v3LC6WHD++L+LIkZ/9Tpyo8T1zBv+ePo0/jh7Ff8ePI+LCBchXryLx4sWqpBMnfhBnbRLrV6z44
Y1583B77lx8vGABPlu6FF+sWoUv168XiHH/2qfc+9jBAd/zf8SqVd+OK061s7vwKqV3Z82COy958JIn
Jd6U+VAqEGOxJvbEGbfZs/GhszNS7OzOK4pDJkx4+i9efpcX33V0xPu8fIPjW5Td5rpAjMWa2BNn3lu
yBP9wPWTixIcVxXq1+mosI5B37cInhw7h7u7deH7zZjy9ZQue27pVIMZiTez1n4nhWujkyQhSq88qio
0azYmIqVORyOfIZ2TVx46h+aGH0Pjyy8h96y1kvfEGyh9/HEWXLyOJUYbyLIPph3cPKIoNWu3uSB5Os
rND9qJFKFmzBvXbtqFx506UrVuHbD5BEt81csYM6LXaYamB8O5m5afQ6dYJcTLFeXy7SspaKO3YswcV
a9ciZ/FipPFdYyk2aTRCOEyQJC1TFHNzkSVxBb9+T0MD2svKEMk3tiQOlCR7RbGvJM02F+ft24eexka
UvfQScm7fRpUs47ft22E0E/8lSZMVxbGSpDUX5372GZr0elRxLG/ahE5+iOnVV8dEbFSre612HsWdQi
wvXIiYDRuQdeAA6tjOtRs3omD5csTwjf/le/9w5MhocaMt4hohDmK51RcXI+Ptt0Xy+sWFFIvkmV54A
SWpqfh9JOoS6+IpU/KF+K8VK9BWXw+Zkd0nnjsXtSUl+IzfpF+s0aTbEnGSEP/GaiiOi0MOm6SWHVZB
cf6yZTBduQI/Ji/TZMKHPCPEJNoWcbgQ5zB5+ldeQVNeHrpralB+4wZS2OrttbXI8vXFH88+C/+RqtD
bIv5jdFWIzmsmVUyYSJ6JrWyhjn+0Kg6bPPksxb3mnTfqjc3FvYEazWmrYsFfi2efTFu6KNma2FerSv
5ituak0i+IIp/sWbhW3rPh5cx9W9zTtq79Kmb1kq/8F9m5/+I07WUXZ2mt1d88/qnJZDKHOJNlZD3ZQ
Q6S0+QKuU4ukpNkP9lG1pKlxJHMIDrywP8Xx1KfJQFl7wAAAABJRU5ErkJggg==
'''

icoaset = '''
iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAAAXNSR0IArs4c6QAAAAlwSFlzAAAJhAA
ACYQBquJjeQAAAAd0SU1FB9sFCQAPJyNXLxIAAAAGYktHRAD/AP8A/6C9p5MAAANASURBVBgZ1cG9q9
5nHQfg63v/fs9JoqUWq7SauNhBMdXFoo1Z6yCIgwila2cnx1BQHPwbRARXO9YX1MUWLEip+FoxaoIkw
WJ6mpPTnpyT87zc98cnPWi2gjp5Xf7/PP2NH3k3z3zzx/4bZevpb734g81y+cUkw7+Vxc58+fnnnnrc
f+grX39B2frSpRdy8cKTMjaqaEWbJi/+4hWLnVO9VUvJwOiMKZKWIRnUGCNpjUQtFovLzz/31OdmW4c
H+0Zf+dONt0wT6Tz26HtdfOKTRmqKrdAT94xBz3DPCBJjUG32u9++euHZb//6fbOto4M9d+8eOz66Y6
oy8NrfDjWlMFAVSQmqaEiRQRUSH3z4AYcHtx3d2huzrcP9mw4P79qsjvU2yaCKgWarGJ15pneqvCMIW
tH7sDpeONy7aT7/ZJ9tZbO2u7vrD6/83Bi0YqAhKBSGraAoJ6pIKPH3Bx9w8PYtH/vCp9azrdV67eWf
ft/Vl77jf7U4d8H5x4z5h0n72ue/6s7h2+7Zv7WnpqaqObp77NXf/8WN198wDDQnhsSJRGyNOHf2wzb
LlS9X9eLS9IFPX928ufuG9dWfuXbtuqrJGMOvXrvi1vyIhx/5EEW5L2hF4r7i9OkzuXb1yrW69L2Xr3
/2M+fPrZfrGqH3QVHKNE/29g7t3V4qESfKiYHmRCkd8zz74y9/Yr585fWPPPTQozabjX9pWKMNhjIVV
QxMGBiY0NHCqAhaykiZE/qgj9LQUUXiHYV1mEJhU2zCDtZoWOJ0WGGV6CPmJDIwohcJQSt66JgQjKIG
QQphjRkbDLROD3PQR2wGVQQT+iBIEXTUIMWE1SBoxSa0IqGPqDA3zK2ZFrEaNMzoGFggRULHjHIi2EE
a68EkTM1czDdv3/HSb/6s90GRsCiW4UyxivsKQTHCTtHjRNHDYlrYvf4P80fPvt8nzn9c6xsJAxMGpm
IdqkhYYI0ZA4tiGVoxwg76PPtr3TAfHK7y1v5RjQwSrZq5WIbgVHEXZ4rl4HQjg6UTO2FZvKfx5iYeP
DXZ2z/odfbiM08cL/Ps1FRRSar3UZKamrbpMVVK0zLcE1XJkDZVwmhViUpVZUTSV9/9J3Vs2NCwiBa9
AAAAAElFTkSuQmCC
'''

icocambiaico = '''
iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAADrUlEQVR4AbWVA7QjSRRA17bNsW3btm3
btm3btm3bnomddEc/d6v67O/v9eacG/ftV1UPLwH/C/ob8fhOkPtf8l1i4lyKouJyuXG7BR4PHq8Xr8
TnwydRFJTYqKpOMBhEOhIT57Y7nDx/YcBgNGIymzFbLFisVqw2Gza7HbvDgUPidOKUuFw6Ui4diYrFH
4TUJKUJhb+LXBK3viod1e9PWiwvEFEKzNy9fp7da0ezcHglpnbPzdyBJdm6sAf3b56X4ugt0rfJHwjE
Fc8fVnvCkEbfZ5dfyjtfObOPse0zc2BRBW7srYPpanMUQyfsd1py70gdjq+swJzeWTm5e562fFUSs8c
x4qWD87BmTK5I56pfb1g5pTlLh+fDdr0VAUvS+J51YP+8kszsUxSvx0UgECAUCsUVL+6XGc/9VmyfUj
RyZm0NfA87oDxu8Rdoxf0DtRnfOi2q4iMcDscVL+idAfet5rhvt8B9JwbXraZYDpfm+bqMPFmWkufrM
2I5UBr3zeZ4bjbTubimDPMHVyEqKireHvdMi+NqUxzXmuG4IRB/Np+vxt1V33Jt9rscGvYe67u8z64e
b3Np6Ks8nPUF1sNVcV5opOG42Jgl/bJw4+yuuOK53VNjudAAy6WGWK82wnC2Arc2fMTZBR8ypvnXLBr
biN2rx7JoTFP610vGxs7vcmfsa5j3VcR2vLbG073V6VsnWVzx7C4pMZ6uiel8LUyXa4t9+5W7+z5k1e
BPWTG5lXbaEnk4krXTu7Cz53s8mPYJpr0VMe+tpDG+VYq44imtv+Xhjmw8O16KFxcrYbhekWdXc/Dg3
OfM6/kFT+5d1ITycCShYIA1E5vwdHk+DFsqYdpVA+O28qzunzGueEDtrx/MaPsZszt+zvye37JkwM8s
HfIjy4d9z8KBn7JrZVtdKg8oEolwbMsUHmxsjHFnE8wH2mLa3Yjjs8sm7BXtSyd78723Xivg9bhx2Ew
47Ra8Hiduh0VEGIyW6uKTe5dxfEUXzq7tztmNg7mwYzwH1o13CvEviZa0LEtFUWRe6vsaP1rJlpVT9f
fy+0tnDgZSJPslu/QkKpYVJKV+xS1fpThBtDbTEw5tX6xLL184HcqTO0t+6fgTsRfV5yQQ8OtRa1JBQ
PVieHSJE/vXoUkvng0WL160pC78s4hjpJKA2GfxOSC2x+/CabrJ6eN7uHj+tJo7d9Z8f2U05ZLLjrev
Avkqog4HCIcUFI+BQwd2vkiRPFnm/2Pm/fBnw/Q3Tixj9W5FyYwAAAAASUVORK5CYII=
'''

icocancico = '''
iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAACm0lEQVR4AaXSQ5QdaxQF4HrWvHH1NH5
mc/QY27M40zgZxp7Htm3brr62bdfO+W9urVVdqfa/1m5cfLXrnOIkp5bydx9Txymcfvl8XigWi+hOCi
yFghiw737xxReDFGH6guDz++EPBBEMhRAKhxGORBCJRhGNxRBjiccRZ0kkkJCEcAYP7hAOBN+iYUJFU
MQqSDKJJEsqhZQkXcLyliLIsAqSTiPNkskgIwl9t3NYRGMMZQ2rIMNEJJvNIpvLISdJl3CUodUZJkWU
gQyjEMIWJV0cS9dwO7TaUgEUMTFdw0oogcpYT2Dx9jtDS6WSPF3D4kyVUAakLRZk7HaUy+V2ydhs+Pf
jj0d3CFe2X52pEupcshim6dORdTggCEIlWbpQ2/jxME6bZrzJcVpFWD4CKepasRyRA/sQ2LwJeoIYnr
FawY8YAT1d7OWkSXja0MBwTTuYAEFsK58pa8UT5t+0Eb51a+FbuQL8qFF4PXw4bITyQ4fg1YQJuP/DD
/wNjlO9Ayu1ZWFzZA1fEOZfvQq+ObPgnzMb3hnTYR8yGJYJ4/Hg11/5yyIqh1lbOcxQcZ7me3fxfNw4
hBYuQHD8OAQGDYSPmj5sbm47x1CF878IE6oIs9+W+/fxsLUVnu+/R/S33xBtaEDg779x59tv9cc4Tt0
lzFA5nKRF3Wpuhl6jgfODDxCuq0OkthZu+tugUuHKN9/oDxCuCHc03xQt73JTE+7qdHj68ccwE3pZp2
u7pNHoLYQ+p9fu0e8zX3+t3y3D/6dnuEyNBaVEjEbhbEODcEWtxl1CT+t0/E6a6S5CTqpU+vt0F9fov
WM6nX6XDFZTBnWW3zhuzEG12nhYq+W3SBa1lb57sK5Of4jab2VOb84GevgpKoXX1Rsk6Bt2BH2zvcb1
9wAAAABJRU5ErkJggg==
'''

icocset = '''
iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAEmUlEQVR4Aa2SA3AkWxSGb0+PETuLyWz
WiLG2bdu2FdtZm7G1tm3btvm/s4OqrrzSw1/19dW536AP8/LyYv9n9tSXGyYLmRML9LbXJrnLLyVVZU
j8lyQRyW6yi3GeFmXPNGGGJLorrhZMGvz7dGomzqRl/StOp2SiaNqI34lusmvMlMSaPHaHR2F7QAC2L
1z4LwnAoeSlSKwpBjMlin5Gyay5KJw61cCUKcidOBGFkyYZ90pB53RmqKG5aW9PRDQiq4qM4p3gQisz
5Iweh6zhw5E1dCjSRozA5evXkR8WhoxBg5A1bJj+TA/NM4YMQX5oKK7cuIFUqqU7+v1t8xYiuApvFAd
AtKAiQ2rfgdjUqxc29euH+48eAZQvP38ic8ECbOzaVX9G6OeZc+fi848fAOXhkyfY3L8/NvXsicLJ0z
C/kukbDwQ/i8Tr2nXEqjZtsLxpU1zMzYUpX3/9Qsr06VjZvLmeFPrJ9IEw5VJBAVbQnVWtWyN7+CjM1
DGjeOhByRQSL6vfGEvq1cPiunWR4OGBs2lpEMrXjx6NdfSzhdLzmZn6WrqjJ613P0wqT+IfIHHvzdJx
FRgS3TwR7+ZmoFYtRLq64tSGDTDlG/30r4QpZ1JSEEE1cVQbT0RXqYKsgYMx2pnEEeAY67ZGNqKCCFE
urghzcdETTkRotQiztcXJ5ctROsdXrcJCa2sEOzoiXKfD5j59sLpdO4Q6OmMkudiUVzxjnRPlg3Ucgq
1sscDGBoFEOBFH0gQzM2TTyyydjFGjsKphQyxr1AhJvr6YwBimEjOIIToebPAGCX3jIGVfnQQBGnMEW
FggzskJyytVwsZq1ZBPrfYTf4t+b32HDphLounENOM4k+irJfHQVRKm7hGg6l5eijBLG8Ta2yPZ3BxL
qCCbLn4XyK5GR+MS9bVQvql7d8wrJe5Wloe6Z5KM2Xeeo27jzCOEcYgRifTSvM6d8U0gvZecjGLazyd
uxsXBlB/EBurrOUb5LKIduWx6zJGzsh0mmDd1FCGWibBYLMZ6jQZfBdLHJD1EF44qlTigUGArzW8J5L
+IMJUKM43iFo48tD0mKZiu41iLuvYckjkeK0mcyvPY5+kJCp4uXowzVHyFLl5Sq3GOOGyU34yPN7xI6
uNwxjCX4/TihvYiVO00Xsmqd55g6WXLYRmJ10kkyJHJsJ3G09Sj56nwNv2CR9QdD4ibNCc5DpK8kM7y
qSVXkDCWvsxCGukvgb8Nh+odx6qZR9fpFrWsGNZKxdggkSJXKsceuQKnlCpcV2vwjLrlvbkF3ppZ4KH
GDJdUGhyls+1UkyGVYZVYgjgSB5B4AYm9rDl4D5ivZA02f+arW0mezXLif+8tI8EZrRS3XOV4VlmBzz
VVgIca8NYAnjS6qfC+uhKPK8txRSfDMeqmHc5iZNqJsJKEI6y53zWtpU+YKW6uugaVLKQvtGqG8kQ5A
WWVAgT7WgEuf1AxVLIQP3XTlfPXS2v5+enH+lM3SvzaD7bzadnTyVeAX6uejr6t+xho0dfBv2Vfhzqt
+9j7telr70/jH+q2GWDn12mMVZeSbyK9s04d9hdFf85lf9K9GAAAAABJRU5ErkJggg==
'''

iconset = '''
iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAFYElEQVR4AY2UA3Rc2x7GT+0+1lip21U
3qoKHa9/Ytu1kXoOJdWPbdia2bdu4tdvv7andzlrbe//++uZQAL6krfhzZohrcqCR3t9SntpUGJ3X05
jnubQ4x/KxN58BUium2xK+bs12mm7KckVHUSCqEmxQmWiNzmJ/1CZZP61Nc+gaasn+5xeDl2vctjelG
DdWRuqih0HHbFMgBkrc0FvshsWuWOSnBIBuYwlvez3UxOjdHiy2O/9Z8HiFw8naOL1btQkm+OMbDgit
X4sUB2UMlntjqSsBC61hSEyIA4PBAM3KEhM1vqiJN3pYn2W1/6PgkTI6a0WkzsO2DBqGkhwQfvAgzFa
uhO7lU888nSfQkUpvDFSHIS0+GAkhtljqjMJgkQOKQtQmPggeqnDdywgzelCZn4C57mQsdkYjQp0Psc
dYkOllgLnmUAxWeGGxIwKLbRFY7o4ixmLIfjDGqj3Rle+IsnAt+lvgxWaPDcXhestFmQno7m5HdUUB2
vLcMVLlg4X2KMw2BmKo3J3MQ7DYGorlriiSlkhMNgRjutEfiz1xGCx1Qoan9F0Bilr1Clwbp9tZE6OD
vhYGamvKsbAwj8TYkGfezNZ7oa+IjoUmb8yR+WJbAJY6wjDREIjxKlcUB25CCn0j2tLNUBKqitwA5V3
PoO2ZJpJlYeqI83HGicNy+Pe/pNE/MEDgC0gMtUZv/v8wW+eG2RoXLDQSr5v+IJF4YrI+GPPtwWhI3I
me9O2oTzZGZYQ6AmhCUpSAALWqKFhloif3Gn78xRM8totYdUwOWgp8yMvLQ011NSoSLDFT5YT5BjfMk
TZYYI1RAl7oTsFMYzhKojXBCFPFSLEtigOUYSjBJULVRBkcIN6Sy9fgZqyGf3wdgeNXpeCs8xMU+K/A
Qk8FFiqKKAzVJ1BX9DNoBEDHfNvz/A6WeGCo2AEjRbbozbYAw1cB37EfOEmVRuvylgQroyFOF82pRsj
zlke8s8T9DG+lm5HWgjBR+BrSX3PBxcwY15S+etiYbIjZ5iBMVHqgv9AJQyXOGCaGerOsUBejjRAa39
2T27ZtpoqD1MSzPCTRkGJEwGZIdZN4snfH1u8pijqX4yN/pyxCAyoiVx78wsF63cXC7ImxzH87Rsscw
cN9Gf/hYkNnngN6iKddaabI8pSC1Penosjb1VSoFd/VLE8Z9BXaoihACVZKPHXkYC1pa/KDlMdKSZUr
4wyWDu3bRhflvToa5aJ2vT3VBBcunMdXX30FHs6T6Eo3RXmoOmiKPDNHj+7dk5CQsIr6iXX3xhxvuce
loWrI85HDpZPbBAh0JWmrGIHKU/l+shgm+Ruu8sJQkR2Y0O4McyiKfIUTxw7DzYifyE0J/qY/PziwYw
sX8x2A9RTTbV1x1qQcb1mEWvNfJ+utAJ7tF4eq3SCKgbDZFfC6s8GF9js6SMiduXR0p5ujk8ir0F8e3
kbfPzyxZ4sSM8q3/tLk97erZ3eZ7dm+hYfpLQBK8OTJtaVh6vcKwrRwWuUgDqvvAOe3B9CZZU1CN0Nj
nB4y3CSgJ8o5t3/bBmFm+gBQ74JXMEN4CWW27747so4RrHaX4acIWUlO8P54BGWRes/UU+SvAD/T759
cPXlgTOyXn+9/f+nSqS/+HrOyUmvCbYVrU51EUR6iigqi9XxSg3i6ALQEz46zbF8vuXn1am7eM6f6VI
QEJn5iZd34RWBmFGcO/O1AtD3fzSxPSYTRfnkszMvSdGz3Jq3166kDzBq8uLef99zpJIXff03/EvBL+
Cqiu5P7dm3mW72a4tpCUf9gAplG37m39vyhQ+pfs7LyfRH43fy/C3y3bdu0aefL+f8B2ey4mWSPqRYA
AAAASUVORK5CYII=
'''

icookico = '''
iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAELUlEQVR4AeWTA5RbaR/G39rmoHbv961
tu/YoToZJtmN7pu6gbse2GdTWQW0bcVLl2byDu/bu0f7Oea7/v/uS/DcZ4DrA345vF0jmki7klygpKV
lXUFCAvLy8X01+fn5L6HeFhYWYFjINHxV8BFGjCDbxZuJMOrHClJQUkpa2qceWLWm4f/8+DAYDdDodt
FotNBoNHjx4gHv37uHOnTs0Lc8ePngI9/XuGLtuLGru1qD2fq11WPIwkNlkbTdRt1Y5ALJu3cYJSauT
YX5kxvkr56HVaOlPfiS8desWdFpdS2QbpRifOh45p7ORfiYd6WfTkX8+3/pu+rsgH5KPWXHS6lQmJj4
Oc5PngJfJQ3JFMhWwrb17927LvV6nh1+aH6asnoI1R5KRdGgVVh1YhaQDSeBX8NHFp8s98gkZRdrxDP
J+Y4poKj7Y9A6W7IrF2Kix2FC7AXqtnspbpAa9AcGZwXh++f+RuDsaMTvCEbMtAtHqCEjKRCASoiWfd
niDlY6a59Cpj0ufxteSXkSkOgDBajlClFJMCpmItPotMBqMMBqNiMiJwAux/0fktsUIUskQ2CyDX70P
5JWe6CHpAWbh/90IZWabuONnHfuPXDxS+20V1+pTzYW0gQt5Mxd+jVxMkk9EjjIX8YXxeC6IQaBa2PJ
OZnvnUeWKkDoZBssGYbZgPoL8wph9R5p/shanD4wY6j0Y4rJpEFXPhnvDbHgoZkPWMAdjhGMw1WcS5K
p58FDOhqRxJnhV0xCn8MNAyQDU7KkBx1UIsdibAe4QFgBEIpL+761F72KUzAHi6k/Bq/8EAuVnEG7/F
BLbvVT9DUL38xCyhwNp8yz4VS/AUPEQFCgLYDFbsGgRBwKBBwPgh+LbRCTyYnhcCTYqNmKU2A6c6hcx
s3Yc5jbbohyLWYqReLe8C94o6oTpOY6w49kjR5ELzUMNzGYTOBwRqIO6WDSaq8TTU8rY/gjKkpKlGM2
xxwKFI77a2hfTdvXDtN398OX2PnCpHwv7RXbIVmTTpUdXjE1shlDoCeqgLparV9VEKvVnJBIftBNTEI
sxTnYQHh2JeccHYM6JfhDvHY9hM4ciS5WNx5bHLbuT7kKLxQIPDymog7pY1OoM4u8fyvj4+OKHhOdEY
OycYZDeGA35qUkY+uVgZKoyQXn8+DFMJhPd/vTaJvUDdVAXS2ZmFAkJiWZ8fQPBYkULARmBeFngCGah
AzY1bwb72mptEdLW0mtf3yBQB3WxZGSsJFFRcVNCQyPw5MkT/JSawzXYcWoHfg26eWgtdVDXDzhK4uL
iHeLjlx6IiIhDWFj0jxIZHosIW9hnPwmtobXUQV0/Ijo6oUti4nImPn7ZgoSEZbyEhBVtWf6TrPhR6L
e0htZSx4+kH3zwAaEkJ6d1sHWnc2BgWJewsKA/FPotraG1rOvf5DsN7384pLYHSQAAAABJRU5ErkJgg
g==
'''

icosset = '''
iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAA
CYQAAAmEBwTBV+gAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAALeSURBVHjatZ
XNahRBEMer5yP7lUyMQYjBgBJI1Iirou4hlyB5AR9APUsuBlSIL5B4Ex8hD+DBgwcVvHhRMXoQUVyCo
Pm6iHF3vnqmp63qnWlmdkcR1GKqZ3t6+lf/rurpZVJK+B9mUbO8vPxMRPGsbdty5vhcfezguJUkCUak
oKx3MabcMAz9Gy8wsb+1sx23P7z3JU6pVCufVtfWFhTYd72FTrcLzsgITM+ehNPNs/B0YxMSmQAZo4Z
AoOOkUBMWL07Dq5cv4N2bjTEhBKBPasWccwjDEJJGQ00Yshksnj8GQKI1jGkgUw2gegYWOhmuULsG04
ujjkPRemDLgOqQBdoyoE4LQoGpu0hBODdzDdZRVN5Ago3gJ683gdJcZpJc9kowf2oKEqHVFsDU0WAaD
KMYLsxO0mQNwk4KzFxSppRHiYA4jjW4VHGM0QMuwDSNAZmIzqBaNaflx6RWe7niSAgER/Do+dtCKvLb
XWFT5ZdaczhHkmLsq/ugYrIYo3uo+NyJ6Z5M3YJOTV51IpUwYtCzouJECA3e3d2GWsPJB9OWYgmsA31
jBuzt7YBIlSaGkUtFDvL44QOt7E+NUpiZ0a/4bywvQzBWzPE/smKOqZL9dn1pCSYOT/wSwMMQ7qysQB
AEqoCHxscHT7coirK+Loof+HD75i011sUDavXu2gB8dPQAGEaHCqcZRcUlYM/zIEJVgvY1BnFdt2zdw
NJCE7xSqdDc3ysmEKWIwDzkZeDC+SDxXqvXAQpgBJSBeRypIzXgoUpHv3lhQGPqC2XptjXyuyLm/B4w
dqM/Fd1OF77v79OBr/r9Fng+hD4VT4JlmtDBd2n1jDHTwoY+lftHj0zND48Mn8nYvu/bV65dZdkexb7
+J9GKPRfLENIzVG0Cjzid0i7V1UJ1CcK3Pn/9chkAKgRttVrQbDZnHMepVavVOhalYdt2Lc2rj+nxMJ
Dbbrc/rq+vE4jldyL6j58Q3BDGwSeCEgAAAABJRU5ErkJggg==
'''
setico = {"adddir" : [icoadddir, "Aggiunge le immagini di una directory al set"],
         "addico" : [icoaddico, "Aggiunge una singola nuova immagine al set"],
         "annulla" : [icoannulla, "Annulla la definizione corrente"],
         "aset" : [icoaset, "Apre un set di icone esistente"],
         "cambiaico" : [icocambiaico, "cambia, a scelta, la sola immagine o la sola descrizione di uso"],
         "cancico" : [icocancico, "Rimuove l'immagine corrente dal set"],
         "cset" : [icocset, "Chiude il programma, modifiche non salvate vengono abbandonate"],
         "nset" : [iconset, "Crea un nuovo set di icone"],
         "okico" : [icookico, "Conferma le impostazioni correnti ed aggiunge al set"],
         "sset" : [icosset, "Salva il set di icone corrente"]
         }
         
         
class IcoDispencer:
   def __init__(self):
       self.icoset = setico

   def getIco(self, chiave):
       return self.icoset[chiave][0]

   def getDescr(self, chiave):
       try:
           descr = self.icoset[chiave][1]
           return descr
       except:
           return None

   def printData(self):
       for chiave in self.icoset:
           print(chiave, ':', self.icoset[chiave][1])

   def getData(self):
       return self.icoset
>

Codice di utilità : tkutilita.py - contiene classe per creare tooltip utilizzati nella applicazione

CODICE
#-*- coding: utf-8 -*-

'''
Raccolta di classi ad utilità generale nelle applicazioni grafiche
basate su tkinter raccolte in giro.
Le fonti saranno indicate nelle singole classi.
'''

try:
   import Tkinter as tk
except ImportError:
   import tkinter as tk

class CreaToolTip(object):
   '''
Crea un tooltip per un generico widget.

Esempio originale tratto da stackoverflow, indirizzo:
https://stackoverflow.com/questions/3221956/how-do-i-display-tooltips-in-tkinter

eseguite minime personalizzazioni.
'''
   def __init__(self, controllo, msg=''):
       self.attesa = 500                # Tempo di attesa in millisecondi
       self.lunghezza = 300             # dimensione del messaggio in pixel
       self.controllo = controllo
       self.testo = msg
       # Utilizza gli eventi del controllo chiamante
       self.controllo.bind('<Enter>', self.avvia)
       self.controllo.bind('<Leave>', self.chiudi)
       self.controllo.bind('<ButtonPress>', self.chiudi)
       self.id = None
       self.tw = None

   def avvia(self, event=None):
       self.schedule()

   def chiudi(self, event=None):
       self.unschedule()
       self.nasconditip()

   def schedule(self):
       self.unschedule()
       self.id = self.controllo.after(self.attesa, self.mostratip)

   def unschedule(self):
       iden = self.id
       self.id = None
       if iden:
           self.controllo.after_cancel(iden)

   def mostratip(self, event=None):
       x = y = 0
       x, y, cx, cy = self.controllo.bbox('insert')
       x += self.controllo.winfo_rootx() + 25
       y += self.controllo.winfo_rooty() + 20
       # crea una finestra toplevel con padre il controllo
       self.tw = tk.Toplevel(self.controllo)
       # lascia solo la label e rimuove gli elementi della finestra
       self.tw.wm_overrideredirect(True)
       self.tw.wm_geometry('+%d+%d' % (x, y))
       messaggio = tk.Label(self.tw,
                            text=self.testo,
                            justify='left',
                            background='#f6f6e3',
                            relief='solid',
                            borderwidth=1,
                            wraplength=self.lunghezza
                            )
       messaggio.pack(ipadx=1)

   def nasconditip(self):
       tw = self.tw
       self.tw = None
       if tw:
           tw.destroy()
>


codice per la definizione di un set di "risorse" : setcreator.py

CODICE
# -*- coding: utf-8 -*-

'''
Modulo di classe per la creazione di un file python (estensione *.py) per
la memorizzazione dei immagini e stringhe descrittive corrispondenti, da
utilizzarsi come icone in una applicazzione.
'''

import os, re, base64, sys

# *** VARIABILI GLOBALI ***

idscode = '''
class IcoDispencer:
   def __init__(self):
       self.icoset = setico

   def getIco(self, chiave):
       return self.icoset[chiave][0]

   def getDescr(self, chiave):
       try:
           descr = self.icoset[chiave][1]
           return descr
       except:
           return None

   def printData(self):
       for chiave in self.icoset:
           print(chiave, ':', self.icoset[chiave][1])

   def getData(self):
       return self.icoset
'''

# *** CLASSI ***

class IcoSetError(Exception):

   def __init__(self, fonte=None, msg='Errore generico'):
       '''
Eccezione sollevata alla definizione di un set

Attibuti : fonte -- procedura che ha lanciato l'eccezione
          msg   -- messaggio collegato all'errore
'''
       self.fonte = fonte
       self.msg = msg



class SetCreator:
   ''' Definisce i set di icone '''

   def __init__(self, contesto='TK'):
       ''' Inizializza con un set vuoto '''
       self._icoset = {}
       self._contesto = contesto
       self._dirSet = ''
       self._nomeSet = ''

   def loadSet(self, pathset):
       import importlib.util, sys
       ''' Cerca di caricare il set di icone passato quale parametro '''
       try:
           self._dirSet = os.path.abspath(os.path.dirname(pathset))
           self._nomeSet = os.path.basename(pathset)
           aset = os.path.splitext(self._nomeSet)[0]
           spec = importlib.util.spec_from_file_location(aset, pathset)
           modulo = importlib.util.module_from_spec(spec)
           spec.loader.exec_module(modulo)            
           ids = modulo.IcoDispencer()
           self._icoset = ids.getData()
       except ImportError:
           raise IcoSetError('In LoadSet, ImportError', sys.exc_info()[1])
       except OSError:
           raise IcoSetError('In LoadSet, OSError', sys.exc_info()[1])
       except ImportError:
           raise IcoSetError('In LoadSet, ImportError', sys.exc_info()[1])
       except:
           raise IcoSetError('In LoadSet, errore imprevisto', sys.exc_info()[1])

   def getData(self):
       ''' Restituisce il dizionario delle icone corrente '''
       return self._icoset

   def getIco(self, chiave):
       '''
Restituisce l'immagine della icona corrispondente alla chiave in parametro

chiave      : la 'key' del dizionario in uso

restituisce : l'immagine corrispondente alla chiave o 'None' se non la trova
'''
       def from_tkinter(chiave):
           # restituzione nel caso si utilizzi tkinter
           try:
               import Tkinter as tk
           except:
               import tkinter as tk
               
           try:
               img = tk.PhotoImage(data = self._icoset[chiave][0])
               return img
           except:
               return None

       def from_gtk(chiave):
           # da definire, forse
           return None

       def from_wx(chiave):
           # da definire, forse
           return None

       def from_qt(chiave):
           # da definire, forse
           return None

       if self._contesto == 'TK':
           return from_tkinter(chiave)
       elif self._contesto == 'GTK':
           return from_gtk(chiave)
       elif self._contesto == 'WX':
           return from_wx(chiave)
       elif self._contesto == 'QT':
           return from_qt(chiave)
       else:
           return None


   def getDescr(self, chiave):
       '''
Restituisce la descrizione della icona corrispondente alla chiave in parametro

chiave      : la 'key' del dizionario in uso

restituisce : la descrizione corrispondente alla chiave o 'None' se non la trova
'''
       try:
           descr = self._icoset[chiave][1]
           return descr
       except:
           return None


   def getDir(self):
       ''' restituisce la directory di appartenenza del set '''
       return self._dirSet


   def getNomeSet(self):
       ''' restituisce il nome del file di set '''
       return self._nomeSet


   def defSet(self, dirSet, nomeSet):
       '''
Definisce un nuovo set di icone.

Parametri : dirSet - stringa, direttrice di storage del set
           nomeSet - il nome del file definente il set

Eccezioni : invoca un IconSetError in caso di parametri vuoti o
           di nome di file che non abbia estensione *.py.
           Eventuali errori di nome file causeranno errori in fase di
           scrittura dati.
'''
       # Verifica direttrice
       if dirSet == None or dirSet == '':
           raise IcoSetError('In defSet' , 'Direttrice di destinazione nulla')
       # verifica nome del file
       if nomeSet == None or nomeSet == '':
           raise IcoSetError('In defSet' , 'Nome del file nullo')
       else:
           elem = nomeSet.split('.')
           if elem[1] != 'py':
               raise IcoSetError('In defSet' , 'Nome del file deve essere ' +
                                 'di tipo python (*.py)'
                                 )
       self._dirSet = dirSet
       self._nomeSet = nomeSet
           

   def _verfile(self, f):
       ext = ['png', 'gif']
       nomefile = os.path.basename(f)
       if not nomefile.split('.')[1].lower() in ext:
           return False
       return True
       

   def cambiaIco(self, chiave, nomeIco):
       '''
Cambia l'immagine corrispondente alla chiave.

Parametri : chiave, la chiave del dizionario cui riferisce l'elemento
                   da modificare
           nomeIco, il path del file da inserire

Eccezioni : in caso di errori di I/O o di immagini diverse dalle tipologie
            "*.png" o "*.gif" viene sollevato un IcoSetError
'''
       # verifica esistenza chiave
       if not chiave in self._icoset.keys():
           raise IcoSetError('In cambiaIco' , 'Chiave da variare inesistente')
       # verifica la compatibilità
       if not self._verfile(nomeIco):
           raise IcoSetError('In cambiaIco' , 'Tipologia immagine non supportata')
       # procede alla conversione dell'immagine ed assegnazione dati
       f = None
       try:
           f = open(nomeIco, 'rb')
           encIco = base64.b64encode(f.read()).decode('utf-8')
           self._icoset[chiave][0] = encIco
       except (IOError, OSError) as e:
           msg = "Errore I/IO : {0}".format(e)
           raise IcoSetError('In cambiaIco' , msg)
       except:
           msg = "Errore inatteso : " + str(sys.exc_info()[0])
           raise IcoSetError('In cambiaIco' , msg)
       finally:
           if f != None:
               if not f.closed:
                   f.close()
   

   def cambiaDescr(self, chiave, descrIco):
       '''
Cambia la descrizione corrispondente alla chiave.

Parametri : chiave, la chiave del dizionario cui riferisce l'elemento
                   da modificare
           descrIco, la descrizione da inserire, può essere vuota

Eccezioni : in caso di errori di chiave viene sollevata una
            IcoSetException
'''
       # verifica esistenza chiave
       if not chiave in self._icoset.keys():
           raise IcoSetError('In cambiaIco' , 'Chiave da variare inesistente')
       p1 = re.compile('[\t\r\n]')
       self._icoset[chiave][1] = p1.sub('', descrIco)
   

   def cancellaIco(self,chiave):
       '''
Rimuove dal set i dati corrispondenti ad una chiave

Parametri : chiave, la chiave del dizionario cui riferisce l'elemento
                   da modificare

Eccezioni : in caso non trovi la chiave viene sollevata una IcoSetException
'''
       if not chiave in self._icoset.keys():
           raise IcoSetError('In cancellaIco' ,
                             'Chiave dati da eliminare inesistente'
                             )
       del self._icoset[chiave]


   def addIco(self, dati):
       '''
Aggiunge una nuova immagine al set.

Parametri : dati - una lista contenente gli elementi :
                  [0] - la codifica b64 della immagine
                  [1] - la chiave della nuova immagine;
                  [2] - eventuale descrizione, in mancanza diviene ''.

Eccezioni : in caso di errori nel file, carenza o duplicazione chiave
           viene sollevata un IcoSetError
'''
       chiave = dati[1]
       if chiave == None or chiave == '':
           raise IcoSetError('In addIco', 'Chiave non definita')
       if chiave in self._icoset.keys():
           raise IcoSetError('In addIco' , 'Chiave già esistente')
       f = None
       self._icoset[chiave] = [dati[0], None]
       descr = dati[2]
       if descr == None:
           descr = ''
       # elimino eventuli tabulazioni e ritorni a capo
       p1 = re.compile('[\t\r\n]')
       self._icoset[chiave][1] = p1.sub('', descr)

   def makeSet(self):
       '''
Scrive dati e metodi nel file di risorse definito, cancellando eventuali
versioni già esistenti.

Eccezioni : in caso di errori di qualsiasi genere viene invocato
           un IcoSetError
'''
       fS = os.path.join(self._dirSet, self._nomeSet)
       f = None
       try:
           # se esiste, elimina la versione precedente
           if os.path.isfile(fS):
               os.remove(fS)
           # crea la nuova risorsa aprendola per scrittura
           f = open(fS, 'w')
           # *** INIZIO SCRITTURA ***
           testo = '# -*- coding: utf-8 -*-\n'
           f.write(testo)
           self._scriviIco(f)
           self._scriviDiz(f)
           f.write('\n\n' + idscode)
       except (IOError, OSError) as e:
           msg = 'Errore in creazione file : {0}'.format(e)
           raise IcoSetError('Registrazione set', msg)
       finally:
           if f != None:
               if not f.closed:
                   f.close()


   def _scriviIco(self, f):
       ''' Scrive i dati-immagine '''
       for elem in sorted(self._icoset.keys()):
           pivot = 0
           strtmp = "\nico" + elem + " = '''\n"
           f.write(strtmp)
           strDati = self._icoset[elem][0].replace('\n', '')
           while pivot < len(strDati):
               if pivot + 79 >= len(strDati):
                   strtmp = strDati[pivot:] + '\n'
               else:
                   strtmp = strDati[pivot: pivot+79] + '\n'
               f.write(strtmp)
               pivot += 79
           strtmp = "'''\n"
           f.write(strtmp)


   def _scriviDiz(self, f):
       ''' Scrive il dizionario di immagini e descrizioni '''
       strTmp = '\nsetico = {"'
       spazi = '\n          '
       primoelem = True
       for elemen in sorted (self._icoset.keys()):
           if not primoelem:
               strTmp += ',\n' + spazi + '"'
           else:
               primoelem = False
           strTmp += (elemen + '" : [ico' + elemen + ', "' +
                      self._icoset[elemen][1] + '"]'
                      )
       strTmp += spazi + '}'
       f.write(strTmp)


   def _defkey(self, fn):
       ''' Definisce una chiave partendo da un nomefile '''
       tmp = fn.split('.')[0]
       if tmp in self._icoset.keys():
           conta = 0
           vabene = False
           while not vabene:
               conta += 1
               chiave = tmp + "_" + conta
               if not chiave in self._icoset.keys():
                   tmp = chiave
                   vabene = True
       return tmp
   

   def _converti(self, fi):
       f = None
       encIco = None
       try:
           f = open(fi, 'rb')
           encIco = base64.encodestring(f.read()).decode('utf-8')
       except (IOError, OSError) as e:
           msg = "Errore I/IO : {0}".format(e)
           raise IcoSetError('In converti' , msg)
       except:
           msg = "Errore inatteso : " + str(sys.exc_info()[0])
           raise IcoSetError('In converti' , msg)
       finally:
           if f != None:
               if not f.closed:
                   f.close()
       return '' + encIco

       
   def addDirImg(self, dirimg):
       ''' Aggiunge le immagini compatibili presenti in una directory '''
       lstfile = [f for f in os.listdir(dirimg) if
                  os.path.isfile(os.path.join(dirimg, f))]
       for f in lstfile:
           nomefile = os.path.join(dirimg, f)
           if self._verfile(nomefile):
               newimg = []
               newimg.append(self._converti(nomefile))
               newimg.append(self._defkey(f))
               newimg.append('')
               self.addIco(newimg)
>

interfaccia grafica della applicazione : setico.py

CODICE
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

tkerror = False

try:
   import Tkinter as tk
   tkerror = True
except:
   import tkinter as tk
   import tkinter.ttk as ttk
   import tkinter.messagebox as mb
   import tkinter.filedialog as fd
   

import base64, os
import risorse, setcreator

# *** VARIABILI GLOBALI ***
sc = setcreator.SetCreator('TK')


# *** CLASSI ***
class FRMSet(tk.Frame):
   ''' Pannello di definizione dei set di icone.'''

   def __init__(self, master):
       super().__init__(master)
       self.master = master
       self.initDir = os.getenv('HOME')
       self.configure(pady=6)
       from tkutilita import CreaToolTip
       ids = risorse.IcoDispencer()
       self.lblDirSet = tk.Label(self,
                                  text='...',
                                  relief='raised',
                                  justify='left',
                                  anchor='w'
                                  )
       self.lblDirSet.pack(side='top', expand=True, fill='x')
       lbl1 = tk.Label(self, text='Set : ')
       lbl1.pack(side='left')
       self.eSet = tk.Entry(self, width=15)
       self.eSet.pack(side='left', expand=True, fill='x')
       sep1 = tk.Frame(self, width=20)
       sep1.pack(side='left', fill='x')
       self.icoNSet = tk.PhotoImage(data = ids.getIco('nset'))
       self.btNSet = tk.Button(self,
                                image=self.icoNSet,
                                padx=6,
                                command=self._newSet
                                )
       self.btNSet.pack(side='left', fill='x')
       self.btNSet_ttp = CreaToolTip(self.btNSet,
                                     ids.getDescr('nset')
                                     )
       self.icoASet = tk.PhotoImage(data = ids.getIco('aset'))
       self.btASet = tk.Button(self,
                                image=self.icoASet,
                                padx=6,
                                command=self._openSet
                                )
       self.btASet.pack(side='left', fill='x')
       self.btASet_ttp = CreaToolTip(self.btASet,
                                     ids.getDescr('aset')
                                     )
       sep2 = tk.Frame(self, width=20)
       sep2.pack(side='left', fill='x')
       self.icoSSet = tk.PhotoImage(data = ids.getIco('sset'))
       self.btSSet = tk.Button(self,
                                image=self.icoSSet,
                                padx=4,
                                command=self._saveSet
                                )
       self.btSSet.pack(side='left', fill='x')
       self.btSSet_ttp = CreaToolTip(self.btSSet,
                                     ids.getDescr('sset')
                                     )
       sep3 = tk.Frame(self, width=20)
       sep3.pack(side='left', expand=True, fill='x')
       self.icoCSet = tk.PhotoImage(data = ids.getIco('cset'))
       self.btCSet = tk.Button(self,
                                image=self.icoCSet,
                                padx=4,
                                command=master.destroy
                                )
       self.btCSet.pack(side='left', fill='x', padx=4)
       self.btCSet_ttp = CreaToolTip(self.btCSet,
                                     ids.getDescr('cset')
                                     )

   def _newSet(self):
       ''' Avvia la definizione di un nuovo set di icone '''
       if self.stato != 'newSet':
           msg = ("Avvio procedura definizione nuovo set\n\n" +
                  "1 - scegliere direttrice;\n" +
                  "2 - scrivere nome del set (*.py);\n" +
                  "3 - premere nuovamente il pulsante.\n\n" +
                  "N.B. : se già presente il set verrà\n" +
                  "       sostituito al 1° salvataggio."
                  )
           resp = mb.askyesno('Confermi operazione?', msg)
           #resp = mb.askyesno('Confermi operazione?', msg)
           if resp == False:
               return
           dirnome = fd.askdirectory(parent= self,
                                                initialdir=self.initDir,
                                                title='Selezionare direttrice'
                                                )
           if not dirnome:
               mb.showinfo('Operazione annullata',
                                      'Nessuna direttrice selezionata'
                                      )
               return
           self.initDir = dirnome
           self.lblDirSet.configure(text=dirnome)
           self.setStato('newSet')
       else:
           txt = self.eSet.get()
           if txt != None and txt != '':
               if txt.split('.')[-1] != 'py':
                   mb.showinfo('Nome set inaccettabile',
                                          'Deve essere un file python (*.py)'
                                          )
                   self.eSet.focus_set()
               else:
                   try:
                       sc.defSet(self.lblDirSet.cget('text'), txt)
                   except setcreator.IcoSetError as ie:
                       msg = str(ie.fonte) + '\n\n' + str(ie.msg)
                       mb.showerror("Errore definizione", msg)
                       return
                   self.master.setStato('in_work')
           else:
               mb.showinfo('Nome set vuoto',
                                      'Obbligatorio, deve essere un file python (*.py)'
                                      )
               self.eSet.focus_set()


   def _openSet(self):
       ''' Permette il caricamento di un set esistente '''
       fnome = fd.askopenfilename(parent=self,
                                             initialdir=self.initDir,
                                             title='Seleziona risorsa',
                                             defaultextension='.py',
                                             filetypes=[('Codice Python',
                                                         '*.py')
                                                        ]
                                             )
       if not fnome:
           return
       # invoca il caricamento dei dati
       try:
           sc.loadSet(fnome)
       except setcreator.IcoSetError as ie:
           msg = str(ie.fonte) + '\n\n' + str(ie.msg)
           mb.showerror("Errore caricamento", msg)
           return
       # aggiorna i controlli di set
       self.lblDirSet.configure(text=sc.getDir())
       self.eSet.config(state='normal')
       self.eSet.delete(0, tk.END)
       self.eSet.insert(0, sc.getNomeSet())
       self.eSet.config(state='disabled')
       # comunica l'avvenuto caricamento
       self.master.gestEvento('dati_caricati')
           

   def _saveSet(self):
       ''' Invoca il salvataggio dello stato corrente '''
       try:
           sc.makeSet()
           self.master.setStato('in_work')
       except setcreator.IcoSetError as ei:
           msg = ei.fonte + '\n\n' + ei.msg
           mb.showerror("Errore cambio immagine", msg)
           return
           

   def setStato(self, stato):
       ''' Definisce lo stato applicativo dei controlli del frame '''
       self.stato = stato
       if self.stato == 'avvio':
           self.eSet.config(state='disabled')
           self.btNSet.config(state='normal')
           self.btASet.config(state='normal')
           self.btSSet.config(state='disabled')
       elif self.stato == 'newSet':
           self.btASet.config(state='disabled')
           self.eSet.config(state='normal')
           self.eSet.focus_set()
       elif self.stato == 'in_work':
           self.eSet.config(state='disabled')
           self.btNSet.config(state='disabled')
           self.btASet.config(state='disabled')
           self.btSSet.config(state='normal')
       elif self.stato == 'modIco' or self.stato == 'newIco':
           self.btSSet.config(state='disabled')
           
       


   
class FRMIco(tk.Frame):
   ''' Pannello di gestione delle singole immagini '''

   def __init__(self, master):
       from tkutilita import CreaToolTip
       ids = risorse.IcoDispencer()
       self.initDir = os.getenv('HOME')
       super().__init__(master)
       self.master = master
       self._currIco = None
       self._nuovaIco = []
       # *** Pannello rappresentazione immagine ***
       frmCanvas = tk.Frame(self, relief='raised', border=1)
       frmCanvas.pack(side='left', fill='y', padx=10, pady=10)
       self.canv = tk.Canvas(frmCanvas,
                             width=120,
                             height=120,
                             bg='#ffffc0',
                             relief='sunken',
                             border=1
                             )
       self.canv.pack(fill='both')
       self.didaIco = tk.Label(frmCanvas,
                               pady=4,
                               relief='sunken',
                               border=1
                               )
       self.didaIco.pack(side='bottom', fill='x')
       # *** Pannello bottoni di comando per immagini ***
       frmButton = tk.Frame(self, relief='sunken', border= 1, padx=4, pady=4)
       frmButton.pack(side='left', fill='y')
       self.icoAddIco = tk.PhotoImage(data = ids.getIco('addico'))
       self.btAddIco = tk.Button(frmButton,
                                 image=self.icoAddIco,
                                 padx=4,
                                 pady=4,
                                 command=self._newIco
                                 )
       self.addIco_ttp = CreaToolTip(self.btAddIco,
                                     ids.getDescr('addico')
                                     )
       self.btAddIco.pack()
       self.icoAddDir = tk.PhotoImage(data = ids.getIco('adddir'))
       self.btAddDir = tk.Button(frmButton,
                                 image=self.icoAddDir,
                                 padx=4,
                                 pady=4,
                                 command=self._impDir
                                 )
       self.addDir_ttp = CreaToolTip(self.btAddDir,
                                     ids.getDescr('adddir')
                                     )
       self.btAddDir.pack()
       self.icoCancIco = tk.PhotoImage(data = ids.getIco('cancico'))
       self.btCancIco = tk.Button(frmButton,
                                  image=self.icoCancIco,
                                  padx=4,
                                  pady=8,
                                  command=self._cancellaIco
                                  )
       self.cancIco_ttp = CreaToolTip(self.btCancIco,
                                      ids.getDescr('cancico')
                                      )
       self.btCancIco.pack()
       self.icoCambiaIco = tk.PhotoImage(data = ids.getIco('cambiaico'))
       self.btCambiaIco = tk.Button(frmButton,
                                    image=self.icoCambiaIco,
                                    padx=4,
                                    pady=8,
                                    command=self._variaIco
                                    )
       self.cambiaIco_ttp = CreaToolTip(self.btCambiaIco,
                                        ids.getDescr('cambiaico')
                                        )
       self.btCambiaIco.pack()
       self.icoAnnulla = tk.PhotoImage(data = ids.getIco('annulla'))
       self.btAnnullaIco = tk.Button(frmButton,
                                     image=self.icoAnnulla,
                                     padx=4,
                                     pady=8,
                                     command=self._annulla
                                     )
       self.annullaIco_ttp = CreaToolTip(self.btAnnullaIco,
                                         ids.getDescr('annulla')
                                         )
       self.btAnnullaIco.pack()
       self.icoOkIco = tk.PhotoImage(data = ids.getIco('okico'))
       self.btOkIco = tk.Button(frmButton,
                                image=self.icoOkIco,
                                padx=4,
                                pady=8,
                                command=self._salvaIco
                                )
       self.okIco_ttp = CreaToolTip(self.btOkIco,
                                    ids.getDescr('okico')
                                    )
       self.btOkIco.pack(side='bottom')
       # *** Pannello descrittori di icona ***
       lfrmData = tk.LabelFrame(self, text=' Descrizione ', padx=4, pady=4)
       lfrmData.pack(side='left', expand=True, fill='both', padx=4, pady=4)
       subf1 = tk.Frame(lfrmData, padx=0, pady=0)
       subf1.pack(expand=True, fill='x', padx=0, pady=0)
       lbl1 = tk.Label(subf1, text='Nome :', width=7, justify='left')
       lbl1.pack(side='left', anchor='n')
       self.eNomeIco = tk.Entry(subf1, width=15)
       self.eNomeIco.pack(side='left', expand=True, fill='x', anchor='n')
       subf2 = tk.Frame(lfrmData)
       subf2.pack(expand=True, fill='both')
       lbl2 = tk.Label(subf2, text='Uso :', width=7, justify='left')
       lbl2.pack(side='left', anchor='n')
       self.tUsoIco = tk.Text(subf2, width=15, height=4, wrap='word')
       self.tUsoIco.pack(side='left', anchor='n', expand=True, fill='both')
       self.tScroll = tk.Scrollbar(subf2, orient=tk.VERTICAL)
       self.tUsoIco.config(yscrollcommand=self.tScroll.set)
       self.tScroll.config(command=self.tUsoIco.yview)
       self.tScroll.pack(side='right', anchor='n', fill='y')

   def setStato(self, stato):
       self.stato = stato
       if self.stato == 'avvio':
           # Non c'è set corrente, tutto disabilitato
           self.btAddIco.config(state='disabled')
           self.btAddDir.config(state='disabled')
           self.btCancIco.config(state='disabled')
           self.btCambiaIco.config(state='disabled')
           self.btAnnullaIco.config(state='disabled')
           self.btOkIco.config(state='disabled')
           self.eNomeIco.config(state='disabled')
           self.tUsoIco.config(state='disabled')
       elif self.stato == 'in_work':
           # Set aperto senza elementi selezionati
           self.btAddIco.config(state='normal')
           self.btAddDir.config(state='normal')
           self.btCancIco.config(state='disabled')
           self.btCambiaIco.config(state='disabled')
           self.btAnnullaIco.config(state='disabled')
           self.btOkIco.config(state='disabled')
           self.eNomeIco.config(state='disabled')
           self.tUsoIco.config(state='disabled')
       elif self.stato == 'ico_selected':
           # Modifiche per icona selezionata
           self.btCancIco.config(state='normal')
           self.btCambiaIco.config(state='normal')
       elif self.stato == 'modIco':
           self.btAddIco.config(state='disabled')
           self.btAddDir.config(state='disabled')
           self.btCancIco.config(state='disabled')
           self.btCambiaIco.config(state='disabled')
           self.btAnnullaIco.config(state='normal')
           self.btOkIco.config(state='normal')
           self.eNomeIco.config(state='disabled')
           self.tUsoIco.config(state='normal')
           self.tUsoIco.focus_set()
       elif self.stato == 'newIco':
           self.btAddIco.config(state='disabled')
           self.btAddDir.config(state='disabled')
           self.btCancIco.config(state='disabled')
           self.btCambiaIco.config(state='disabled')
           self.btAnnullaIco.config(state='normal')
           self.btOkIco.config(state='normal')
           self.eNomeIco.config(state='normal')
           self.tUsoIco.config(state='normal')
           self.eNomeIco.focus_set()


   def _cleanCtr(self):
       '''
Svuota i controlli icona

N,B, : I controlli di testo del frame vengono attivati e rimangono
attivi, eventuale disattivazione va eseguita nel processo chiamante
'''
       self.canv.delete('all')
       self._currIco = None
       self.didaIco.configure(text='')
       # attiva i campi di testo
       self.eNomeIco.config(state='normal')
       self.tUsoIco.config(state='normal')
       # Pulizia e riscrittura dei campi di testo
       self.eNomeIco.delete(0, tk.END)
       self.tUsoIco.delete(1.0, tk.END)
       
           
           

   def _convertiIco(self, nomeIco):
       ''' Converte un file di immagine '''
       ext = ['png', 'gif', 'jpg', 'jpeg']
       # verifica l'estensione del file immagine
       nomefile = os.path.basename(nomeIco)
       if not nomefile.split('.')[1].lower() in ext:
           raise setcreator.IcoSetError('In convertiIco' ,
                                        'Tipologia immagine non supportata'
                                        )
       # procede alla conversione dell'immagine ed assegnazione dati
       f = None
       encIco = None
       try:
           f = open(nomeIco, 'rb')
           encIco = base64.encodestring(f.read()).decode('utf-8')
       except (IOError, OSError) as e:
           msg = "Errore I/IO : {0}".format(e)
           raise setcreator.IcoSetError('In convertiIco' , msg)
       except:
           msg = "Errore inatteso : " + str(sys.exc_info()[0])
           raise setcreator.IcoSetError('In convertiIco' , msg)
       finally:
           if f != None:
               if not f.closed:
                   f.close()
       return '' + encIco


       
       
   def esegui(self, comando, chiave='', file=''):
       ''' Esegue un comando passato dalla finestra principale '''
       if comando == 'mostra_icona':
           # mostra una icona già registrata
           # pulizia e ridisegno del canvas
           self._cleanCtr()
           # - calcolo coordinate di inizio e disegno
           self._currIco = sc.getIco(chiave)
           x = self.canv.winfo_width() // 2
           y = self.canv.winfo_height() // 2
           self.canv.create_image(x, y, image=self._currIco, anchor='center')
           self.didaIco.configure(text=str(self._currIco.width()) +
                                  'x' + str(self._currIco.height()))
           # scrittura campi di testo
           self.eNomeIco.insert(0, chiave)
           self.tUsoIco.insert(tk.END, sc.getDescr(chiave))
           # disattiva i campi di testo
           self.eNomeIco.config(state='disabled')
           self.tUsoIco.config(state='disabled')
           # ridefinisce lo stato del frame
           self.setStato('ico_selected')
       elif comando == 'mostra_immagine':
           # mostra l'immagine di una nuova icona
           self._cleanCtr()
           self._nuovaIco = []
           self._nuovaIco.append(self._convertiIco(file))
           self._currIco = tk.PhotoImage(data = self._nuovaIco[0])
           x = self.canv.winfo_width() // 2
           y = self.canv.winfo_height() // 2
           self.canv.create_image(x, y, image=self._currIco, anchor='center')
           self.didaIco.configure(text=str(self._currIco.width()) +
                                  'x' + str(self._currIco.height()))
           
               
           
           

   def _apriImg(self):
       ''' Apre un file di immagine e restituisce il nomefile '''
       # base per tipi di files
       tipi = [('Files immagine',
               ('*.png', '*.PNG',
               '*.gif', '*.GIF'
                )
                )
               ]
       fnome = fd.askopenfilename(parent=self,
                                             initialdir=self.initDir,
                                             title='Seleziona immagine',
                                             defaultextension='.png',
                                             filetypes=tipi
                                             )
       if not fnome:
           return None
       # definisce la direttrice corrente quale predefinita
       if os.path.isfile(fnome):
           self.initDir = os.path.dirname(fnome)
       return fnome


   def _impDir(self):
       ''' Importa nel set le immagini compatibili di una directory '''
       initDir = os.getenv('HOME')
       dirnome = fd.askdirectory(parent= self,
                                            initialdir=initDir,
                                            title='Selezionare direttrice'
                                            )
       if not dirnome:
           return
       try:
           sc.addDirImg(dirnome)
       except setcreator.IcoSetError as ie:
           msg = str(ie.fonte) + '\n\n' + str(ie.msg)
           mb.showerror("Errore lettura immagini", msg)
           return
       self.master.gestEvento('updateIco')
           
   

   def _variaIco(self):
       ''' Cambia l'icona o la descrizione di un elemento '''
       msg = ("Può essere variata l'immagine o la descrizione d'uso\n\n" +
              "Volete cambiare l'immagine?")
       resp = mb.askyesnocancel('Cosa cambio?', msg)
       if resp == None:
           return
       elif resp == True:
           fnome = self._apriImg()
           if not fnome:
               return
           try:
               sc.cambiaIco(self.eNomeIco.get(), fnome)
           except setcreator.IcoSetError as ie:
               msg = str(ie.fonte) + '\n\n' + str(ie.msg)
               mb.showerror("Errore cambio immagine", msg)
               return
           self.esegui('mostra_icona', self.eNomeIco.get())
       else:
           self.master.setStato('modIco')


   def _variaDescr(self):
       ''' Riassegna la descrizione d'uso dell'icona corrente '''
       try:
           descr = self.tUsoIco.get(1.0, tk.END)
           if descr:
               sc.cambiaDescr(self.eNomeIco.get(), descr)
           else:
               sc.cambiaDescr(self.eNomeIco.get(), '')
       except setcreator.IcoSetError as ie:
           msg = str(ie.fonte) + '\n\n' + str(ie.msg)
           mb.showerror("Errore cambio descrizione", msg)
           return
       self.master.gestEvento('updateIco')


   def _newIco(self):
       ''' Imposta l'ambiente per l'inserimento di una nuova icona '''
       # definisce lo stato del frame e regola i controlli
       nf = self._apriImg()
       if nf == None or nf == '':
           # nessuna selezione, processo annullato
           mb.showinfo("Processo annullato",
                                  'Nessun file è stato selezionato'
                                  )
           self.master.setStato('in_work')
           return
       try:
           self.master.setStato('newIco')
           self.esegui('mostra_immagine', file=nf)
       except setcreator.IcoSetError as ie:
           msg = str(ie.fonte) + '\n\n' + str(ie.msg)
           mb.showerror("Errore immagine", msg)
           self.master.setStato('in_work')
           return
       self.eNomeIco.focus_set()
       

   def _annulla(self):
       ''' Annulla la definizione corrente '''
       self._cleanCtr()
       # disattiva i campi di testo
       self.eNomeIco.config(state='disabled')
       self.tUsoIco.config(state='disabled')
       self.master.gestEvento('updateIco')

   
   def _salvaIco(self):
       ''' Secondo lo stato del frame aggiorna o aggiunge l'icona '''
       if self.stato == 'modIco':
           self._variaDescr()
       elif self.stato == 'newIco':
           nomeIco = self.eNomeIco.get()
           if not nomeIco:
               msg = ('Il nome da assegnare è un dato necessario\n\n' +
                      'Si vuol proseguire nella immissione?')
               resp = mb.askyesno('Cosa vuoi fare?', msg)
               if resp == True:
                   self.eNomeIco.focus_set()
                   return
               else:
                   self._clearCtr()
                   self.master.setStato('in_work')
                   return
           self._nuovaIco.append(nomeIco)
           descr = self.tUsoIco.get(1.0, tk.END)
           self._nuovaIco.append(descr)
           try:
               sc.addIco(self._nuovaIco)
           except setcreator.IcoSetError as er:
               msg = str(er.fonte) + '\n\n' + str(er.msg)
               mb.showerror("Errore In Aggiunta", msg)
               return
           self.master.gestEvento('updateIco')
       else:
           return


   def _cancellaIco(self):
       ''' Cancella l'elemento corrente dal set '''
       if self.eNomeIco.get() == None or self.eNomeIco.get() == '':
           return
       
       msg = ("Siete certi di voler eliminare l'elemento\n\n" +
              self.eNomeIco.get() + "?")
       resp = mb.askyesnocancel('Richiesta conferma', msg)
       if resp == None:
           return
       elif resp == True:
           try:
               sc.cancellaIco(self.eNomeIco.get())
           except setcreator.IcoSetError as ie:
               msg = str(ie.fonte) + '\n\n' + str(ie.msg)
               mb.showerror("Errore cancellazione immagine", msg)
               return
           # ripulisce i controlli
           self._cleanCtr()
           # disattiva i campi di testo
           self.eNomeIco.config(state='disabled')
           self.tUsoIco.config(state='disabled')
           # ridefinisce lo stato del frame
           self.master.gestEvento('updateIco')
       else:
           return




class FRMLista(tk.Frame):
   ''' Pannello della lista delle immagini presenti '''

   def __init__(self, master):
       super().__init__(master)
       self.stato = ''
       self.configure(padx=4, pady=4)
       lbl1 = tk.Label(self, text='Lista Immagini :')
       lbl1.pack(anchor='w')
       # test con frame per utilizzo layout "grid"
       frmGrid = tk.Frame(self)
       frmGrid.pack(expand=True, fill='both')
       self.tvIco = ttk.Treeview(frmGrid,
                                 columns=('chiave', 'descr'),
                                 selectmode='browse',
                                 show='headings',
                                 height=4)
       # definizione colonne treeview
       self.tvIco.heading('chiave', text='Chiave')
       self.tvIco.column('chiave', stretch=False, width=150)
       self.tvIco.heading('descr', text='Descrizione')
       self.tvIco.column('descr', width=150)
       # definizione dello scroll
       vScroll = tk.Scrollbar(self, orient=tk.VERTICAL)
       vScroll.config(command=self.tvIco.yview)
       self.tvIco.configure(yscrollcommand=vScroll.set)
       self.tvIco.grid(column=0,
                       row=0,
                       sticky='nsew',
                       in_=frmGrid
                       )
       vScroll.grid(column=1,
                    row=0,
                    sticky='ns',
                    in_=frmGrid
                    )
       frmGrid.grid_columnconfigure(0, weight=1)
       frmGrid.grid_rowconfigure(0, weight=1)
       # selezione dalla treeview con doppio click mouse
       # o pressione dei tasti 'Invio'
       self.tvIco.bind('<Double-1>', self._tvDbClick)
       self.tvIco.bind('<Return>', self._tvDbClick)
       self.tvIco.bind('<KP_Enter>', self._tvDbClick)


   def _tvDbClick(self, event):
       # si legge la riga selezionata
       riga = self.tvIco.item(self.tvIco.focus())
       # verifica vi siano dati
       if len(riga['values']) == 0:
           return
       # estrae la chiave dal primo dei valori associati
       chiave = riga['values'][0]
       self.master.comando('scelta_icona', chiave)


   def setStato(self, stato):
       ''' Gestisce le condizioni contestuali del frame '''
       self.stato = stato
       if self.stato == 'in_work':
           self.tvIco.state(('!disabled',))
       else:
           self.tvIco.state(('disabled',))


   def evento(self, cosa):
       ''' Risponde ad una segnalazione di evento dati '''
       if cosa == 'dati_caricati':
           # ripulisce la treeview
           for elem in self.tvIco.get_children():
               self.tvIco.delete(elem)
           # carica i dati disponibili
           for elem in sorted(sc.getData().keys()):
               self.tvIco.insert('', 'end',
                                 values=(elem,
                                         sc.getDescr(elem)
                                         )
                                 )
       return True        

   


class GUISet(tk.Tk):
   ''' Finestra principale della applicazione. '''

   def __init__(self):
       super().__init__()
       self.nascondi()
       self.title('Gestore Set Icone')
       self.option_add('*Dialog.msg.font', 'Helvetica 9')
       # Posiziona i frame componenti vuoti
       self.frmSet = FRMSet(self)
       self.frmSet.pack(fill='x')
       self.frmIco = FRMIco(self)
       self.frmIco.pack(fill='x')
       self.frmList = FRMLista(self)
       self.frmList.pack(expand=True, fill='both')
       # aggiorna i parametri della finestra
       self.update()
       # Richiede le proprie dimensioni
       wx = self.winfo_reqwidth()
       wy = self.winfo_reqheight()
       # e le imposta come minime per la finestra
       self.minsize(width=wx, height=wy)
       # imposta i controlli alla condizione iniziale
       self.setStato('avvio')
       # si nasconde

   def nascondi(self):
       ''' Nasconde la finestra.
Da utilizzarsi prima dell'inserimento dei componenti della finestra
'''
       self.withdraw()

   def mostra(self):
       ''' Mostra la finestra '''
       self.deiconify()

   def setStato(self, stato=''):
       ''' Imposta lo stato dei controlli nei sub-frame '''
       self.frmSet.setStato(stato)
       self.frmIco.setStato(stato)
       self.frmList.setStato(stato)

   def gestEvento(self, evento):
       ''' Decide cosa comunicare ai frame sul verificarsi di una circostanza '''
       if evento == 'dati_caricati':
           if self.frmList.evento(evento):
               self.setStato('in_work')
       elif evento == 'updateIco':
           self.frmSet.setStato('in_work')
           self.frmIco.setStato('in_work')
           self.frmList.evento('dati_caricati')
           
               
   def comando(self, comando, chiave=''):
       ''' Distribuisce i comandi tra i frame '''
       if comando == 'scelta_icona':
           self.frmIco.esegui('mostra_icona', chiave)




def centraFinestra(gui):
   ''' Centra una finestra, passata come parametro, sullo schermo '''
   l = gui.winfo_screenwidth()
   a = gui.winfo_screenheight()
   wx = gui.winfo_reqwidth()
   wy = gui.winfo_reqheight()
   gui.geometry('{}x{}+{}+{}'.format(wx, wy, (l-wx)//2, (a-wy)//2))

   
def main():
   finestra = GUISet()
   centraFinestra(finestra)
   finestra.mostra()
   finestra.mainloop()
   

if __name__ == '__main__':
   if tkerror:
       print('Mi dispiace, questo codice non è compatibile' +
             ' con le versioni 2.x di python-Tkinter')
   else:
       main()
>
 
Web  Top
0 replies since 24/8/2020, 13:06   123 views
  Share