kpolyakov-graph 1.5.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- kpolyakov_graph-1.5.2/PKG-INFO +44 -0
- kpolyakov_graph-1.5.2/README.md +6 -0
- kpolyakov_graph-1.5.2/graph.py +558 -0
- kpolyakov_graph-1.5.2/kpolyakov_graph.egg-info/PKG-INFO +44 -0
- kpolyakov_graph-1.5.2/kpolyakov_graph.egg-info/SOURCES.txt +7 -0
- kpolyakov_graph-1.5.2/kpolyakov_graph.egg-info/dependency_links.txt +1 -0
- kpolyakov_graph-1.5.2/kpolyakov_graph.egg-info/top_level.txt +1 -0
- kpolyakov_graph-1.5.2/setup.cfg +4 -0
- kpolyakov_graph-1.5.2/setup.py +39 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: kpolyakov-graph
|
|
3
|
+
Version: 1.5.2
|
|
4
|
+
Summary: Graph - tkinter-based framework for simple Python graphics
|
|
5
|
+
Home-page: http://kpolyakov.spb.ru/school/probook/python.htm
|
|
6
|
+
Download-URL: http://kpolyakov.spb.ru/school/probook/python.htm
|
|
7
|
+
Author: Konstantin Polyakov
|
|
8
|
+
Author-email: kpolyakov@mail.ru
|
|
9
|
+
Maintainer: Konstantin Polyakov
|
|
10
|
+
Maintainer-email: kpolyakov@mail.ru
|
|
11
|
+
License:
|
|
12
|
+
Licensed under MIT licence.
|
|
13
|
+
|
|
14
|
+
Keywords: application,framework,tkinter,graphics
|
|
15
|
+
Classifier: Development Status :: 3 - Alpha
|
|
16
|
+
Classifier: Environment :: Other Environment
|
|
17
|
+
Classifier: Intended Audience :: Developers
|
|
18
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
19
|
+
Classifier: Operating System :: OS Independent
|
|
20
|
+
Classifier: Programming Language :: Python
|
|
21
|
+
Classifier: Programming Language :: Python :: 3
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.2
|
|
23
|
+
Classifier: Topic :: Software Development
|
|
24
|
+
Classifier: Topic :: Software Development :: Build Tools
|
|
25
|
+
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
|
|
26
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
27
|
+
Classifier: Topic :: Software Development :: User Interfaces
|
|
28
|
+
Dynamic: author
|
|
29
|
+
Dynamic: author-email
|
|
30
|
+
Dynamic: classifier
|
|
31
|
+
Dynamic: description
|
|
32
|
+
Dynamic: download-url
|
|
33
|
+
Dynamic: home-page
|
|
34
|
+
Dynamic: keywords
|
|
35
|
+
Dynamic: license
|
|
36
|
+
Dynamic: maintainer
|
|
37
|
+
Dynamic: maintainer-email
|
|
38
|
+
Dynamic: summary
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
Graph: tkinter-based framework for simple graphics
|
|
42
|
+
|
|
43
|
+
`Graph` is a **Python3.2+** library designed to simplifying
|
|
44
|
+
coordinate graphics on the basis of tkinter library.
|
|
@@ -0,0 +1,558 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
GRAPH - модуль для простой графики в Python.
|
|
4
|
+
(C) К. Поляков, 2016-2022
|
|
5
|
+
e-mail: kpolyakov@mail.ru
|
|
6
|
+
web: http://kpolyakov.spb.ru
|
|
7
|
+
Версия 1.5.4
|
|
8
|
+
|
|
9
|
+
Модуль graph - это "обертка" над стандартной библиотекой tkinter,
|
|
10
|
+
позволяющая рисовать простыми командами в отдельном графическом окне.
|
|
11
|
+
В ней упрощён доступ ко многим возможностям библиотеки tkinter,
|
|
12
|
+
в то же время сохранена возможность использования всех средств tkinter.
|
|
13
|
+
|
|
14
|
+
ЛИЦЕНЗИЯ
|
|
15
|
+
|
|
16
|
+
Copyright (c) 2016-2019, Константин Поляков
|
|
17
|
+
Все права защищены.
|
|
18
|
+
|
|
19
|
+
Разрешается повторное распространение и использование как в виде исходного
|
|
20
|
+
кода, так и в двоичной форме, с изменениями или без, при соблюдении
|
|
21
|
+
следующих условий:
|
|
22
|
+
1) При повторном распространении исходного кода должно оставаться указанное
|
|
23
|
+
выше уведомление об авторском праве, этот список условий и последующий
|
|
24
|
+
отказ от гарантий.
|
|
25
|
+
2) При повторном распространении двоичного кода должна сохраняться указанная
|
|
26
|
+
выше информация об авторском праве, этот список условий и последующий
|
|
27
|
+
отказ от гарантий в документации и/или в других материалах,
|
|
28
|
+
поставляемых при распространении.
|
|
29
|
+
3) Ни название Организации, ни имена ее сотрудников не могут быть
|
|
30
|
+
использованы в качестве поддержки или продвижения продуктов,
|
|
31
|
+
основанных на этом ПО без предварительного письменного разрешения.
|
|
32
|
+
|
|
33
|
+
ДАННОЕ ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ ПРЕДОСТАВЛЯЕТСЯ «КАК ЕСТЬ», БЕЗ ЛЮБОГО ВИДА
|
|
34
|
+
ГАРАНТИЙ, ЯВНО ВЫРАЖЕННЫХ ИЛИ ПОДРАЗУМЕВАЕМЫХ, ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИВАЯСЬ
|
|
35
|
+
ГАРАНТИЯМИ ТОВАРНОЙ ПРИГОДНОСТИ, СООТВЕТСТВИЯ ПО ЕГО КОНКРЕТНОМУ НАЗНАЧЕНИЮ
|
|
36
|
+
И НЕНАРУШЕНИЯ ПРАВ. НИ В КАКОМ СЛУЧАЕ АВТОРЫ ИЛИ ПРАВООБЛАДАТЕЛИ НЕ НЕСУТ
|
|
37
|
+
ОТВЕТСТВЕННОСТИ ПО ИСКАМ О ВОЗМЕЩЕНИИ УЩЕРБА, УБЫТКОВ ИЛИ ДРУГИХ ТРЕБОВАНИЙ
|
|
38
|
+
ПО ДЕЙСТВУЮЩИМ КОНТРАКТАМ, ДЕЛИКТАМ ИЛИ ИНОМУ, ВОЗНИКШИМ ИЗ, ИМЕЮЩИМ ПРИЧИНОЙ
|
|
39
|
+
ИЛИ СВЯЗАННЫМ С ПРОГРАММНЫМ ОБЕСПЕЧЕНИЕМ ИЛИ ИСПОЛЬЗОВАНИЕМ ПРОГРАММНОГО
|
|
40
|
+
ОБЕСПЕЧЕНИЯ ИЛИ ИНЫМИ ДЕЙСТВИЯМИ С ПРОГРАММНЫМ ОБЕСПЕЧЕНИЕМ.
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
"""
|
|
44
|
+
Исходя из http://docs.python.org/3/library/sys.html внесены исправления для
|
|
45
|
+
обеспечения работоспособности в ОС Linux (С. Целищев).
|
|
46
|
+
"""
|
|
47
|
+
from sys import platform
|
|
48
|
+
|
|
49
|
+
if platform == "win32" or platform == "cygwin":
|
|
50
|
+
VK_SPACE = 0x20
|
|
51
|
+
VK_PRIOR = 0x21 # PAGE UP key
|
|
52
|
+
VK_NEXT = 0x22 # PAGE DOWN key
|
|
53
|
+
VK_END = 0x23 # END key
|
|
54
|
+
VK_HOME = 0x24 # HOME key
|
|
55
|
+
VK_LEFT = 0x25
|
|
56
|
+
VK_UP = 0x26
|
|
57
|
+
VK_RIGHT = 0x27
|
|
58
|
+
VK_DOWN = 0x28
|
|
59
|
+
VK_INSERT = 0x2D # INS key
|
|
60
|
+
VK_DELETE = 0x2E # DELETE key
|
|
61
|
+
VK_BACK = 0x08 # BACKSPACE key
|
|
62
|
+
VK_TAB = 0x09 # TAB key
|
|
63
|
+
VK_RETURN = 0x0D # RETURN key
|
|
64
|
+
VK_ESCAPE = 0x1B # ESC key
|
|
65
|
+
elif platform == "linux":
|
|
66
|
+
VK_SPACE = 0x41
|
|
67
|
+
VK_PRIOR = 0x70 # PAGE UP key
|
|
68
|
+
VK_NEXT = 0x75 # PAGE DOWN key
|
|
69
|
+
VK_END = 0x73 # END key
|
|
70
|
+
VK_HOME = 0x6E # HOME key
|
|
71
|
+
VK_LEFT = 0x71
|
|
72
|
+
VK_UP = 0x6F
|
|
73
|
+
VK_RIGHT = 0x72
|
|
74
|
+
VK_DOWN = 0x74
|
|
75
|
+
VK_INSERT = 0x76 # INS key
|
|
76
|
+
VK_DELETE = 0x77 # DELETE key
|
|
77
|
+
VK_BACK = 0x16 # BACKSPACE key
|
|
78
|
+
VK_TAB = 0x17 # TAB key
|
|
79
|
+
VK_RETURN = 0x24 # RETURN key
|
|
80
|
+
VK_ESCAPE = 0x09 # ESC key
|
|
81
|
+
|
|
82
|
+
DEF_GRAPH_WIDTH = 500
|
|
83
|
+
DEF_GRAPH_HEIGHT = 600
|
|
84
|
+
|
|
85
|
+
import tkinter
|
|
86
|
+
from random import randint
|
|
87
|
+
try:
|
|
88
|
+
from PIL import ImageTk, Image
|
|
89
|
+
except:
|
|
90
|
+
pass
|
|
91
|
+
|
|
92
|
+
NW = tkinter.NW
|
|
93
|
+
N = tkinter.N
|
|
94
|
+
NE = tkinter.NE
|
|
95
|
+
W = tkinter.W
|
|
96
|
+
CENTER = tkinter.CENTER
|
|
97
|
+
E = tkinter.E
|
|
98
|
+
SW = tkinter.SW
|
|
99
|
+
S = tkinter.S
|
|
100
|
+
SE = tkinter.SE
|
|
101
|
+
ARC = tkinter.ARC
|
|
102
|
+
CHORD = tkinter.CHORD
|
|
103
|
+
PIESLICE = tkinter.PIESLICE
|
|
104
|
+
|
|
105
|
+
#----------------------------------
|
|
106
|
+
class onTimerCall():
|
|
107
|
+
def __init__(self, _func, _timeInterval):
|
|
108
|
+
self.func = _func
|
|
109
|
+
self.timeInterval = _timeInterval
|
|
110
|
+
self.active = True
|
|
111
|
+
#----------------------------------
|
|
112
|
+
def __initGraph__():
|
|
113
|
+
global _win, _C, _Cw, _Ch, _Cpos
|
|
114
|
+
global _pos, _penColor, _brushColor, _penSize
|
|
115
|
+
global _timerCalls, _viewPort
|
|
116
|
+
global _images
|
|
117
|
+
_win = tkinter.Tk()
|
|
118
|
+
_win.configure(bg="lightgray")
|
|
119
|
+
_win.geometry(str(DEF_GRAPH_WIDTH)+"x"+
|
|
120
|
+
str(DEF_GRAPH_HEIGHT)+"+100+100")
|
|
121
|
+
_viewPort = None
|
|
122
|
+
_Cw = DEF_GRAPH_WIDTH
|
|
123
|
+
_Ch = DEF_GRAPH_HEIGHT
|
|
124
|
+
_C = tkinter.Canvas(_win, background='white', bd=0, highlightthickness=0,
|
|
125
|
+
width=_Cw, height=_Ch)
|
|
126
|
+
_Cpos = [0, 0]
|
|
127
|
+
_C.place(x = _Cpos[0], y = _Cpos[1])
|
|
128
|
+
_penColor = "black"
|
|
129
|
+
_penSize = 1
|
|
130
|
+
_brushColor = ""
|
|
131
|
+
_pos = (0,0)
|
|
132
|
+
_timerCalls = []
|
|
133
|
+
_images = []
|
|
134
|
+
#----------------------------------
|
|
135
|
+
def mainWindow():
|
|
136
|
+
return _win
|
|
137
|
+
def canvas():
|
|
138
|
+
return _C
|
|
139
|
+
#----------------------------------
|
|
140
|
+
def canvasPos(x = -1, y = -1):
|
|
141
|
+
global _C, _Cpos
|
|
142
|
+
if x >= 0:
|
|
143
|
+
_C.place(x = x, y = y)
|
|
144
|
+
_Cpos = [x, y]
|
|
145
|
+
else:
|
|
146
|
+
return tuple(_Cpos)
|
|
147
|
+
#----------------------------------
|
|
148
|
+
def canvasSize(w = -1, h = -1):
|
|
149
|
+
global _C, _Cw, _Ch
|
|
150
|
+
if w > 0:
|
|
151
|
+
_C.config(width = w, height = h)
|
|
152
|
+
windowSize( w, h )
|
|
153
|
+
_Cw = w
|
|
154
|
+
_Ch = h
|
|
155
|
+
else:
|
|
156
|
+
return (_Cw, _Ch)
|
|
157
|
+
#----------------------------------
|
|
158
|
+
def pointInView(x, y):
|
|
159
|
+
w, h = windowSize()
|
|
160
|
+
return (x > 0 and y > 0 and x < h and y < h)
|
|
161
|
+
def circleInView(x, y, r):
|
|
162
|
+
w, h = windowSize()
|
|
163
|
+
return (x > r and y > r and x < w-r and y < h-r)
|
|
164
|
+
#----------------------------------
|
|
165
|
+
def windowSize(w = -1, h = -1):
|
|
166
|
+
global _win
|
|
167
|
+
_win.update()
|
|
168
|
+
geom = _win.geometry().split("+")
|
|
169
|
+
if w != -1:
|
|
170
|
+
_win.geometry( "%dx%d+%s+%s" % (w, h, geom[1], geom[2]) )
|
|
171
|
+
else:
|
|
172
|
+
w, h = map(int, geom[0].split("x"))
|
|
173
|
+
return (w, h)
|
|
174
|
+
#----------------------------------
|
|
175
|
+
def viewCoords(x1 = None, x2 = -1, y1 = -1, y2 = -1):
|
|
176
|
+
global _viewPort
|
|
177
|
+
if ~(x1 is None):
|
|
178
|
+
_viewPort = (x1, x2, y1, y2)
|
|
179
|
+
else:
|
|
180
|
+
geom = windowSize()
|
|
181
|
+
_viewPort = None
|
|
182
|
+
#----------------------------------
|
|
183
|
+
def penColor(c = -1, g = -1, b = -1):
|
|
184
|
+
global _penColor
|
|
185
|
+
if type(c) == tuple: c, g, b = c
|
|
186
|
+
if c != -1:
|
|
187
|
+
if g != -1:
|
|
188
|
+
c = "#%02X%02X%02X" % (c, g, b)
|
|
189
|
+
_penColor = c
|
|
190
|
+
else:
|
|
191
|
+
return _penColor
|
|
192
|
+
#----------------------------------
|
|
193
|
+
def penSize(c = -1):
|
|
194
|
+
global _penSize
|
|
195
|
+
if c != -1:
|
|
196
|
+
_penSize = c
|
|
197
|
+
else:
|
|
198
|
+
return _penSize
|
|
199
|
+
#----------------------------------
|
|
200
|
+
def brushColor(c = -1, g = -1, b = -1):
|
|
201
|
+
global _brushColor
|
|
202
|
+
if type(c) == tuple: c, g, b = c
|
|
203
|
+
if c != -1 :
|
|
204
|
+
if c != "":
|
|
205
|
+
if g != -1:
|
|
206
|
+
c = "#%02X%02X%02X" % (c, g, b)
|
|
207
|
+
_brushColor = c
|
|
208
|
+
else:
|
|
209
|
+
return _brushColor
|
|
210
|
+
#----------------------------------
|
|
211
|
+
def randColor():
|
|
212
|
+
r = randint(0, 255)
|
|
213
|
+
g = randint(0, 255)
|
|
214
|
+
b = randint(0, 255)
|
|
215
|
+
col = "#%02X%02X%02X" % (r, g, b)
|
|
216
|
+
return col
|
|
217
|
+
#----------------------------------
|
|
218
|
+
def transformCoord(x, y):
|
|
219
|
+
global _viewPort
|
|
220
|
+
if _viewPort:
|
|
221
|
+
x1, x2, y1, y2 = _viewPort
|
|
222
|
+
w, h = windowSize()
|
|
223
|
+
x = (x - x1)*w/(x2 - x1)
|
|
224
|
+
y = (y2 - y)*h/(y2 - y1)
|
|
225
|
+
return x, y
|
|
226
|
+
#----------------------------------
|
|
227
|
+
def moveTo(x, y = -1):
|
|
228
|
+
global _pos
|
|
229
|
+
if type(x) == tuple: x, y = x
|
|
230
|
+
x, y = transformCoord(x, y)
|
|
231
|
+
_pos = (x, y)
|
|
232
|
+
#----------------------------------
|
|
233
|
+
def lineTo(x, y = -1):
|
|
234
|
+
global _pos
|
|
235
|
+
if type(x) == tuple: x, y = x
|
|
236
|
+
x, y = transformCoord ( x, y )
|
|
237
|
+
line = _C.create_line(_pos[0], _pos[1], x, y,
|
|
238
|
+
fill = _penColor,
|
|
239
|
+
width = _penSize )
|
|
240
|
+
_pos = (x, y)
|
|
241
|
+
return line
|
|
242
|
+
#----------------------------------
|
|
243
|
+
def point(x, y, col = -1):
|
|
244
|
+
old_col = penColor()
|
|
245
|
+
if col != -1: penColor(col)
|
|
246
|
+
moveTo(x, y)
|
|
247
|
+
pt = lineTo(x+1,y)
|
|
248
|
+
penColor(old_col)
|
|
249
|
+
return pt
|
|
250
|
+
#----------------------------------
|
|
251
|
+
def line(x1, y1, x2, y2):
|
|
252
|
+
x1, y1 = transformCoord ( x1, y1 )
|
|
253
|
+
x2, y2 = transformCoord ( x2, y2 )
|
|
254
|
+
line = _C.create_line(x1, y1, x2, y2,
|
|
255
|
+
fill = _penColor,
|
|
256
|
+
width = _penSize)
|
|
257
|
+
return line
|
|
258
|
+
#----------------------------------
|
|
259
|
+
def unpackCoord(points):
|
|
260
|
+
coord = []
|
|
261
|
+
for p in points:
|
|
262
|
+
x, y = transformCoord(p[0], p[1])
|
|
263
|
+
coord.extend( (x, y) )
|
|
264
|
+
return coord
|
|
265
|
+
#----------------------------------
|
|
266
|
+
def polyline(points):
|
|
267
|
+
coord = unpackCoord(points)
|
|
268
|
+
line = _C.create_line(*coord,
|
|
269
|
+
fill = _penColor,
|
|
270
|
+
width = _penSize)
|
|
271
|
+
return line
|
|
272
|
+
#----------------------------------
|
|
273
|
+
def rectangle(x1, y1, x2, y2):
|
|
274
|
+
x1, y1 = transformCoord ( x1, y1 )
|
|
275
|
+
x2, y2 = transformCoord ( x2, y2 )
|
|
276
|
+
rect = _C.create_rectangle(x1, y1, x2, y2,
|
|
277
|
+
outline = _penColor,
|
|
278
|
+
width = _penSize,
|
|
279
|
+
fill = _brushColor)
|
|
280
|
+
return rect
|
|
281
|
+
#----------------------------------
|
|
282
|
+
def circle(x, y, R):
|
|
283
|
+
x1 = x - R; y1 = y - R
|
|
284
|
+
x2 = x + R; y2 = y + R
|
|
285
|
+
return oval(x1, y1, x2, y2)
|
|
286
|
+
#----------------------------------
|
|
287
|
+
def oval(x1, y1, x2, y2):
|
|
288
|
+
x1, y1 = transformCoord ( x1, y1 )
|
|
289
|
+
x2, y2 = transformCoord ( x2, y2 )
|
|
290
|
+
_oval = _C.create_oval(x1, y1, x2, y2,
|
|
291
|
+
outline = _penColor,
|
|
292
|
+
width = _penSize,
|
|
293
|
+
fill = _brushColor)
|
|
294
|
+
return _oval
|
|
295
|
+
#----------------------------------
|
|
296
|
+
def arc(x1, y1, x2, y2, start, end, style = PIESLICE):
|
|
297
|
+
x1, y1 = transformCoord ( x1, y1 )
|
|
298
|
+
x2, y2 = transformCoord ( x2, y2 )
|
|
299
|
+
_arc = _C.create_arc(x1, y1, x2, y2,
|
|
300
|
+
start = start, extent = end - start,
|
|
301
|
+
style = style,
|
|
302
|
+
outline = _penColor,
|
|
303
|
+
width = _penSize,
|
|
304
|
+
fill = _brushColor)
|
|
305
|
+
return _arc
|
|
306
|
+
#----------------------------------
|
|
307
|
+
def polygon(points):
|
|
308
|
+
coord = unpackCoord(points)
|
|
309
|
+
if points[0] != points[-1]:
|
|
310
|
+
points.append( points[0] )
|
|
311
|
+
plg = _C.create_polygon(*coord,
|
|
312
|
+
outline=_penColor, width = _penSize,
|
|
313
|
+
fill=_brushColor)
|
|
314
|
+
return plg
|
|
315
|
+
#----------------------------------
|
|
316
|
+
def image(x, y, fileName, anchor = NW, **kwargs):
|
|
317
|
+
if type(x) == tuple:
|
|
318
|
+
fileName = y
|
|
319
|
+
x, y = x
|
|
320
|
+
x, y = transformCoord ( x, y )
|
|
321
|
+
try:
|
|
322
|
+
if fileName.lower().endswith('.gif'):
|
|
323
|
+
newImage = tkinter.PhotoImage(file = fileName)
|
|
324
|
+
else:
|
|
325
|
+
im = Image.open(fileName)
|
|
326
|
+
newImage = ImageTk.PhotoImage(im)
|
|
327
|
+
except:
|
|
328
|
+
pass
|
|
329
|
+
img = _C.create_image(x, y, image = newImage, anchor = anchor, **kwargs)
|
|
330
|
+
_images.append( (img, newImage) )
|
|
331
|
+
return img
|
|
332
|
+
#----------------------------------
|
|
333
|
+
def text(_text, _x, _y, **kwargs):
|
|
334
|
+
_textLabel = _C.create_text( _x, _y, text = _text, anchor = NW, fill = _penColor, **kwargs )
|
|
335
|
+
return _textLabel
|
|
336
|
+
#----------------------------------
|
|
337
|
+
def label(_text, _x, _y, **kwargs):
|
|
338
|
+
kwargs["bg"] = kwargs.get("bg", "white")
|
|
339
|
+
lbl = tkinter.Label(_win, text = _text, **kwargs)
|
|
340
|
+
_x, _y = transformCoord(_x, _y)
|
|
341
|
+
lbl.place(x = _x, y = _y)
|
|
342
|
+
return lbl
|
|
343
|
+
#----------------------------------
|
|
344
|
+
def checkbox(_text, _x, _y, **kwargs):
|
|
345
|
+
def _setChecked(self, value):
|
|
346
|
+
self.var.set(value)
|
|
347
|
+
print('set', value)
|
|
348
|
+
kwargs["bg"] = kwargs.get("bg", "white")
|
|
349
|
+
cbx = tkinter.Checkbutton( _win, text = _text, **kwargs )
|
|
350
|
+
cbx.var = tkinter.IntVar()
|
|
351
|
+
cbx["variable"] = cbx.var
|
|
352
|
+
tkinter.Checkbutton.checked = property( lambda x: x.var.get(), _setChecked )
|
|
353
|
+
_x, _y = transformCoord(_x, _y)
|
|
354
|
+
cbx.place(x = _x, y = _y)
|
|
355
|
+
return cbx
|
|
356
|
+
#----------------------------------
|
|
357
|
+
def button(_text, _x, _y, **kwargs):
|
|
358
|
+
btn = tkinter.Button(_win, text = _text, **kwargs)
|
|
359
|
+
_x, _y = transformCoord(_x, _y)
|
|
360
|
+
btn.place(x = _x, y = _y)
|
|
361
|
+
return btn
|
|
362
|
+
#----------------------------------
|
|
363
|
+
def edit(_text, _x, _y, **kwargs):
|
|
364
|
+
textVar = tkinter.StringVar()
|
|
365
|
+
textVar.set(_text)
|
|
366
|
+
edt = tkinter.Entry(_win, textvariable = textVar, **kwargs)
|
|
367
|
+
edt.text = textVar
|
|
368
|
+
_x, _y = transformCoord(_x, _y)
|
|
369
|
+
edt.place(x = _x, y = _y)
|
|
370
|
+
return edt
|
|
371
|
+
#----------------------------------
|
|
372
|
+
def coords(obj):
|
|
373
|
+
allCoords = _C.coords(obj)
|
|
374
|
+
if len(allCoords) == 2:
|
|
375
|
+
img = [x for x in _images if x[0] == obj]
|
|
376
|
+
if img:
|
|
377
|
+
image = img[0][1]
|
|
378
|
+
allCoords += [allCoords[0]+image.width(), allCoords[1]+image.height()]
|
|
379
|
+
elif len(allCoords) > 4: # polygon
|
|
380
|
+
allCoords = [ min(allCoords[::2]), min(allCoords[1::2]),
|
|
381
|
+
max(allCoords[::2]), max(allCoords[1::2]) ]
|
|
382
|
+
return allCoords
|
|
383
|
+
#----------------------------------
|
|
384
|
+
def width(obj):
|
|
385
|
+
x, y, x1, y1 = coords(obj)
|
|
386
|
+
return x1 - x + 1
|
|
387
|
+
#----------------------------------
|
|
388
|
+
def height(obj):
|
|
389
|
+
x, y, x1, y1 = coords(obj)
|
|
390
|
+
return y1 - y + 1
|
|
391
|
+
#----------------------------------
|
|
392
|
+
def bbox(obj):
|
|
393
|
+
return _C.bbox(obj) #(+ border!)
|
|
394
|
+
#----------------------------------
|
|
395
|
+
def center(obj):
|
|
396
|
+
x1, y1, x2, y2 = coords(obj)
|
|
397
|
+
return (x1+x2)/2, (y1+y2)/2
|
|
398
|
+
#----------------------------------
|
|
399
|
+
def xCoord(obj):
|
|
400
|
+
if hasattr(obj,'winfo_x'): # label
|
|
401
|
+
x1 = int(obj.place_info()['x'])
|
|
402
|
+
else:
|
|
403
|
+
x1, y1, x2, y2 = coords(obj)
|
|
404
|
+
return x1
|
|
405
|
+
#----------------------------------
|
|
406
|
+
def yCoord(obj):
|
|
407
|
+
if hasattr(obj,'winfo_x'): # label
|
|
408
|
+
y1 = int(obj.place_info()['y'])
|
|
409
|
+
else:
|
|
410
|
+
x1, y1, x2, y2 = coords(obj)
|
|
411
|
+
return y1
|
|
412
|
+
#----------------------------------
|
|
413
|
+
def overlapRect(obj, x1, y1, x2, y2):
|
|
414
|
+
return obj in _C.find_overlapping( x1, y1, x2, y2 )
|
|
415
|
+
#----------------------------------
|
|
416
|
+
def overlap(obj1, obj2):
|
|
417
|
+
try:
|
|
418
|
+
x1, y1, x2, y2 = coords(obj2)
|
|
419
|
+
return obj1 in _C.find_overlapping( x1, y1, x2, y2 )
|
|
420
|
+
except:
|
|
421
|
+
return False
|
|
422
|
+
#----------------------------------
|
|
423
|
+
def moveObjectTo(obj, x, y):
|
|
424
|
+
x, y = transformCoord(x, y)
|
|
425
|
+
if hasattr(obj,'winfo_x'): # label
|
|
426
|
+
obj.place(x=x, y=y)
|
|
427
|
+
else:
|
|
428
|
+
coords = _C.coords(obj)
|
|
429
|
+
_C.move(obj, x-coords[0], y-coords[1])
|
|
430
|
+
#----------------------------------
|
|
431
|
+
def moveObjectBy(obj, dx, dy):
|
|
432
|
+
if _viewPort:
|
|
433
|
+
x1, x2, y1, y2 = _viewPort
|
|
434
|
+
w, h = windowSize()
|
|
435
|
+
dx = dx*w/(x2 - x1)
|
|
436
|
+
dy = - dy*h/(y2 - y1)
|
|
437
|
+
if hasattr(obj,'winfo_x'): # label
|
|
438
|
+
x0 = int(obj.place_info()['x'])
|
|
439
|
+
y0 = int(obj.place_info()['y'])
|
|
440
|
+
obj.place(x=x0+dx, y=y0+dy)
|
|
441
|
+
else:
|
|
442
|
+
_C.move(obj, dx, dy)
|
|
443
|
+
#----------------------------------
|
|
444
|
+
def deleteObject(obj):
|
|
445
|
+
_C.delete(obj)
|
|
446
|
+
#----------------------------------
|
|
447
|
+
def changeCoords(obj, points):
|
|
448
|
+
coord = unpackCoord(points)
|
|
449
|
+
_C.coords(obj, *coord)
|
|
450
|
+
#----------------------------------
|
|
451
|
+
def changeProperty(obj, **kwargs):
|
|
452
|
+
_C.itemconfigure(obj, **kwargs)
|
|
453
|
+
#----------------------------------
|
|
454
|
+
def changePenColor(obj, color):
|
|
455
|
+
_C.itemconfigure(obj, outline=color)
|
|
456
|
+
#----------------------------------
|
|
457
|
+
def changeFillColor(obj, color):
|
|
458
|
+
_C.itemconfigure(obj, fill=color)
|
|
459
|
+
#----------------------------------
|
|
460
|
+
def onMouseEvent(eventName, fn = None, btn = 0):
|
|
461
|
+
eventStr = "<%s>" % eventName
|
|
462
|
+
if btn == 0:
|
|
463
|
+
if type(fn) == int:
|
|
464
|
+
btn = fn
|
|
465
|
+
fn = None
|
|
466
|
+
if btn > 0:
|
|
467
|
+
eventStr = "<%s-%d>" % (eventName, btn)
|
|
468
|
+
_C.bind(eventStr, fn);
|
|
469
|
+
listen()
|
|
470
|
+
#----------------------------------
|
|
471
|
+
def onMouseMove(fn = None):
|
|
472
|
+
_C.bind("<Motion>", fn);
|
|
473
|
+
listen()
|
|
474
|
+
def onMouseButtonMove(fn = None, btn = 0):
|
|
475
|
+
_C.bind("<B1-Motion>", fn);
|
|
476
|
+
listen()
|
|
477
|
+
def onMouseDown(fn = None, btn = 0):
|
|
478
|
+
onMouseEvent("Button", fn, btn)
|
|
479
|
+
def onMouseUp(fn = None, btn = 0):
|
|
480
|
+
onMouseEvent("ButtonRelease", fn, btn)
|
|
481
|
+
def onMouseClick(fn = None, btn = 0):
|
|
482
|
+
onMouseUp(fn, btn)
|
|
483
|
+
def onMouseDblClick(fn = None, btn = 0):
|
|
484
|
+
onMouseEvent("Double-Button", fn, btn)
|
|
485
|
+
#----------------------------------
|
|
486
|
+
def onMouseUp(fn = None, btn = 0):
|
|
487
|
+
eventStr = "<ButtonRelease>"
|
|
488
|
+
if btn == 0:
|
|
489
|
+
if type(fn) == int:
|
|
490
|
+
btn = fn
|
|
491
|
+
fn = None
|
|
492
|
+
if btn > 0:
|
|
493
|
+
eventStr = "<ButtonRelease-%d>" % btn
|
|
494
|
+
_C.bind(eventStr, fn);
|
|
495
|
+
listen()
|
|
496
|
+
#----------------------------------
|
|
497
|
+
def onKey(keyStr, fn = None):
|
|
498
|
+
if type(keyStr) == str:
|
|
499
|
+
_C.bind("<KeyPress-%s>" % keyStr, fn);
|
|
500
|
+
else:
|
|
501
|
+
_C.bind("<KeyPress>", keyStr);
|
|
502
|
+
listen()
|
|
503
|
+
#----------------------------------
|
|
504
|
+
def listen():
|
|
505
|
+
_C.focus_force()
|
|
506
|
+
#----------------------------------
|
|
507
|
+
def onTimer(func, _time = -1):
|
|
508
|
+
global _timerCalls
|
|
509
|
+
if _time < 0: _time = 30
|
|
510
|
+
timerId = onTimerCall(func, _time)
|
|
511
|
+
_timerCalls.append( timerId )
|
|
512
|
+
return timerId
|
|
513
|
+
#----------------------------------
|
|
514
|
+
def killTimer(timerId):
|
|
515
|
+
global _timerCalls
|
|
516
|
+
if timerId in _timerCalls:
|
|
517
|
+
_timerCalls.remove( timerId )
|
|
518
|
+
timerId.active = False
|
|
519
|
+
#----------------------------------
|
|
520
|
+
def runLoopFunc(timerCall):
|
|
521
|
+
def timerFunc():
|
|
522
|
+
if timerCall.active:
|
|
523
|
+
timerCall.func()
|
|
524
|
+
_win.after(timerCall.timeInterval, timerFunc)
|
|
525
|
+
return timerFunc
|
|
526
|
+
#----------------------------------
|
|
527
|
+
def run():
|
|
528
|
+
for timerCall in _timerCalls:
|
|
529
|
+
runLoopFunc(timerCall)()
|
|
530
|
+
_win.mainloop()
|
|
531
|
+
#----------------------------------
|
|
532
|
+
def close():
|
|
533
|
+
_win.destroy()
|
|
534
|
+
|
|
535
|
+
###########################################
|
|
536
|
+
__initGraph__()
|
|
537
|
+
if __name__ == "__main__":
|
|
538
|
+
windowSize ( 500, 250 )
|
|
539
|
+
|
|
540
|
+
for i in range(0, 100, 10):
|
|
541
|
+
line(0, 0, 100, i)
|
|
542
|
+
|
|
543
|
+
penColor("red")
|
|
544
|
+
for i in range(200, 100, -10):
|
|
545
|
+
brushColor( randint(0,255),randint(0,255),randint(0,255))
|
|
546
|
+
rectangle(100, 100, i, i)
|
|
547
|
+
|
|
548
|
+
penColor("blue")
|
|
549
|
+
for i in range(100, 0, -10):
|
|
550
|
+
brushColor( randint(0,255),randint(0,255),randint(0,255))
|
|
551
|
+
circle(300, 100, i)
|
|
552
|
+
|
|
553
|
+
penColor("red")
|
|
554
|
+
for i in range(10, 100, 10):
|
|
555
|
+
brushColor( randint(0,255),randint(0,255),randint(0,255))
|
|
556
|
+
polygon([(70,100), (150,i), (230,100), (70,100)])
|
|
557
|
+
|
|
558
|
+
run()
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: kpolyakov-graph
|
|
3
|
+
Version: 1.5.2
|
|
4
|
+
Summary: Graph - tkinter-based framework for simple Python graphics
|
|
5
|
+
Home-page: http://kpolyakov.spb.ru/school/probook/python.htm
|
|
6
|
+
Download-URL: http://kpolyakov.spb.ru/school/probook/python.htm
|
|
7
|
+
Author: Konstantin Polyakov
|
|
8
|
+
Author-email: kpolyakov@mail.ru
|
|
9
|
+
Maintainer: Konstantin Polyakov
|
|
10
|
+
Maintainer-email: kpolyakov@mail.ru
|
|
11
|
+
License:
|
|
12
|
+
Licensed under MIT licence.
|
|
13
|
+
|
|
14
|
+
Keywords: application,framework,tkinter,graphics
|
|
15
|
+
Classifier: Development Status :: 3 - Alpha
|
|
16
|
+
Classifier: Environment :: Other Environment
|
|
17
|
+
Classifier: Intended Audience :: Developers
|
|
18
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
19
|
+
Classifier: Operating System :: OS Independent
|
|
20
|
+
Classifier: Programming Language :: Python
|
|
21
|
+
Classifier: Programming Language :: Python :: 3
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.2
|
|
23
|
+
Classifier: Topic :: Software Development
|
|
24
|
+
Classifier: Topic :: Software Development :: Build Tools
|
|
25
|
+
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
|
|
26
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
27
|
+
Classifier: Topic :: Software Development :: User Interfaces
|
|
28
|
+
Dynamic: author
|
|
29
|
+
Dynamic: author-email
|
|
30
|
+
Dynamic: classifier
|
|
31
|
+
Dynamic: description
|
|
32
|
+
Dynamic: download-url
|
|
33
|
+
Dynamic: home-page
|
|
34
|
+
Dynamic: keywords
|
|
35
|
+
Dynamic: license
|
|
36
|
+
Dynamic: maintainer
|
|
37
|
+
Dynamic: maintainer-email
|
|
38
|
+
Dynamic: summary
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
Graph: tkinter-based framework for simple graphics
|
|
42
|
+
|
|
43
|
+
`Graph` is a **Python3.2+** library designed to simplifying
|
|
44
|
+
coordinate graphics on the basis of tkinter library.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
graph
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
from setuptools import setup
|
|
3
|
+
setup(
|
|
4
|
+
name='kpolyakov-graph',
|
|
5
|
+
version='1.5.2',
|
|
6
|
+
py_modules=['graph'],
|
|
7
|
+
description = "Graph - tkinter-based framework for simple Python graphics",
|
|
8
|
+
author = "Konstantin Polyakov",
|
|
9
|
+
author_email = "kpolyakov@mail.ru",
|
|
10
|
+
maintainer = "Konstantin Polyakov",
|
|
11
|
+
maintainer_email = "kpolyakov@mail.ru",
|
|
12
|
+
url = "http://kpolyakov.spb.ru/school/probook/python.htm",
|
|
13
|
+
download_url = "http://kpolyakov.spb.ru/school/probook/python.htm",
|
|
14
|
+
keywords = ["application", "framework", "tkinter", "graphics"],
|
|
15
|
+
classifiers = [
|
|
16
|
+
"Development Status :: 3 - Alpha",
|
|
17
|
+
"Environment :: Other Environment",
|
|
18
|
+
"Intended Audience :: Developers",
|
|
19
|
+
"License :: OSI Approved :: MIT License",
|
|
20
|
+
"Operating System :: OS Independent",
|
|
21
|
+
"Programming Language :: Python",
|
|
22
|
+
"Programming Language :: Python :: 3",
|
|
23
|
+
"Programming Language :: Python :: 3.2",
|
|
24
|
+
"Topic :: Software Development",
|
|
25
|
+
"Topic :: Software Development :: Build Tools",
|
|
26
|
+
"Topic :: Software Development :: Libraries :: Application Frameworks",
|
|
27
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
28
|
+
"Topic :: Software Development :: User Interfaces",
|
|
29
|
+
],
|
|
30
|
+
license = """
|
|
31
|
+
Licensed under MIT licence.
|
|
32
|
+
""",
|
|
33
|
+
long_description = """
|
|
34
|
+
Graph: tkinter-based framework for simple graphics
|
|
35
|
+
|
|
36
|
+
`Graph` is a **Python3.2+** library designed to simplifying
|
|
37
|
+
coordinate graphics on the basis of tkinter library.
|
|
38
|
+
"""
|
|
39
|
+
)
|