Module gpanel
[frames] | no frames]

Source Code for Module gpanel

   1  # gpanel.py 
   2  # Version 1.05; Jan 31, 2017 
   3   
   4  ''' 
   5  Module to create a graphics window of default size 501x501 pixels (client drawing area) 
   6  using a coordinate system with x-axis from left to right, y-axis from bottom to top 
   7  (called user coordinates, default range 0..1, 0..1). 
   8   
   9  The module provides a global namespace for GPanel class methods. It also contaisn 
  10  the class GPane that can be used to embed a GPanel graphics window together with 
  11  other widgets in a GUI application. 
  12   
  13  The drawing methods perform drawing operation in an offscreen buffer (QPixmap) 
  14  and automatically renders it on the screen, so the graphics is shown step-by-step. 
  15   
  16  User coordinates:  (ux, uy) 
  17  Pixel coordinates: (px, py) (screen pixels) 
  18  Transformation: px = px(ux), py = py(uy) 
  19  Pixel coordinate range: 0..winWidth - 1 (inclusive), 0..winHeight - 1 (inclusive); (0,0) upper left corner, x to the right, y downwards 
  20  User coordinate range: xmin..xmax (inclusive), ymin..ymax (inclusive); (0,0) lower left corner, x to the right, y upwards. 
  21   
  22  Transformation: user(ux, uy) to pixel(px, py): 
  23  (width = winWidth - 1, height = winHeight - 1) 
  24  px = a * ux + b 
  25  py = c * uy + d 
  26  with a = width / (xmax - xmin) 
  27  b = width * xmin / (xmin - xmax) 
  28  c = height / (ymin - ymax) 
  29  d = height * ymax / (ymax - ymin) 
  30   
  31  Inverse: 
  32  ux = (px - b) / a 
  33  uy = (py - d) / c 
  34   
  35  Because of the transformation from float to pixel coordinates, some rounding errors 
  36  may happen. If you need pixel accuracy, define a GPanel window with some user defined width x height, 
  37  e.g. makeGPanal(Size(501, 401)). Define then user coordinates in the range 0..width-1, 0..height-1, e.g. 
  38  window(0, 500, 0, 400). Now pixels in the range 0..500 x 0..400 (inclusive) may be addressed with no 
  39  rounding errors. (This is a total of 501 x 401 pixels.) 
  40   
  41  If you prefer a coordinate system with the origin at the upper left corner, define the y-range in reverse 
  42  order, e.g. window(0, 500, 400, 0). 
  43   
  44  WARNING: Because PyQt is not thread-safe, in principle all graphics drawings should be 
  45  executed in the GUI thread (for GPanel the main thread or a GUI callback). 
  46   
  47  In order to get notifications for keyboard and mouse callbacks, the main thread should 
  48  not be blocked otherwise than within the keep() function. 
  49   
  50  Typical program: 
  51   
  52  from pygpanel import * 
  53   
  54  makeGPanel(0, 10, 0, 10) 
  55  for ypt in range(0, 11, 1): 
  56      line(0, ypt, 10 - ypt, 0) 
  57      time.sleep(0.1) # to see what happens 
  58  keep() 
  59   
  60  keep() is blocking and keeps the graphics window open until the close button is hit or the 
  61  Python process terminates. 
  62  ''' 
  63   
  64  from __future__ import division 
  65  from PyQt4 import QtGui, QtCore 
  66  from PyQt4.QtGui import * 
  67  from PyQt4.QtCore import * 
  68  import thread 
  69  import sys, time, math 
  70  import random 
  71   
  72  _p = None 
  73  isTigerJython = False 
74 75 -class _WindowNotInitialized(Exception): pass
76
77 -def _isGPanelValid():
78 if _p == None: 79 raise _WindowNotInitialized("Use \"makeGPanel()\" to create the graphics window before calling GPanel methods.")
80
81 -def makeGPanel(*args, **kwargs):
82 ''' 83 Constructs a GPanel and displays a non-resizable graphics window. 84 Defaults with no parameter: 85 Window size: 501x501 pixels 86 Window title: "GPanel". 87 User coordinates: 0, 1, 0, 1. 88 Background color: white. 89 Pen color: black. 90 Pen size: 1. 91 92 1 Parameter: Size(window_width, window_height). 93 4 Parameters: xmin, xmax, ymin, ymax. 94 95 KEEP IN MIND: To use GUI callbacks, the main program must block in the keep() function. 96 @param Size: a Size reference to define the dimension of the graphics windows. 97 @param xmin: left x user coordinate 98 @param xmax: right x user coordinate 99 @param ymin: lower y user coordinate 100 @param ymax: upper y user coordinate 101 @param kwargs: mousePressed, mouseReleased, mouseDragged, keyPressed, keyReleased, closed 102 ''' 103 global _p 104 105 if _p == None: 106 _p = GPanel(*args) 107 108 for key in kwargs: 109 if key == "mousePressed": 110 _p.addMousePressListener(kwargs[key]) 111 elif key == "mouseReleased": 112 _p.addMouseReleaseListener(kwargs[key]) 113 elif key == "mouseDragged": 114 _p.addMouseDragListener(kwargs[key]) 115 elif key == "keyPressed": 116 _p.addKeyPressListener(kwargs[key]) 117 elif key == "keyReleased": 118 _p.addKeyReleaseListener(kwargs[key]) 119 elif key == "closed": 120 _p.addCloseListener(kwargs[key]) 121 return _p
122
123 -def addCloseListener(closeListener):
124 ''' 125 Registers the given function that is called when the title bar 126 close button is hit. 127 128 If a listener (!= None) is registered, the automatic closing is disabled. 129 To close the window, call sys.exit(). 130 131 KEEP IN MIND: To use GUI callbacks, the main program must block in the keep() function. 132 @param closeListener: a callback function called when the close button is hit 133 ''' 134 _isGPanelValid() 135 _p.addCloseListener(closeListener)
136
137 -def addKeyPressListener(onKeyPressed):
138 ''' 139 Registers a callback that is invoked when a key is pressed (and the graphics window has the focus). 140 141 KEEP IN MIND: To use GUI callbacks, the main program must block in the keep() function. 142 @param onKeyPressed: a callback function called when a key is pressed 143 ''' 144 _isGPanelValid() 145 _p.addKeyPressListener(onKeyPressed)
146
147 -def addKeyReleaseListener(onKeyReleased):
148 ''' 149 Registers a callback that is invoked when a key is released (and the graphics window has the focus). 150 151 KEEP IN MIND: To use GUI callbacks, the main program must block in the keep() function. 152 @param onKeyReleased: a callback function called when a key is pressed 153 ''' 154 _isGPanelValid() 155 _p.addKeyReleaseListener(onKeyReleased)
156
157 -def addMouseDragListener(onMouseDragged):
158 ''' 159 Registers a callback that is invoked when the mouse is moved while a mouse button is pressed (drag). 160 161 KEEP IN MIND: To use GUI callbacks, the main program must block in the keep() function. 162 @param onMouseDragged: a callback function called when the moused is dragged 163 ''' 164 _isGPanelValid() 165 _p.addMouseMoveListener(onMouseDragged)
166
167 -def addMousePressListener(onMousePressed):
168 ''' 169 Registers a callback that is invoked when a mouse button is pressed. 170 Use isLeftMouseButton() or isRightMouseButton() to check which button used. 171 172 KEEP IN MIND: To use GUI callbacks, the main program must block in the keep() function. 173 @param onMousePressed: a callback function called when a mouse button is pressed 174 ''' 175 _isGPanelValid() 176 _p.addMousePressListener(onMousePressed)
177
178 -def addMouseReleaseListener(onMouseReleased):
179 ''' 180 Registers a callback that is invoked when a mouse button is releases. 181 Use isLeftMouseButton() or isRightMouseButton() to check which button used. 182 183 KEEP IN MIND: To use GUI callbacks, the main program must block in the keep() function. 184 @param onMouseReleased: a callback function called when a mouse button is released 185 ''' 186 _isGPanelValid() 187 _p.addMouseReleaseListener(onMouseReleased)
188
189 -def arc(radius, startAngle, spanAngle):
190 ''' 191 Draws a circle sector with center at the current graph cursor position, 192 given radius and given start and span angles. 193 @param radius: the radius of the arc 194 @param startAngle: starting angle in degrees, zero to east, positive counter-clockwise 195 @param spanAngle: span angle (sector angle) in degrees, positive counter-clockwise 196 ''' 197 _isGPanelValid() 198 _p.arc(radius, startAngle, spanAngle)
199
200 -def bgColor(*args):
201 ''' 202 Same as setBgColor(). 203 ''' 204 setBgColor(*args)
205
206 -def chord(radius, startAngle, spanAngle):
207 ''' 208 Draws a circle chord with center at the current graph cursor position, 209 given radius and given start and span angles (in degrees, positive 210 counter-clockwise, zero to east). 211 @param radius: the radius of the arc 212 @param startAngle: starting angle in degrees, zero to east, positive counter-clockwise 213 @param spanAngle: span angle (sector angle) in degrees, positive counter-clockwise 214 ''' 215 _isGPanelValid() 216 _p.chord(radius, startAngle, spanAngle)
217
218 -def circle(radius):
219 ''' 220 Draws a circle with center at the current graph cursor position 221 with given radius in horizontal window coordinates. 222 @param radius: the radius of the circle 223 ''' 224 _isGPanelValid() 225 _p.circle(radius)
226
227 -def clear():
228 ''' 229 Clears the graphics window and the offscreen buffer used by the window 230 (fully paint with background color). 231 Sets the current graph cursor position to (0, 0). 232 If enableRepaint(false) only clears the offscreen buffer. 233 ''' 234 _isGPanelValid() 235 _p.clear()
236
237 -def delay(delayTime):
238 ''' 239 Stop execution for given delay time. 240 @param delayTime: the delay time (in ms) 241 ''' 242 time.sleep(delayTime / 1000.0)
243
244 -def draw(*args):
245 ''' 246 Draws a line form current graph cursor position to (x, y). 247 Sets the graph cursor position to (x, y). 248 Also with one parameter of type complex, list or tuple. 249 @param x: the x coordinate of the target point 250 @param y: the y coordinate of the target point 251 @param target: (alternative) the target point as complex, list or tuple 252 ''' 253 x, y = _getCoords(*args) 254 _isGPanelValid() 255 _p.draw(x, y)
256
257 -def drawGrid(*args):
258 ''' 259 Draws a coordinate system with annotated axes. 260 (You must increase the user coordinate system at least 10% in both directions.) 261 262 Overloaded variants: 263 264 drawGrid(x, y): Grid with 10 ticks in range 0..x, 0..y. Label text depends if x, y or int or float 265 266 drawGrid(x, y, color): same with given grid color 267 268 drawGrid(x1, x2, y1, y2): same with given span x1..x2, y1..y2 269 270 drawGrid(x1, x2, y1, y2, color): same with given grid color 271 272 drawGrid(x1, x2, y1, y2, x3, y3): same with given number of ticks x3, y3 in x- and y-direction 273 ''' 274 _isGPanelValid() 275 _p.drawGrid(*args)
276
277 -def ellipse(a, b):
278 ''' 279 Draws an ellipse with center at the current graph cursor position 280 with given axes. 281 @param a: the major ellipse axis 282 @param b: the minor ellipse axis 283 ''' 284 _isGPanelValid() 285 _p.ellipse(a, b)
286
287 -def enableRepaint(enable):
288 ''' 289 Enables/Disables automatic repaint in graphics drawing methods. 290 @param enable: if True, the automatic repaint is enabled; otherwise disabled 291 ''' 292 _isGPanelValid() 293 _p.enableRepaint(enable)
294
295 -def erase():
296 ''' 297 Same as clear(), but lets the current graph cursor unganged. 298 ''' 299 _isGPanelValid() 300 _p.erase()
301
302 -def fill(x, y, *args):
303 ''' 304 Fills the closed unicolored region with the inner point (x, y) with 305 the replacement color (RGB, RGBA or X11 color string). 306 The old color is not given, the color of the current (x, y) pixel is taken. 307 @param x: the x coordinate of the inner point 308 @param y: the y coordinate of the inner point 309 @param color: the old color (RGB list/tuple or X11 color string) (may be omitted) 310 @param replacementColor: the new color (RGB list/tuple or X11 color string) 311 ''' 312 _isGPanelValid() 313 _p.fill(x, y, *args)
314
315 -def fillArc(radius, startAngle, spanAngle):
316 ''' 317 Draws a filled circle sector with center at the current graph cursor position, 318 given radius and given start and span angles (in degrees, positive 319 counter-clockwise, zero to east). (fill color = pen color) 320 @param radius: the radius of the arc 321 @param startAngle: starting angle in degrees, zero to east, positive counter-clockwise 322 @param spanAngle: span angle (sector angle) in degrees, positive counter-clockwise 323 ''' 324 _isGPanelValid() 325 _p.fillArc(radius, startAngle, spanAngle)
326
327 -def fillChord(radius, startAngle, spanAngle):
328 ''' 329 Draws a filled circle chord with center at the current graph cursor position, 330 given radius and given start and span angles (in degrees, positive 331 counter-clockwise, zero to east). (fill color = pen color) 332 @param radius: the radius of the arc 333 @param startAngle: starting angle in degrees, zero to east, positive counter-clockwise 334 @param spanAngle: span angle (sector angle) in degrees, positive counter-clockwise 335 ''' 336 _isGPanelValid() 337 _p.fillChord(radius, startAngle, spanAngle)
338
339 -def fillCircle(radius):
340 ''' 341 Draws a filled circle with center at the current graph cursor position 342 with given radius in horizontal window coordinates (fill color = pen color). 343 @param radius: the radius of the circle 344 ''' 345 _isGPanelValid() 346 _p.fillCircle(radius)
347
348 -def fillEllipse(a, b):
349 ''' 350 Draws a filled ellipse with center at the current graph cursor position 351 with given axes (fill color = pen color). 352 @param a: the major ellipse axis 353 @param b: the minor ellipse axis 354 ''' 355 _isGPanelValid() 356 _p.fillEllipse(a, b)
357
358 -def fillPath(color):
359 ''' 360 Closes the path started with startPath() and shows a filled polygon from the saved 361 draw() positions with given color. 362 ''' 363 _isGPanelValid() 364 _p.fillPath(color)
365
366 -def fillPolygon(*args):
367 ''' 368 Draws a filled polygon with given list of vertexes (list of [x, y]) 369 (fill color = pen color). 370 1 parameter: a list/tuple of the corners [x, y] 371 2 parameters: two lists/tuples x, y of corresponding x-y pairs 372 ''' 373 _isGPanelValid() 374 _p.fillPolygon(*args)
375
376 -def fillRectangle(*args):
377 ''' 378 Draws a filled rectangle (fill color = pen color). 379 2 parameters: Center at the current graph cursor position 380 and given width and height 381 4 parameters: Given diagonal 382 ''' 383 _isGPanelValid() 384 _p.fillRectangle(*args)
385
386 -def fillTriangle(*args):
387 ''' 388 Draws a filled triangle with given corners. 389 6 parameters: x1, y1, x2, y2, x3, y3 coordinates of corners 390 3 parameters: [x1, y1], [x2, y2], [x3, y3] lists of corners 391 ''' 392 _isGPanelValid() 393 _p.fillTriangle(*args)
394
395 -def getDividingPoint(*args):
396 ''' 397 Returns the tuple of user coordinates of the point on the line through the point pt1 = (x1, y1) 398 and the point pt2 = (x2, y2) that is in distance ratio times the length from pt1 to pt2 from 399 pt1. For ratio < 0 the point is in the opposite direction. 400 3 parameteters: pt1, pt2 (complex/list/tuple), ratio 401 5 parameteters: x1, y1, x2, y2, ratio 402 ''' 403 if len(args) == 5: 404 x1 = args[0] 405 y1 = args[1] 406 x2 = args[2] 407 y2 = args[3] 408 ratio = args[4] 409 elif len(args) == 3: 410 x1, y1, x2, y2 = _get2Coords(args[0], args[1]) 411 ratio = args[2] 412 else: 413 raise ValueError("Illegal number of parameters.") 414 _isGPanelValid() 415 return _p.getDividingPoint(x1, y1, x2, y2, ratio)
416
417 -def getBitmap():
418 ''' 419 Returns the QImage of the complete graphics area. 420 (For compatiblity with TigerJython.) 421 ''' 422 _isGPanelValid() 423 return _p.getFullImage()
424
425 -def getFullImage():
426 ''' 427 Returns the QImage of the complete graphics area. 428 ''' 429 _isGPanelValid() 430 return _p.getFullImage()
431
432 -def getImage(filename):
433 ''' 434 Same as loadImage(filename) 435 (For compatiblity with TigerJython.) 436 ''' 437 return loadImage(filename)
438
439 -def loadImage(filename, pic_format = None):
440 ''' 441 Returns a QImage of the picture loaded from the given file. For pic_format = None, 442 the picture format is guessed from the file data. 443 @param: the file path to the picture file 444 @param pic_format: format of picture, supported: "None" (default), "GIF", "JPG", 445 "BMP", "PNG", "PBM", "PGM", "PPM", "TIFF", "XBM" "XPM". 446 ''' 447 return GPanel.loadImage(filename, pic_format)
448
449 -def getPainter():
450 ''' 451 Returns the QPainter reference used to draw into the offscreen buffer. 452 ''' 453 _isGPanelValid() 454 return _p.getPainter()
455
456 -def getPixelColor(*args):
457 ''' 458 Returns the RGBA color tuple of a pixel with given user coordinates. 459 No params: Returns color at current graph cursor position. 460 ''' 461 _isGPanelValid() 462 return _p.getPixelColor(*args)
463
464 -def getPixelColorStr(*args):
465 ''' 466 Returns the X11 color string of a pixel with given user coordinates. 467 No params: Returns color at current graph cursor position. 468 ''' 469 _isGPanelValid() 470 return _p.getPixelColorStr(*args)
471
472 -def getPos():
473 ''' 474 Returns a tuple with current graph cursor position (tuple, user coordinates). 475 ''' 476 _isGPanelValid() 477 return _p.getPos()
478
479 -def getPosX():
480 ''' 481 Returns the current graph cursor x-position (user coordinates). 482 @return: x coordinate of graph cursor 483 @rtype: float 484 ''' 485 _isGPanelValid() 486 return _p.getPosX()
487
488 -def getPosY():
489 ''' 490 Returns the current graph cursor y-position (user coordinates). 491 @return: y coordinate of graph cursor 492 @rtype: float 493 ''' 494 _isGPanelValid() 495 return _p.getPosY()
496
497 -def getScreenWidth():
498 ''' 499 Returns the width of the screen (in pixels). 500 @return: screen width 501 @rtype: int 502 ''' 503 return GPanel.getScreenWidth()
504
505 -def getScreenHeight():
506 ''' 507 Returns the height of the screen (in pixels). 508 @return: screen height 509 @rtype: int 510 ''' 511 return GPanel.getScreenHeight()
512
513 -def imageFromData(data, pic_format, x, y):
514 ''' 515 Draws the picture with given string data in JPEG format at user coordinates of lower left corner. 516 @param data: picture data stream in string format 517 @param pic_format: format of picture, supported: "GIF", "JPG", "BMP", "PNG", 518 "PBM", "PGM", "PPM", "TIFF", "XBM" "XPM" 519 @param x: x coordinate of lower left corner 520 @param y: y coordinate of lower left corner 521 @return: True, if operation is successful; otherwise false 522 @rtype: boolean 523 ''' 524 _isGPanelValid() 525 img = QImage() 526 rc = img.loadFromData(data, pic_format) 527 if rc: 528 image(img, x, y) 529 return True 530 return False
531
532 -def image(*args):
533 ''' 534 Draws the picture with given file path or given image at given upper-left coordinates. 535 1st parameter: image path (string) or QImage reference 536 2nd, 3rd parameters: llx, lly (lower left corner in user coordinates) 537 ''' 538 _isGPanelValid() 539 _p.showImage(*args)
540
541 -def isLeftMouseButton():
542 ''' 543 Returns True, if the last mouse action was performed with the left mouse button. 544 ''' 545 _isGPanelValid() 546 return _p.isLeftMouseButton()
547
548 -def isRightMouseButton():
549 ''' 550 Returns True, if the last mouse action was performed with the right mouse button. 551 ''' 552 _isGPanelValid() 553 return _p.isRightMouseButton()
554
555 -def keep():
556 ''' 557 Blocks until the title bar's close button is hit. Then cleans up 558 the graphics system. 559 ''' 560 _isGPanelValid() 561 _p.keep()
562
563 -def line(*args):
564 ''' 565 Draws a line with given user start and end coordinates 566 and sets the graph cursor position to the end point. 567 Also with 2 parameters of type complex, list or tuple. 568 4 parameters: x1, y1, x2, y2 569 2 parameters: pt1, pt2 as complex/list/tuple 570 ''' 571 x1, y1, x2, y2 = _get2Coords(*args) 572 _isGPanelValid() 573 _p.line(x1, y1, x2, y2)
574
575 -def lineWidth(width):
576 ''' 577 Sets the current pen size (width) (>=1). 578 Returns the previouis pen size. 579 580 Same as setPenSize(). For TigerJython compatiblity. 581 @param width: the pen width (>=1) 582 ''' 583 setPenSize(width)
584
585 -def makeColor(r, g, b):
586 ''' 587 Returns the tuple (r, g, b). For compatibility with TigerJython. 588 ''' 589 return (r, g, b)
590
591 -def move(*args):
592 ''' 593 Sets the current graph cursor position to given user coordinates. 594 (without drawing anything). 595 Also with 1 parameter of type complex, list or tuple. 596 597 Same as pos(). 598 @param x: the x coordinate of the target point 599 @param y: the y coordinate of the target point 600 @param target: (alternative) the target point as complex, list or tuple 601 ''' 602 pos(*args)
603
604 -def point(*args):
605 ''' 606 Draws a single point with current pen size and pen color at given user coordinates. 607 No params: draws a current graph cursor position 608 @param x: the x coordinate of the target point 609 @param y: the y coordinate of the target point 610 @param target: (alternative) the target point as complex, list or tuple 611 ''' 612 _isGPanelValid() 613 _p.point(*args)
614
615 -def linePlot(*args):
616 ''' 617 Draws a line plot with given x,y data. 618 1 parameter: a list/tuple of subsequent data points [x, y] 619 2 parameters: two lists/tuples x, y of corresponding x-y pairs 620 The graph cursor position remains unchanged. 621 ''' 622 _isGPanelValid() 623 _p.linePlot(*args)
624
625 -def pos(*args):
626 ''' 627 Sets the current graph cursor position to given user coordinates (x, y). 628 (without drawing anything). 629 Also with 1 parameter of type complex, list or tuple. 630 631 Same as move(). 632 @param x: the x coordinate of the target point 633 @param y: the y coordinate of the target point 634 @param target: (alternative) the target point as complex, list or tuple 635 ''' 636 x, y = _getCoords(*args) 637 _isGPanelValid() 638 _p.pos(x, y)
639
640 -def polygon(*args):
641 ''' 642 Draws a filled polygon with given list of vertexes (list of [x, y]) 643 (fill color = pen color). 644 1 parameter: a list/tuple of the corners [x, y] 645 2 parameters: two lists/tuples x, y of corresponding x-y pairs 646 ''' 647 _isGPanelValid() 648 _p.polygon(*args)
649
650 -def rectangle(*args):
651 ''' 652 Draws a rectangle. 653 2 parameters: Center at the current graph cursor position 654 and given width and height. 655 4 parameters: Given diagonal 656 ''' 657 _isGPanelValid() 658 _p.rectangle(*args)
659
660 -def repaint():
661 ''' 662 Renders the offscreen buffer in the graphics window. 663 ''' 664 _isGPanelValid() 665 _p.repaint()
666
667 -def recallGraphics():
668 ''' 669 Restores the saved graphics from the image buffer. Use saveGraphics() 670 to save it. 671 672 Same as restoreGraphics() (for TigerJython compatibility). 673 ''' 674 restoreGraphics()
675
676 677 -def restoreGraphics():
678 ''' 679 Restores the saved graphics from the image buffer. Use saveGraphics() 680 to save it. 681 ''' 682 _isGPanelValid() 683 _p.restoreGraphics()
684
685 -def saveGraphics():
686 ''' 687 Saves the current graphics into a image buffer. Use restoreGraphics() 688 to restore it. 689 ''' 690 _isGPanelValid() 691 _p.saveGraphics()
692
693 -def setBgColor(*args):
694 ''' 695 Sets the background color. All drawings are erased and the current 696 graph cursor is set to (0, 0). 697 1 parameter: value considered as X11 color string 698 3 parameters: values considered as RGB (alpha = 255) 699 4 parameters: values considered as RGBA 700 ''' 701 _isGPanelValid() 702 return _p.setBgColor(*args)
703
704 -def setColor(*args):
705 ''' 706 Sets the current pen color. 707 1 parameter: - string value considered as X11 color string 708 - list considered as [r, b, g] or [r, g, b, a] 709 - tuple considered as (r, b, g) or (r, g, b, a) 710 3 parameters: values considered as RGB (alpha = 255) 711 4 parameters: values considered as RGBA 712 713 Same as setPenColor(). For TigerJython compatiblity. 714 ''' 715 return setPenColor(*args)
716
717 -def setPaintMode():
718 ''' 719 Resets the drawing mode to standard (overwriting). 720 ''' 721 _isGPanelValid() 722 _p.setPaintMode()
723
724 -def setPenColor(*args):
725 ''' 726 Sets the current pen color. 727 1 parameter: - string value considered as X11 color string 728 - list considered as [r, b, g] or [r, g, b, a] 729 - tuple considered as (r, b, g) or (r, g, b, a) 730 3 parameters: values considered as RGB (alpha = 255) 731 4 parameters: values considered as RGBA 732 ''' 733 _isGPanelValid() 734 return _p.setPenColor(*args)
735
736 -def setPenSize(size):
737 ''' 738 Sets the current pen size (width) (>=1). 739 Returns the previouis pen size. 740 Same as lineWidth(). 741 @param width: the pen width (>=1) 742 ''' 743 _isGPanelValid() 744 return _p.setPenSize(size)
745
746 -def setTitle(title):
747 ''' 748 Sets the title in the window title bar. 749 @param title: the title text 750 ''' 751 _isGPanelValid() 752 return _p.setTitle(size)
753
754 -def setUserCoords(xmin, xmax, ymin, ymax):
755 ''' 756 Sets user coordinate system left_x, right_x, bottom_y, top_y (inclusive). 757 Same as window(). 758 759 @param xmin: the x coordinate (of a visible pixel) at left border 760 @param xmax: the x coordinate (of a visible pixel) at right border 761 @param ymin: the y coordinate (of a visible pixel) at bottom border 762 @param ymax: the y coordinate (of a visible pixel) at top border 763 ''' 764 _isGPanelValid() 765 _p.setUserCoords(xmin, xmax, ymin, ymax)
766
767 -def setWindowCenter():
768 ''' 769 Sets the screen position to the center of the screen. 770 ''' 771 _isGPanelValid() 772 _p.setWindowCenter()
773
774 -def setWindowPos(ulx, uly):
775 ''' 776 Sets the screen position of the graphics window. 777 @param ulx: the upper left corner's x-coordinate 778 @param ulx: the upper left corner's y-coordinate 779 ''' 780 _isGPanelValid() 781 _p.setWindowPos(ulx, uly)
782
783 -def setXORMode(*args):
784 ''' 785 Performs pixel color XOR operation with the existing background pixel. 786 Be aware that if the background is white, drawing with a white pen shows a black pixel. 787 (Parameter not used, for TigerJython compatibility) 788 ''' 789 _isGPanelValid() 790 _p.setXORMode()
791
792 793 -def startPath():
794 ''' 795 Starts recording the path vertexes. The positions of subsequent draw() operations are saved. 796 The path is used to show a filled polygon when fillPath() is called. 797 ''' 798 _isGPanelValid() 799 _p.startPath()
800
801 -def storeGraphics():
802 ''' 803 Saves the current graphics into a image buffer. Use restoreGraphics() 804 to restore it. 805 806 Same as saveGraphics() (for TigerJython compatibility). 807 ''' 808 saveGraphics()
809
810 -def text(*args):
811 ''' 812 Draws a text at given position (user coordinates). 813 1 parameter: at current graph cursor position 814 2 parameters: target point (comolex/list/tuple), text 815 3 parameters: x, y, text 816 ''' 817 _isGPanelValid() 818 _p.text(*args)
819
820 -def title(title):
821 ''' 822 Sets the title in the window title bar. 823 Same as setTitle(), for TigerJython compatibility. 824 @param title: the title text 825 ''' 826 _isGPanelValid() 827 _p.setTitle(title)
828
829 -def toPixel(user):
830 ''' 831 Returns pixel coordinates (tuple) of given user coordinates (tuple). 832 ''' 833 _isGPanelValid() 834 return _p.toPixel(user)
835
836 -def toPixelHeight(userHeight):
837 ''' 838 Returns pixel y-increment of given user y-increment (always positive). 839 ''' 840 _isGPanelValid() 841 return p.toPixelHeight(userHeight)
842
843 -def toPixelWidth(userWidth):
844 ''' 845 Returns pixel x-increment of given user x-increment (always positive). 846 ''' 847 _isGPanelValid() 848 return _p.toPixelWidth(userWidth)
849
850 -def toPixelX(userX):
851 ''' 852 Returns pixel x-coordinate of given user x-coordinate. 853 ''' 854 _isGPanelValid() 855 return _p.toPixelX(userX)
856
857 -def toPixelY(userY):
858 ''' 859 Returns pixel y-coordinate of given user y-coordinate. 860 ''' 861 _isGPanelValid() 862 return _p.toPixelY(userY)
863
864 -def toUser(pixel):
865 ''' 866 Returns user coordinates (tuple) of given pixel coordinates (tuple). 867 ''' 868 _isGPanelValid() 869 return _p.toUser(pixel)
870
871 -def toUserHeight(pixelHeight):
872 ''' 873 Returns user y-increment of given pixel y-increment (always positive). 874 ''' 875 _isGPanelValid() 876 return _p.toUserHeight(pixelHeight)
877
878 -def toUserWidth(pixelWidth):
879 ''' 880 Returns user x-increment of given pixel x-increment (always positive). 881 ''' 882 _isGPanelValid() 883 return _p.toUserWidth(pixelWidth)
884
885 -def toUserX(pixelX):
886 ''' 887 Returns user x-coordinate of given pixel x-coordinate. 888 ''' 889 _isGPanelValid() 890 return _p.toUserX(pixelX)
891
892 -def toUserY(pixelY):
893 ''' 894 Returns user y-coordinate of given pixel y-coordinate. 895 ''' 896 _isGPanelValid() 897 return _p.toUserY(pixelY)
898
899 -def triangle(*args):
900 ''' 901 Draws a triangle with given corners. 902 6 parameters: x1, y1, x2, y2, x3, y3 coordinates of corners 903 3 parameters: [x1, y1], [x2, y2], [x3, y3] lists of corners 904 ''' 905 _isGPanelValid() 906 _p.triangle(*args)
907
908 -def window(xmin, xmax, ymin, ymax):
909 ''' 910 Sets user coordinate system left_x, right_x, bottom_y, top_y (inclusive). 911 Same as setUserCoords(). For TigerJython compatiblity. 912 913 @param xmin: the x coordinate (of a visible pixel) at left border 914 @param xmax: the x coordinate (of a visible pixel) at right border 915 @param ymin: the y coordinate (of a visible pixel) at bottom border 916 @param ymax: the y coordinate (of a visible pixel) at top border 917 ''' 918 _isGPanelValid() 919 _p.setUserCoords(xmin, xmax, ymin, ymax)
920
921 -def windowPosition(ulx, uly):
922 ''' 923 Sets the screen position (pixel coordinates of upper left corner). 924 ''' 925 _isGPanelValid() 926 _p.windowPosition(ulx, uly)
927
928 -def windowCenter():
929 ''' 930 Sets the window to the center of the screen. 931 ''' 932 _isGPanelValid() 933 _p.windowCenter()
934
935 -def _getCoords(*args):
936 if len(args) == 2: 937 return args[0], args[1] 938 elif len(args) == 1: 939 if type(args[0]) == complex: 940 return args[0].real, args[0].imag 941 elif type(args[0]) == list or type(args[0]) == tuple: 942 return args[0][0], args[0][1] 943 else: 944 raise ValueError("Illegal parameter type.") 945 else: 946 raise ValueError("Illegal number of parameters.")
947
948 -def _get2Coords(*args):
949 if len(args) == 4: 950 return args[0], args[1], args[2], args[3] 951 elif len(args) == 2: 952 val = [] 953 for arg in args: 954 if type(arg) == complex: 955 val.append(arg.real) 956 val.append(arg.imag) 957 elif type(args) == list or type(args) == tuple: 958 val.append(arg[0]) 959 val.append(arg[1]) 960 else: 961 raise ValueError("Illegal parameter type.") 962 return val[0], val[1], val[2], val[3] 963 else: 964 raise ValueError("Illegal number of parameters.")
965
966 # ------------------------ end of GPanel methods ----------- 967 968 -def run(f):
969 ''' 970 Calls f() in a new thread. 971 ''' 972 thread.start_new_thread(f, ())
973
974 975 -def getRandomX11Color():
976 ''' 977 Returns a random X11 color string. 978 ''' 979 return GPanel.getRandomX11Color()
980
981 # Code from: http://code.activestate.com 982 -def linfit(X, Y):
983 ''' 984 Returns a and b in y = a*x + b for given list X of x values and 985 corresponding list Y of values. 986 ''' 987 def mean(Xs): 988 return sum(Xs) / len(Xs)
989 m_X = mean(X) 990 m_Y = mean(Y) 991 992 def std(Xs, m): 993 normalizer = len(Xs) - 1 994 return math.sqrt(sum((pow(x - m, 2) for x in Xs)) / normalizer) 995 996 def pearson_r(Xs, Ys): 997 sum_xy = 0 998 sum_sq_v_x = 0 999 sum_sq_v_y = 0 1000 1001 for (x, y) in zip(Xs, Ys): 1002 var_x = x - m_X 1003 var_y = y - m_Y 1004 sum_xy += var_x * var_y 1005 sum_sq_v_x += pow(var_x, 2) 1006 sum_sq_v_y += pow(var_y, 2) 1007 return sum_xy / math.sqrt(sum_sq_v_x * sum_sq_v_y) 1008 1009 r = pearson_r(X, Y) 1010 b = r * (std(Y, m_Y) / std(X, m_X)) 1011 A = m_Y - b * m_X 1012 return b, A 1013
1014 1015 1016 1017 # ----------------------------- Size class ------------------------- 1018 -class Size():
1019 ''' 1020 Class that defines the pair width, height of dimension attributes. 1021 '''
1022 - def __init__(self, width, height):
1023 self.width = width 1024 self.height = height
1025
1026 1027 1028 # ===================================================================== 1029 # ============================= GPanel class ========================== 1030 # ===================================================================== 1031 -class GPanel(QtGui.QWidget):
1032 ''' 1033 Class to create a graphics window of default size 501x501 pixels (client drawing area) 1034 using a coordinate system with x-axis from left to right, y-axis from bottom to top 1035 (called user coordinates, default range 0..1, 0..1). 1036 1037 The drawing methods perform drawing operation in an offscreen buffer (QPixmap) 1038 and automatically renders it on the screen, so the graphics is shown step-by-step. 1039 1040 1041 The drawing methods perform drawing operation in an offscreen buffer (pixmap) 1042 and automatically renders it on the screen, so the graphics is shown step-by-step. 1043 1044 User coordinates: (ux, uy) 1045 Pixel coordinates: (px, py) (screen pixels) 1046 Transformation: px = px(ux), py = py(uy) 1047 Pixel coordinate range: 0..winWidth - 1 (inclusive), 0..winHeight - 1 (inclusive); (0,0) upper left corner, x to the right, y downwards 1048 User coordinate range: xmin..xmax (inclusive), ymin..ymax (inclusive); (0,0) lower left corner, x to the right, y upwards. 1049 1050 Transformation: user(ux, uy) to pixel(px, py): 1051 (width = winWidth - 1, height = winHeight - 1) 1052 px = a * ux + b 1053 py = c * uy + d 1054 with a = width / (xmax - xmin) 1055 b = width * xmin / (xmin - xmax) 1056 c = height / (ymin - ymax) 1057 d = height * ymax / (ymax - ymin) 1058 1059 Inverse: 1060 ux = (px - b) / a 1061 uy = (py - d) / c 1062 1063 Because of the transformation from float to pixel coordinates, some rounding errors 1064 may happen. If you need pixel accuracy, define a GPanel window with some user defined width x height, 1065 e.g. GPanal(Size(501, 401)). Define then user coordinates in the range 0..width-1, 0..height-1, e.g. 1066 setUserCoords(0, 500, 0, 400). Now pixels in the range 0..500 x 0..400 (inclusive) may be addressed with no 1067 rounding errors. (This is a total of 501 x 401 pixels.) 1068 1069 If you prefer a coordinate system with the origin at the upper left corner, define the y-range in reverse 1070 order, e.g. setUserCoords(0, 500, 400, 0). 1071 1072 WARNING: Because PyQt is not thread-safe, in principle all graphics drawings should be 1073 executed in the GUI thread (for GPanel the main thread or a GUI callback). 1074 1075 Typical program: 1076 1077 from pygpanel import * 1078 1079 p = GPanel(0, 10, 0, 10) 1080 for ypt in range(0, 11, 1): 1081 p.line(0, ypt, 10 - ypt, 0) 1082 time.sleep(0.1) # to see what happens 1083 p.keep() 1084 1085 keep() is blocking and keeps the graphics panel open until the close button is hit or the 1086 Python process terminates. 1087 ''' 1088
1089 - def __init__(self, *args, **kwargs):
1090 ''' 1091 Constructs a GPanel and displays a non-resizable graphics window. 1092 Defaults with no parameter: 1093 Window size: 501x501 pixels 1094 Window title: "GPanel" 1095 User coordinates: 0, 1, 0, 1 1096 Background color: white 1097 Pen color: black 1098 Pen size: 1 1099 1100 1 Parameter: Size(window_width, window_height) 1101 4 Parameters: xmin, xmax, ymin, ymax 1102 @param Size: a Size refererence that defines the width and height of the graphics window. 1103 ''' 1104 try: 1105 self._embedded = kwargs['embedded'] 1106 except: 1107 self._embedded = False 1108 else: 1109 if type(self._embedded) != bool: 1110 self._embedded = False 1111 if not self._embedded: 1112 self._app = QtGui.QApplication(sys.argv) 1113 super(GPanel, self).__init__() 1114 self.xmin = 0 1115 self.xmax = 1 1116 self.ymin = 0 1117 self.ymax = 1 1118 self.winWidth = 501 1119 self.winHeight = 501 1120 if not (len(args) == 0 or len(args) == 1 or len(args) == 4): 1121 raise ValueError("Illegal parameter list") 1122 if len(args) == 1: 1123 self.winWidth = args[0].width 1124 self.winHeight = args[0].height 1125 elif len(args) == 4: 1126 self.xmin = args[0] 1127 self.xmax = args[1] 1128 self.xmax = args[1] 1129 self.ymin = args[2] 1130 self.ymax = args[3] 1131 self._initUI()
1132
1133 - def _initUI(self):
1134 self._setDefaults() 1135 self._label = QLabel() 1136 self._pixmap = QPixmap(QSize(self.winWidth, self.winHeight)) 1137 self._vbox = QVBoxLayout() 1138 self._vbox.setContentsMargins(1, 1, 1, 1) 1139 self.setLayout(self._vbox) 1140 self._painter = QPainter(self._pixmap) 1141 self.paintEvent(0) 1142 self.clear() 1143 if not self._embedded: 1144 self.show() 1145 self.setFixedSize(self.winWidth + 2, self.winHeight + 2)
1146
1147 - def _setDefaults(self):
1148 self.setWindowTitle('GPanel') 1149 self._penSize = 1 1150 self._penColor = QColor(0, 0, 0) 1151 self._bgColor = QColor(255, 255, 255, 255) 1152 1153 # default pos of GPanel window 1154 if not self._embedded: 1155 ulx = 10 1156 uly = 10 1157 super(GPanel, self).move(ulx, uly) # position 1158 1159 self._xCurrent = 0 1160 self._yCurrent = 0 1161 self._enableRepaint = True 1162 self._adjust() 1163 self._onMousePressed = None 1164 self._onMouseReleased = None 1165 self._onMouseDragged = None 1166 self._onKeyPressed = None 1167 self._onKeyReleased = None 1168 self._isLeftMouseButton = False 1169 self._isRightMouseButton = False 1170 self._inMouseMoveCallback = False 1171 self._closeListener = None 1172 self._pathHistory = None 1173 self._savePixmap = None 1174 self._doRepaint = False
1175
1176 - def clear(self):
1177 ''' 1178 Clears the graphics window and the offscreen buffer used by the window 1179 (fully paint with background color). 1180 Sets the current graph cursor position to (0, 0). 1181 If enableRepaint(false) only clears the offscreen buffer. 1182 ''' 1183 self._painter.setPen(QPen(self._bgColor, 1)) 1184 self._painter.fillRect(QRect(0, 0, self.winWidth, self.winHeight), self._bgColor) 1185 self._painter.setPen(QPen(self._penColor, self._penSize)) 1186 self._xCurrent = 0 1187 self._yCurrent = 0 1188 if self._enableRepaint: 1189 self.repaint()
1190
1191 - def erase(self):
1192 ''' 1193 Same as clear(), but lets the current graph cursor unganged. 1194 ''' 1195 self._painter.setPen(QPen(self._bgColor, 1)) 1196 self._painter.fillRect(QRect(0, 0, self.winWidth, self.winHeight), self._bgColor) 1197 self._painter.setPen(QPen(self._penColor, self._penSize)) 1198 if self._enableRepaint: 1199 self.repaint()
1200
1201 - def keep(self):
1202 ''' 1203 Blocks until the title bar's close button is hit. Then cleans up 1204 the graphics system. 1205 ''' 1206 self._app.exec_() # blocking
1207 # self._painter.end() 1208 # sys.exit(0) 1209
1210 - def setTitle(self, title):
1211 ''' 1212 Sets the title in the window title bar. 1213 @param title: the title text 1214 ''' 1215 self.setWindowTitle(title)
1216 1217 # override
1218 - def paintEvent(self, e):
1219 if self._doRepaint: 1220 self._label.setPixmap(self._pixmap) 1221 self._vbox.addWidget(self._label) 1222 self._doRepaint = False
1223
1224 - def setColor(self, *args):
1225 ''' 1226 Same as setPenColor() 1227 ''' 1228 self.setPenColor(*args)
1229 1230
1231 - def _toRGBA(self, *args):
1232 if len(args) == 1: 1233 if type(args[0]) == str: 1234 try: 1235 color = args[0].lower() 1236 rgb = x11ColorDict[color] 1237 except KeyError: 1238 raise ValueError("X11 color", args[0], "not found") 1239 r = rgb[0] 1240 g = rgb[1] 1241 b = rgb[2] 1242 a = 255 1243 elif type(args[0]) == list or type(args[0]) == tuple: 1244 if len(args[0]) == 3: 1245 r = args[0][0] 1246 g = args[0][1] 1247 b = args[0][2] 1248 a = 255 1249 elif len(args[0]) == 4: 1250 r = args[0][0] 1251 g = args[0][1] 1252 b = args[0][2] 1253 a = args[0][3] 1254 else: 1255 raise ValueError("Illegal parameter list") 1256 else: 1257 raise ValueError("Illegal parameter list") 1258 1259 elif len(args) == 3: 1260 r = args[0] 1261 g = args[1] 1262 b = args[2] 1263 a = 255 1264 1265 elif len(args) == 4: 1266 r = args[0] 1267 g = args[1] 1268 b = args[2] 1269 a = 255 1270 1271 else: 1272 raise ValueError("Illegal number of arguments") 1273 1274 return r, g, b, a
1275
1276 - def setPenColor(self, *args):
1277 ''' 1278 Sets the current pen color. 1279 1 parameter: - string value considered as X11 color string 1280 - list considered as [r, b, g] or [r, g, b, a] 1281 - tuple considered as (r, b, g) or (r, g, b, a) 1282 3 parameters: values considered as RGB (alpha = 255) 1283 4 parameters: values considered as RGBA 1284 ''' 1285 r, g, b, a = self._toRGBA(*args) 1286 self._penColor = QColor(r, g, b, a) 1287 self._painter.setPen(QPen(self._penColor, self._penSize))
1288
1289 - def setPenSize(self, size):
1290 ''' 1291 Sets the current pen size (width) (>=1). 1292 Returns the previous pen size. 1293 @param width: the pen width >=1) 1294 ''' 1295 oldPenSize = self._penSize 1296 self._penSize = size 1297 self._painter.setPen(QPen(self._penColor, self._penSize)) 1298 return oldPenSize
1299 1300 # coordinate transformations
1301 - def toPixel(self, user):
1302 ''' 1303 Returns pixel coordinates (tuple) of given user coordinates (tupel). 1304 ''' 1305 return self.toPixelX(user[0]), self.toPixelY(user[1])
1306
1307 - def toPixelX(self, userX):
1308 ''' 1309 Returns pixel x-coordinate of given user x-coordinate. 1310 ''' 1311 return (int)(self._a * userX + self._b)
1312
1313 - def toPixelY(self, userY):
1314 ''' 1315 Returns pixel y-coordinate of given user y-coordinate. 1316 ''' 1317 return (int)(self._c * userY + self._d)
1318
1319 - def toPixelWidth(self, userWidth):
1320 ''' 1321 Returns pixel x-increment of given user x-increment (always positive). 1322 ''' 1323 return int(abs(self._a * userWidth))
1324
1325 - def toPixelHeight(self, userHeight):
1326 ''' 1327 Returns pixel y-increment of given user y-increment (always positive). 1328 ''' 1329 return int(abs(self._c * userHeight))
1330
1331 - def toUser(self, pixel):
1332 ''' 1333 Returns user coordinates (tuple) of given pixel coordinates (tuple). 1334 ''' 1335 return self.toUserX(pixel[0]), self.toUserY(pixel[1])
1336
1337 - def toUserX(self, pixelX):
1338 ''' 1339 Returns user x-coordinate of given pixel x-coordinate. 1340 ''' 1341 a = (self.winWidth - 1) / (self.xmax - self.xmin) 1342 b = (self.winWidth - 1) * self.xmin / (self.xmin - self.xmax) 1343 return (pixelX - b) / a
1344
1345 - def toUserY(self, pixelY):
1346 ''' 1347 Returns user y-coordinate of given pixel y-coordinate. 1348 ''' 1349 c = (self.winHeight - 1) / (self.ymin - self.ymax) 1350 d = (self.winHeight - 1) * self.ymax / (self.ymax - self.ymin) 1351 return (pixelY - d) / c
1352
1353 - def toUserWidth(self, pixelWidth):
1354 ''' 1355 Returns user x-increment of given pixel x-increment (always positive). 1356 ''' 1357 a = (self.winWidth - 1) / (self.xmax - self.xmin) 1358 return abs(pixelWidth / a)
1359
1360 - def toUserHeight(self, pixelHeight):
1361 ''' 1362 Returns user y-increment of given pixel y-increment (always positive). 1363 ''' 1364 c = (self.winWidth - 1) / (self._ymin - self._ymax) 1365 return abs(pixelHeight / c)
1366
1367 - def setUserCoords(self, xmin, xmax, ymin, ymax):
1368 ''' 1369 Sets user coordinate system left_x, right_x, bottom_y, top_y (inclusive). 1370 @param xmin: the x coordinate (of a visible pixel) at left border 1371 @param xmax: the x coordinate (of a visible pixel) at right border 1372 @param ymin: the y coordinate (of a visible pixel) at bottom border 1373 @param ymax: the y coordinate (of a visible pixel) at top border 1374 ''' 1375 self.xmin = xmin 1376 self.xmax = xmax 1377 self.ymin = ymin 1378 self.ymax = ymax 1379 self._adjust()
1380
1381 - def _adjust(self):
1382 self._a = (self.winWidth - 1) / (self.xmax - self.xmin) 1383 self._b = (self.winWidth - 1) * self.xmin / (self.xmin - self.xmax) 1384 self._c = (self.winHeight - 1) / (self.ymin - self.ymax) 1385 self._d = (self.winHeight - 1) * self.ymax / (self.ymax - self.ymin)
1386 1387 # end of coordinate transformations 1388
1389 - def repaint(self):
1390 ''' 1391 Renders the offscreen buffer in the graphics window. 1392 ''' 1393 self._doRepaint = True 1394 self.update() 1395 QApplication.processEvents()
1396
1397 - def enableRepaint(self, enable):
1398 ''' 1399 Enables/Disables automatic repaint in graphics drawing methods. 1400 @param enable: if True, the automatic repaint is enabled; otherwise disabled 1401 ''' 1402 self._enableRepaint = enable
1403
1404 - def line(self, x1, y1, x2, y2):
1405 ''' 1406 Draws a line with given user start and end coordinates 1407 and sets the graph cursor position to the end point. 1408 Also with 2 parameters of type complex, list or tuple. 1409 4 parameters: x1, y1, x2, y2 1410 2 parameters: pt1, pt2 as complex/list/tuple 1411 ''' 1412 xStart = self.toPixelX(x1) 1413 yStart = self.toPixelY(y1) 1414 xEnd = self.toPixelX(x2) 1415 yEnd = self.toPixelY(y2) 1416 self._painter.drawLine(xStart, yStart, xEnd, yEnd) 1417 self._xCurrent = x2 1418 self._yCurrent = y2 1419 if self._enableRepaint: 1420 self.repaint()
1421
1422 - def pos(self, x, y):
1423 ''' 1424 Sets the current graph cursor position to given user coordinates. 1425 (without drawing anything, same as move()). 1426 @param x: the x coordinate of the target point 1427 @param y: the y coordinate of the target point 1428 @param target: (alternative) the target point as complex, list or tuple 1429 ''' 1430 self._xCurrent = x 1431 self._yCurrent = y
1432
1433 - def move(self, x, y):
1434 # Overrides super.move() 1435 ''' 1436 Sets the current graph cursor position to given user coordinates. 1437 (without drawing anything, same as pos()). 1438 @param x: the x coordinate of the target point 1439 @param y: the y coordinate of the target point 1440 @param target: (alternative) the target point as complex, list or tuple 1441 ''' 1442 self.pos(x, y)
1443
1444 - def draw(self, x, y):
1445 ''' 1446 Draws a line form current graph cursor position to (x, y). 1447 Sets the graph cursor position to (x, y). 1448 @param x: the x coordinate of the target point 1449 @param y: the y coordinate of the target point 1450 @param target: (alternative) the target point as complex, list or tuple 1451 ''' 1452 self.line(self._xCurrent, self._yCurrent, x, y) 1453 if self._pathHistory != None: 1454 self._pathHistory.append([x, y])
1455
1456 - def linePlot(self, *args):
1457 ''' 1458 Draws a line plot with given x,y data. 1459 1 parameter: a list/tuple of subsequent data points [x, y] 1460 2 parameters: two lists/tuples x, y of corresponding x-y pairs 1461 The graph cursor position remains unchanged. 1462 ''' 1463 nodes = [] 1464 if len(args) == 1: 1465 for pt in args[0]: 1466 node = [pt[0], pt[1]] 1467 nodes.append(node) 1468 elif len(args) == 2: 1469 if len(args[0]) != len(args[1]): 1470 raise ValueError("x and y list/tuple must have equal size") 1471 for i in range(len(args[0])): 1472 node = [args[0][i], args[1][i]] 1473 nodes.append(node) 1474 else: 1475 raise ValueError("Illegal number of parameters.") 1476 1477 for i in range(len(nodes) - 1): 1478 x1 = self.toPixelX(nodes[i][0]) 1479 y1 = self.toPixelY(nodes[i][1]) 1480 x2 = self.toPixelX(nodes[i + 1][0]) 1481 y2 = self.toPixelY(nodes[i + 1][1]) 1482 self._painter.drawLine(x1, y1, x2, y2) 1483 1484 if self._enableRepaint: 1485 self.repaint()
1486
1487 - def getPos():
1488 ''' 1489 Returns a tuple with current graph cursor position (tuple, user coordinates). 1490 ''' 1491 return self._xCurrent, self._yCurrent
1492
1493 - def getPosX(self):
1494 ''' 1495 Returns the current graph cursor x-position (user coordinates). 1496 ''' 1497 return self._xCurrent
1498
1499 - def getPosY(self):
1500 ''' 1501 Returns the current graph cursor y-position (user coordinates). 1502 ''' 1503 return self._yCurrent
1504
1505 - def text(self, *args):
1506 ''' 1507 Draws a text at given position (user coordinates). 1508 1 parameter: at current graph cursor position 1509 2 parameters: target point (comolex/list/tuple), text 1510 3 parameters: x, y, text 1511 ''' 1512 if len(args) == 1: 1513 xPos = self.toPixelX(self._xCurrent) 1514 yPos = self.toPixelY(self._yCurrent) 1515 text = args[0] 1516 elif len(args) == 2: 1517 xPos, yPos = _getCoords(args[0][:-1]) 1518 text = args[1] 1519 elif len(args) == 3: 1520 xPos = self.toPixelX(args[0]) 1521 yPos = self.toPixelY(args[1]) 1522 text = args[2] 1523 else: 1524 raise ValueError("Illegal number of arguments") 1525 1526 self._painter.drawText(xPos, yPos, text) 1527 if self._enableRepaint: 1528 self.repaint()
1529
1530 - def addCloseListener(self, closeListener):
1531 ''' 1532 Registers the given function that is called when the title bar 1533 close button is hit. If a listener (!= None) is registered, 1534 the automatic closing is disabled. To close the window, call 1535 sys.exit(). 1536 1537 KEEP IN MIND: To use GUI callbacks, the main program must block in the keep() function. 1538 @param closeListener: a callback function called when the close button is hit 1539 ''' 1540 self._closeListener = closeListener
1541
1542 - def closeEvent(self, e):
1543 # Override 1544 if self._closeListener != None: 1545 e.ignore() 1546 self._closeListener()
1547
1548 - def setBgColor(self, *args):
1549 ''' 1550 Sets the background color. All drawings are erased and the current 1551 graph cursor is set to (0, 0). 1552 1553 1 parameter: - string value considered as X11 color string 1554 - list considered as [r, b, g] or [r, g, b, a] 1555 - tuple considered as (r, b, g) or (r, g, b, a) 1556 3 parameters: values considered as RGB (alpha = 255) 1557 4 parameters: values considered as RGBA 1558 ''' 1559 r, g, b, a = self._toRGBA(*args) 1560 self._bgColor = QColor(r, g, b, a) 1561 self.clear()
1562 1563
1564 - def circle(self, radius):
1565 ''' 1566 Draws a circle with center at the current graph cursor position 1567 with given radius in horizontal window coordinates. 1568 @param radius: the radius of the circle 1569 ''' 1570 xPix = self.toPixelX(self._xCurrent) 1571 yPix = self.toPixelY(self._yCurrent) 1572 rPix = self.toPixelWidth(radius) 1573 self._painter.drawEllipse(QPointF(xPix, yPix), rPix, rPix) 1574 if self._enableRepaint: 1575 self.repaint()
1576
1577 - def fillCircle(self, radius):
1578 ''' 1579 Draws a filled circle with center at the current graph cursor position 1580 with given radius in horizontal window coordinates (fill color = pen color). 1581 @param radius: the radius of the circle 1582 ''' 1583 xPix = self.toPixelX(self._xCurrent) 1584 yPix = self.toPixelY(self._yCurrent) 1585 rPix = self.toPixelWidth(radius) 1586 self._painter.setPen(Qt.NoPen) 1587 self._painter.setBrush(QBrush(self._penColor)) 1588 self._painter.drawEllipse(QPointF(xPix, yPix), rPix, rPix) 1589 if self._enableRepaint: 1590 self.repaint() 1591 self._painter.setPen(QPen(self._penColor, self._penSize)) 1592 self._painter.setBrush(Qt.NoBrush)
1593 1594
1595 - def ellipse(self, a, b):
1596 ''' 1597 Draws an ellipse with center at the current graph cursor position 1598 with given axes. 1599 @param a: the major ellipse axis 1600 @param b: the minor ellipse axis 1601 ''' 1602 xPix = self.toPixelX(self._xCurrent) 1603 yPix = self.toPixelY(self._yCurrent) 1604 aPix = self.toPixelWidth(a) 1605 bPix = self.toPixelHeight(b) 1606 self._painter.drawEllipse(QPointF(xPix, yPix), aPix, bPix) 1607 if self._enableRepaint: 1608 self.repaint()
1609
1610 - def fillEllipse(self, a, b):
1611 ''' 1612 Draws a filled ellipse with center at the current graph cursor position 1613 with given axes (fill color = pen color). 1614 @param a: the major ellipse axis 1615 @param b: the minor ellipse axis 1616 ''' 1617 xPix = self.toPixelX(self._xCurrent) 1618 yPix = self.toPixelY(self._yCurrent) 1619 aPix = self.toPixelWidth(a) 1620 bPix = self.toPixelHeight(b) 1621 self._painter.setPen(Qt.NoPen) 1622 self._painter.setBrush(QBrush(self._penColor)) 1623 self._painter.drawEllipse(QPointF(xPix, yPix), aPix, bPix) 1624 if self._enableRepaint: 1625 self.repaint() 1626 self._painter.setPen(QPen(self._penColor, self._penSize)) 1627 self._painter.setBrush(Qt.NoBrush)
1628
1629 - def rectangle(self, *args):
1630 ''' 1631 Draws a rectangle. 1632 2 parameters: Center at the current graph cursor position 1633 and given width and height. 1634 4 parameters: Given diagonal 1635 ''' 1636 if len(args) == 2: 1637 wPix = self.toPixelWidth(args[0]) 1638 hPix = self.toPixelHeight(args[1]) 1639 ulx = self.toPixelX(self._xCurrent) - wPix // 2 1640 uly = self.toPixelY(self._yCurrent) - hPix // 2 1641 elif len(args) == 4: 1642 wPix = self.toPixelWidth(args[2] - args[0]) 1643 hPix = self.toPixelHeight(args[3] - args[1]) 1644 ulx = self.toPixelX(args[0]) 1645 uly = self.toPixelY(args[1]) 1646 self._painter.drawRect(ulx, uly, wPix, hPix) 1647 if self._enableRepaint: 1648 self.repaint()
1649
1650 - def fillRectangle(self, *args):
1651 ''' 1652 Draws a filled rectangle (fill color = pen color). 1653 2 parameters: Center at the current graph cursor position 1654 and given width and height. 1655 4 parameters: Given diagonal 1656 ''' 1657 if len(args) == 2: 1658 wPix = self.toPixelWidth(args[0]) 1659 hPix = self.toPixelHeight(args[1]) 1660 ulx = self.toPixelX(self._xCurrent) - wPix // 2 1661 uly = self.toPixelY(self._yCurrent) - hPix // 2 1662 elif len(args) == 4: 1663 wPix = self.toPixelWidth(args[2] - args[0]) 1664 hPix = self.toPixelHeight(args[3] - args[1]) 1665 ulx = self.toPixelX(args[0]) 1666 uly = self.toPixelY(args[1]) 1667 self._painter.setPen(Qt.NoPen) 1668 self._painter.setBrush(QBrush(self._penColor)) 1669 self._painter.drawRect(ulx, uly, wPix, hPix) 1670 if self._enableRepaint: 1671 self.repaint() 1672 self._painter.setPen(QPen(self._penColor, self._penSize)) 1673 self._painter.setBrush(Qt.NoBrush)
1674
1675 - def polygon(self, *args):
1676 ''' 1677 Draws a polygon with given list of vertexes (list of [x, y] or (x, y)) 1678 (fill color = pen color). 1679 1 parameter: a list/tuple of the corners [x, y] or (x, y) 1680 2 parameters: two lists/tuples x, y of corresponding x-y pairs 1681 ''' 1682 nodes = [] 1683 if len(args) == 1: 1684 for pt in args[0]: 1685 node = QPointF(self.toPixelX(pt[0]), self.toPixelY(pt[1])) 1686 nodes.append(node) 1687 elif len(args) == 2: 1688 if len(args[0]) != len(args[1]): 1689 raise ValueError("x and y list/tuple must have equal size") 1690 for i in range(len(args[0])): 1691 node = QPointF(self.toPixelX(args[0][i]), self.toPixelY(args[1][i])) 1692 nodes.append(node) 1693 else: 1694 raise ValueError("Illegal number of parameters.") 1695 p = QPolygonF(nodes) 1696 self._painter.drawPolygon(p) 1697 if self._enableRepaint: 1698 self.repaint()
1699
1700 - def fillPolygon(self, *args):
1701 ''' 1702 Draws a filled polygon with given list of vertexes (list of [x, y] or (x, y)) 1703 (fill color = pen color). 1704 1 parameter: a list/tuple of the corners [x, y] or (x, y) 1705 2 parameters: two lists/tuples x, y of corresponding x-y pairs 1706 ''' 1707 nodes = [] 1708 if len(args) == 1: 1709 for pt in args[0]: 1710 node = QPointF(self.toPixelX(pt[0]), self.toPixelY(pt[1])) 1711 nodes.append(node) 1712 elif len(args) == 2: 1713 if len(args[0]) != len(args[1]): 1714 raise ValueError("x and y list/tuple must have equal size") 1715 for i in range(len(args[0])): 1716 node = QPointF(self.toPixelX(args[0][i]), self.toPixelY(args[1][i])) 1717 nodes.append(node) 1718 else: 1719 raise ValueError("Illegal number of parameters.") 1720 p = QPolygonF(nodes) 1721 self._painter.setPen(Qt.NoPen) 1722 self._painter.setBrush(QBrush(self._penColor)) 1723 self._painter.drawPolygon(p) 1724 if self._enableRepaint: 1725 self.repaint() 1726 self._painter.setPen(QPen(self._penColor, self._penSize)) 1727 self._painter.setBrush(Qt.NoBrush)
1728
1729 - def triangle(self, *args):
1730 ''' 1731 Draws a triangle with given corners. 1732 6 parameters: x1, y1, x2, y2, x3, y3 coordinates of corners 1733 3 parameters: [x1, y1], [x2, y2], [x3, y3] lists of corners 1734 ''' 1735 if len(args) == 6: # triangle(x1, y1, x2, y2, x3, y3) 1736 corners = [[args[0], args[1]], [args[2], args[3]], [args[4], args[5]]] 1737 self.polygon(corners) 1738 elif len(args) == 3: # triangle([x1, y1], [x2, y2], [x3, y3]) 1739 corners = [args[0], args[1], args[2]] 1740 self.polygon(corners) 1741 else: 1742 raise ValueError("Illegal number of parameters.")
1743
1744 - def fillTriangle(self, *args):
1745 ''' 1746 Draws a filled triangle with given corners. 1747 6 parameters: x1, y1, x2, y2, x3, y3 coordinates of corners 1748 3 parameters: [x1, y1], [x2, y2], [x3, y3] lists of corners 1749 ''' 1750 if len(args) == 6: # triangle(x1, y1, x2, y2, x3, y3) 1751 corners = [[args[0], args[1]], [args[2], args[3]], [args[4], args[5]]] 1752 self.fillPolygon(corners) 1753 elif len(args) == 3: # triangle([x1, y1], [x2, y2], [x3, y3]) 1754 corners = [args[0], args[1], args[2]] 1755 self.fillPolygon(corners) 1756 else: 1757 raise ValueError("Illegal number of parameters.")
1758
1759 - def arc(self, r, startAngle, spanAngle):
1760 ''' 1761 Draws a circle sector with center at the current graph cursor position, 1762 given radius and given start and span angles. 1763 @param radius: the radius of the arc 1764 @param startAngle: starting angle in degrees, zero to east, positive counter-clockwise 1765 @param spanAngle: span angle (sector angle) in degrees, positive counter-clockwise 1766 ''' 1767 xPix = self.toPixelX(self._xCurrent) 1768 yPix = self.toPixelY(self._yCurrent) 1769 rPix = self.toPixelWidth(r) 1770 topLeft = QPoint(xPix - rPix, yPix - rPix) 1771 bottomRight = QPoint(xPix + rPix, yPix + rPix) 1772 rect = QRect(topLeft, bottomRight) 1773 self._painter.drawArc(rect, int(16 * startAngle), int(16 * spanAngle)) 1774 if self._enableRepaint: 1775 self.repaint()
1776
1777 - def fillArc(self, r, startAngle, spanAngle):
1778 ''' 1779 Draws a filled circle sector with center at the current graph cursor position, 1780 given radius and given start and span angles. 1781 @param radius: the radius of the arc 1782 @param startAngle: starting angle in degrees, zero to east, positive counter-clockwise 1783 @param spanAngle: span angle (sector angle) in degrees, positive counter-clockwise 1784 ''' 1785 xPix = self.toPixelX(self._xCurrent) 1786 yPix = self.toPixelY(self._yCurrent) 1787 rPix = self.toPixelWidth(r) 1788 topLeft = QPoint(xPix - rPix, yPix - rPix) 1789 bottomRight = QPoint(xPix + rPix, yPix + rPix) 1790 rect = QRect(topLeft, bottomRight) 1791 self._painter.setPen(Qt.NoPen) 1792 self._painter.setBrush(QBrush(self._penColor)) 1793 self._painter.drawChord(rect, int(16 * startAngle), int(16 * spanAngle)) 1794 1795 # Draw sector triangle 1796 xStart = int(xPix + rPix * math.cos(math.radians(startAngle))) 1797 yStart = int(yPix - rPix * math.sin(math.radians(startAngle))) 1798 xEnd = int(xPix + rPix * math.cos(math.radians(startAngle + spanAngle))) 1799 yEnd = int(yPix - rPix * math.sin(math.radians(startAngle + spanAngle))) 1800 triangle = [[xPix, yPix], [xStart, yStart], [xEnd, yEnd]] 1801 nodes = [] 1802 for pt in triangle: 1803 node = QPointF(pt[0], pt[1]) 1804 nodes.append(node) 1805 p = QPolygonF(nodes) 1806 self._painter.drawPolygon(p) 1807 1808 if self._enableRepaint: 1809 self.repaint() 1810 self._painter.setPen(QPen(self._penColor, self._penSize)) 1811 self._painter.setBrush(Qt.NoBrush)
1812
1813 - def chord(self, r, startAngle, spanAngle):
1814 ''' 1815 Draws a circle chord with center at the current graph cursor position, 1816 given radius and given start and span angles (in degrees, positive 1817 counter-clockwise, zero to east). 1818 @param radius: the radius of the arc 1819 @param startAngle: starting angle in degrees, zero to east, positive counter-clockwise 1820 @param spanAngle: span angle (sector angle) in degrees, positive counter-clockwise 1821 ''' 1822 xPix = self.toPixelX(self._xCurrent) 1823 yPix = self.toPixelY(self._yCurrent) 1824 rPix = self.toPixelWidth(r) 1825 topLeft = QPoint(xPix - rPix, yPix - rPix) 1826 bottomRight = QPoint(xPix + rPix, yPix + rPix) 1827 rect = QRect(topLeft, bottomRight) 1828 self._painter.drawChord(rect, int(16 * startAngle), int(16 * spanAngle)) 1829 if self._enableRepaint: 1830 self.repaint()
1831
1832 - def fillChord(self, r, startAngle, spanAngle):
1833 ''' 1834 Draws a filled circle chord with center at the current graph cursor position, 1835 given radius and given start and span angles (in degrees, positive 1836 counter-clockwise, zero to east). 1837 @param radius: the radius of the arc 1838 @param startAngle: starting angle in degrees, zero to east, positive counter-clockwise 1839 @param spanAngle: span angle (sector angle) in degrees, positive counter-clockwise 1840 ''' 1841 xPix = self.toPixelX(self._xCurrent) 1842 yPix = self.toPixelY(self._yCurrent) 1843 rPix = self.toPixelWidth(r) 1844 topLeft = QPoint(xPix - rPix, yPix - rPix) 1845 bottomRight = QPoint(xPix + rPix, yPix + rPix) 1846 rect = QRect(topLeft, bottomRight) 1847 self._painter.setPen(Qt.NoPen) 1848 self._painter.setBrush(QBrush(self._penColor)) 1849 self._painter.drawChord(rect, int(16 * startAngle), int(16 * spanAngle)) 1850 if self._enableRepaint: 1851 self.repaint() 1852 self._painter.setPen(QPen(self._penColor, self._penSize)) 1853 self._painter.setBrush(Qt.NoBrush)
1854
1855 - def startPath(self):
1856 ''' 1857 Starts recording the path vertexes. The positions of subsequent draw() operations are saved. 1858 The path is used to show a filled polygon when fillPath() is called. 1859 ''' 1860 self._pathHistory = [[self._xCurrent, self._yCurrent]]
1861
1862 - def fillPath(self, color):
1863 ''' 1864 Closes the path started with startPath() and shows a filled polygon from the saved 1865 draw() positions with given color. 1866 ''' 1867 if self._pathHistory == None: 1868 raise Exception("Must call startPath() before fillPath()") 1869 oldColor = self._penColor 1870 oldSize = self._penSize 1871 self.setPenColor(color) 1872 self.setPenSize(1) 1873 self.fillPolygon(self._pathHistory) 1874 self._painter.setPen(QPen(oldColor, oldSize)) 1875 self.polygon(self._pathHistory) # draw outline again 1876 self._pathHistory = None
1877
1878 - def showImage(self, *args):
1879 ''' 1880 Draws the picture with given file path or given image at given upper-left coordinates. 1881 1st parameter: image path (string) or QImage reference 1882 2nd, 3rd parameters: llx, lly (lower left corner in user coordinates) 1883 ''' 1884 if type(args[0])== str: 1885 img = QImage(args[0]) 1886 else: 1887 img = args[0] 1888 xPix = self.toPixelX(args[1]) 1889 yPix = self.toPixelY(args[2]) - img.height() + 1 # 1 pixel border 1890 self._painter.drawImage(xPix, yPix, img) 1891 if self._enableRepaint: 1892 self.repaint()
1893
1894 - def point(self, *args):
1895 ''' 1896 Draws a single point with current pen size and pen color at given user coordinates. 1897 No params: draws a current graph cursor position 1898 @param x: the x coordinate of the target point 1899 @param y: the y coordinate of the target point 1900 @param target: (alternative) the target point as complex, list or tuple 1901 ''' 1902 if len(args) == 0: 1903 xPix = self.toPixelX(self._xCurrent) 1904 yPix = self.toPixelY(self._yCurrent) 1905 elif len(args) == 1: 1906 pt = _getCoords(*args) 1907 xPix = self.toPixelX(pt[0]) 1908 yPix = self.toPixelY(pt[1]) 1909 elif len(args) == 2: 1910 xPix = self.toPixelX(args[0]) 1911 yPix = self.toPixelY(args[1]) 1912 else: 1913 raise ValueError("Illegal number of arguments") 1914 self._painter.drawPoint(QPointF(xPix, yPix)) 1915 if self._enableRepaint: 1916 self.repaint()
1917
1918 - def getPixelColor(self, *args):
1919 ''' 1920 Returns the RGBA color tuple of a pixel with given user coordinates. 1921 No params: Returns color at current graph cursor position. 1922 ''' 1923 if len(args) == 0: 1924 xPix = self.toPixelX(self._xCurrent) 1925 yPix = self.toPixelY(self._yCurrent) 1926 elif len(args) == 2: 1927 xPix = self.toPixelX(args[0]) 1928 yPix = self.toPixelY(args[1]) 1929 else: 1930 raise ValueError("Illegal number of parameters.") 1931 img = self._pixmap.toImage() 1932 c = img.pixel(xPix, yPix) 1933 return QColor(c).getRgb() # RGBA
1934
1935 - def getPixelColorStr(self, *args):
1936 ''' 1937 Returns the X11 color string of a pixel with given user coordinates. 1938 No params: Returns color at current graph cursor position. 1939 ''' 1940 r, g, b, a = self.getPixelColor(*args) 1941 for name, rgb in x11ColorDict.items(): 1942 if name[-1] in [str(i) for i in range(10)]: # skip names with ending number 1943 continue 1944 if " " in name: # skip names with space 1945 continue 1946 if "grey" in name: # skip British gray 1947 continue 1948 if rgb == [r, g, b]: 1949 return name 1950 raise ValueError("X11 color", [r, g, b], "not found")
1951
1952 - def _toColor(self, color):
1953 if type(color) == str: 1954 try: 1955 color = color.lower() 1956 color = x11ColorDict[color] 1957 return color 1958 except KeyError: 1959 raise ValueError("X11 color", color, "not found") 1960 else: 1961 return color
1962
1963 - def fill(self, x, y, *args):
1964 ''' 1965 Fills the closed unicolored region with the inner point (x, y) with 1966 the replacement color (RGB, RGBA or X11 color string). 1967 The old color is not given, the color of the current (x, y) pixel is taken. 1968 @param x: the x coordinate of the inner point 1969 @param y: the y coordinate of the inner point 1970 @param color: the old color (RGB list/tuple or X11 color string) (may be omitted) 1971 @param replacementColor: the new color (RGB list/tuple or X11 color string) 1972 ''' 1973 xPix = self.toPixelX(x) 1974 yPix = self.toPixelY(y) 1975 1976 if len(args) == 2: 1977 color = self._toColor(args[0]) 1978 replacementColor = self._toColor(args[1]) 1979 elif len(args) == 1: 1980 im = self._pixmap.toImage() 1981 col= QColor(im.pixel(xPix, yPix)) 1982 color = [col.red(), col.green(), col.blue()] 1983 replacementColor = self._toColor(args[0]) 1984 else: 1985 raise ValueError("Illegal number of parameters.") 1986 1987 img = GPanel.floodFill(self._pixmap, [self.toPixelX(x), self.toPixelY(y)], color, replacementColor) 1988 self._painter.drawImage(0, 0, img) 1989 if self._enableRepaint: 1990 self.repaint()
1991
1992 - def getPainter(self):
1993 ''' 1994 Returns the QPainter reference used to draw into the offscreen buffer. 1995 ''' 1996 return self._painter
1997
1998 - def getFullImage(self):
1999 ''' 2000 Returns the QImage reference of the whole graphics area. 2001 ''' 2002 return self._pixmap.toImage()
2003
2004 - def drawGrid(self, *args):
2005 ''' 2006 Draws a coordinate system with annotated axes. 2007 (You must increase the user coordinate system at least 10% in both directions.) 2008 drawGrid(x, y): Grid with 10 ticks in range 0..x, 0..y. Label text depends if x, y or int or float 2009 drawGrid(x, y, color): same with given grid color 2010 drawGrid(x1, x2, y1, y2): same with given span x1..x2, y1..y2 2011 drawGrid(x1, x2, y1, y2, color): same with given grid color 2012 drawGrid(x1, x2, y1, y2, x3, y3): same with given number of ticks x3, y3 in x- and y-direction 2013 ''' 2014 if len(args) == 2: 2015 self._drawGrid(0, args[0], 0, args[1], 10, 10, None) 2016 if len(args) == 3: 2017 self._drawGrid(0, args[0], 0, args[1], 10, 10, args[2]) 2018 elif len(args) == 4: 2019 self._drawGrid(args[0], args[1], args[2], args[3], 10, 10, None) 2020 elif len(args) == 5: 2021 self._drawGrid(args[0], args[1], args[2], args[3], 10, 10, args[4]) 2022 elif len(args) == 6: 2023 self._drawGrid(args[0], args[1], args[2], args[3], args[4], args[5], None) 2024 elif len(args) == 7: 2025 self._drawGrid(args[0], args[1], args[2], args[3], args[4], args[5], args[6]) 2026 else: 2027 raise ValueError("Illegal number of parameters.")
2028
2029 - def _drawGrid(self, xmin, xmax, ymin, ymax, xticks, yticks, color):
2030 # Save current cursor and color 2031 xPos = self.getPosX() 2032 yPos = self.getPosY() 2033 if color != None: 2034 oldColor = self._penColor 2035 self.setPenColor(color) 2036 # Horizontal 2037 for i in range(yticks + 1): 2038 y = ymin + (ymax - ymin) / float(yticks) * i 2039 self.line(xmin, y, xmax, y) 2040 if isinstance(ymin, float) or isinstance(ymax, float): 2041 self.text(xmin - 0.09 * (xmax - xmin), y, str(y)) 2042 else: 2043 self.text(xmin - 0.09 * (xmax - xmin), y, str(int(y))) 2044 # Vertical 2045 for k in range(xticks + 1): 2046 x = xmin + (xmax - xmin) / float(xticks) * k 2047 self.line(x, ymin, x, ymax) 2048 if isinstance(xmin, float) or isinstance(xmax, float): 2049 self.text(x, ymin - 0.05 * (ymax - ymin), str(x)) 2050 else: 2051 self.text(x, ymin - 0.05 * (ymax - ymin), str(int(x))) 2052 # Restore cursor and color 2053 self.pos(xPos, yPos) 2054 if color != None: 2055 self._penColor = oldColor 2056 self._painter.setPen(QPen(self._penColor, self._penSize))
2057
2058 - def addMousePressListener(self, onMousePressed):
2059 ''' 2060 Registers a callback that is invoked when a mouse button is pressed. 2061 Use isLeftMouseButton() or isRightMouseButton() to check which button used. 2062 2063 KEEP IN MIND: To use GUI callbacks, the main program must block in the keep() function. 2064 @param onMousePressed: a callback function called when a mouse button is pressed 2065 ''' 2066 self._onMousePressed = onMousePressed
2067
2068 - def addMouseReleaseListener(self, onMouseReleased):
2069 ''' 2070 Registers a callback that is invoked when a mouse button is releases. 2071 Use isLeftMouseButton() or isRightMouseButton() to check which button used. 2072 2073 KEEP IN MIND: To use GUI callbacks, the main program must block in the keep() function. 2074 @param onMouseReleased: a callback function called when a mouse button is released 2075 ''' 2076 self._onMouseReleased = onMouseReleased
2077
2078 - def addMouseDragListener(self, onMouseDragged):
2079 ''' 2080 Registers a callback that is invoked when the mouse is moved while a mouse button is pressed (drag). 2081 2082 KEEP IN MIND: To use GUI callbacks, the main program must block in the keep() function. 2083 @param onMouseDragged: a callback function called when the moused is dragged 2084 ''' 2085 self._onMouseDragged = onMouseDragged
2086
2087 - def isLeftMouseButton(self):
2088 ''' 2089 Returns True, if the last mouse action was performed with the left mouse button. 2090 ''' 2091 return self._isLeftMouseButton
2092
2093 - def isRightMouseButton(self):
2094 ''' 2095 Returns True, if the last mouse action was performed with the right mouse button. 2096 ''' 2097 return self._isRightMouseButton
2098
2099 - def addKeyPressListener(self, onKeyPressed):
2100 ''' 2101 Registers a callback that is invoked when a key is pressed (and the graphics window has the focus). 2102 2103 KEEP IN MIND: To use GUI callbacks, the main program must block in the keep() function. 2104 @param onKeyPressed: a callback function called when a key is pressed 2105 ''' 2106 self._onKeyPressed = onKeyPressed
2107
2108 - def addKeyReleaseListener(self, onKeyReleased):
2109 ''' 2110 Registers a callback that is invoked when a key is released (and the graphics window has the focus). 2111 2112 KEEP IN MIND: To use GUI callbacks, the main program must block in the keep() function. 2113 @param onKeyReleased: a callback function called when a key is released 2114 ''' 2115 self._onKeyReleased = onKeyReleased
2116
2117 - def getScreenWidth(self):
2118 ''' 2119 Returns the screen width in pixels. 2120 ''' 2121 screen_resolution = self._app.desktop().screenGeometry() 2122 return screen_resolution.width()
2123
2124 - def getScreenHeight(self):
2125 ''' 2126 Returns the screen height in pixels. 2127 ''' 2128 screen_resolution = self._app.desktop().screenGeometry() 2129 return screen_resolution.height()
2130 2131
2132 - def setWindowCenter(self):
2133 ''' 2134 Sets the screen position to the center of the screen. 2135 ''' 2136 frameGm = self.frameGeometry() 2137 centerPoint = QtGui.QDesktopWidget().availableGeometry().center() 2138 frameGm.moveCenter(centerPoint) 2139 super(GPanel, self).move(frameGm.topLeft())
2140
2141 - def setWindowPos(self, ulx, uly):
2142 ''' 2143 Sets the screen position of the graphics window. 2144 @param ulx: the upper left corner's x-coordinate 2145 @param ulx: the upper left corner's y-coordinate 2146 ''' 2147 super(GPanel, self).move(ulx, uly)
2148
2149 - def saveGraphics(self):
2150 ''' 2151 Saves the current graphics into a image buffer. Use restoreGraphics() 2152 to restore it. 2153 ''' 2154 self._savePixmap = self._pixmap.copy(QRect())
2155
2156 - def restoreGraphics(self):
2157 ''' 2158 Restores the saved graphics from the image buffer. Use saveGraphics() 2159 to save it. 2160 ''' 2161 if self._savePixmap == None: 2162 raise Exception("Store graphics buffer is empty.") 2163 img = self._savePixmap.toImage() 2164 self._painter.drawImage(0, 0, img) 2165 if self._enableRepaint: 2166 self.repaint()
2167
2168 - def setXORMode(self, *args):
2169 ''' 2170 Performs pixel color XOR operation with the existing background pixel. 2171 Be aware that if the background is white, drawing with a white pen shows a black pixel. 2172 (Parameter not used, for TigerJython compatibility) 2173 ''' 2174 self._painter.setCompositionMode(QPainter.RasterOp_SourceXorDestination)
2175 2176
2177 - def setPaintMode(self):
2178 ''' 2179 Resets the drawing mode to standard (overwriting). 2180 ''' 2181 self._painter.setCompositionMode(QPainter.CompositionMode_SourceOver)
2182
2183 - def windowPosition(self, ulx, uly):
2184 ''' 2185 Sets the screen position (pixel coordinates of upper left corner). 2186 ''' 2187 super(GPanel, self).move(ulx, uly)
2188
2189 - def windowCenter(self):
2190 ''' 2191 Sets the window to the center of the screen. 2192 ''' 2193 xc, yc = GPanel.getScreenCenter() 2194 self.windowPosition(xc - self.winWidth // 2, yc - self.winHeight // 2)
2195 2196 2197 # ------------- Mouse events ----------------------------
2198 - def mousePressEvent(self, e):
2199 pos = QPoint(e.pos()) 2200 self._isLeftMouseButton = (e.button() == Qt.LeftButton) 2201 self._isRightMouseButton = (e.button() == Qt.RightButton) 2202 if self._onMousePressed != None: 2203 self._onMousePressed(self.toUserX(pos.x()), self.toUserY(pos.y()))
2204
2205 - def mouseReleaseEvent(self, e):
2206 pos = QPoint(e.pos()) 2207 self._isLeftMouseButton = (e.button() == Qt.LeftButton) 2208 self._isRightMouseButton = (e.button() != Qt.RightButton) 2209 if self._onMouseReleased != None: 2210 self._onMouseReleased(self.toUserX(pos.x()), self.toUserY(pos.y()))
2211
2212 - def mouseMoveEvent(self, e):
2213 # reject reentrance 2214 if self._inMouseMoveCallback: 2215 return 2216 self._inMouseMoveCallback = True 2217 pos = QPoint(e.pos()) 2218 if self._onMouseDragged != None: 2219 self._onMouseDragged(self.toUserX(pos.x()), self.toUserY(pos.y())) 2220 self._inMouseMoveCallback = False
2221 2222 # ------------- Key events ---------------------------
2223 - def keyPressEvent(self, e):
2224 key = e.key() 2225 if self._onKeyPressed != None: 2226 self._onKeyPressed(key)
2227
2228 - def keyReleaseEvent(self, e):
2229 key = e.key() 2230 if self._onKeyReleased != None: 2231 self._onKeyReleased(key)
2232 2233 # ------------- static methods ------------------------------- 2234 @staticmethod
2235 - def loadImage(filename, pic_format = None):
2236 ''' 2237 Returns a QImage of the picture loaded from the given file. For pic_format = None, 2238 the picture format is guessed from the file data. 2239 @param: the file path to the picture file 2240 @param pic_format: format of picture, supported: "None" (default), "GIF", "JPG", 2241 "BMP", "PNG", "PBM", "PGM", "PPM", "TIFF", "XBM" "XPM". 2242 ''' 2243 img = QImage(filename, pic_format) 2244 return img
2245 2246 @staticmethod
2247 - def getPixelColorImg(image, xPix, yPix):
2248 ''' 2249 Returns a tuple with the RGBA values at given pixel position (pixel coordinates). 2250 @param image: the QImage reference 2251 @param xPix: the pixel x-coordinate 2252 @param yPix: the pixel y-coordinate 2253 ''' 2254 c = image.pixel(xPix, yPix) 2255 return QColor(c).getRgb() # RGBA
2256 2257 @staticmethod
2258 - def scale(image, scaleFactor):
2259 ''' 2260 Returns a new QImage of the scaled picture of the given QImage. 2261 @param image: the original QImage reference 2262 @param scaleFactor: the scale factor 2263 ''' 2264 width = int(image.width() * scaleFactor) 2265 img = image.scaledToWidth(width) 2266 return img
2267 2268 @staticmethod
2269 - def crop(image, x1, y1, x2, y2):
2270 ''' 2271 Returns a QImage of the sub-area of the given QImage. 2272 @param image: the given QImage reference 2273 @param xPix: the pixel ulx-coordinate 2274 @param yPix: the pixel uly-coordinate 2275 ''' 2276 width = abs(x2 - x1) 2277 height = abs(y2 - y1) 2278 img = image.copy(x1, y1, width, height) 2279 return img
2280 2281 @staticmethod
2282 - def getDividingPoint(x1, y1, x2, y2, ratio):
2283 ''' 2284 Returns the tuple of user coordinates of the point on the line through the point pt1 = (x1, y1) 2285 and the point pt2 = (x2, y2) that is in distance ratio times the length from pt1 to pt2 from 2286 pt1. For ratio < 0 the point is in the opposite direction. 2287 3 parameteters: pt1, pt2 (complex/list/tuple), ratio 2288 5 parameteters: x1, y1, x2, y2, ratio 2289 ''' 2290 v1 = (x1, y1) 2291 v2 = (x2, y2) 2292 dv = (v2[0] - v1[0], v2[1] - v1[1]) # = v2 - v1 2293 v = (v1[0] + ratio * dv[0], v1[1] + ratio * dv[1]) # v1 + ratio * dv 2294 return v[0], v[1]
2295 2296 @staticmethod
2297 - def floodFill(pm, pt, oldColor, newColor):
2298 # Implementation from Hardik Gajjar of algorithm 2299 # at http://en.wikipedia.org/wiki/Flood_fill 2300 ''' 2301 Fills a bounded single-colored region with 2302 the given color. The given point is part of the region and used 2303 to specify it. 2304 @param pm the pixmap containing the connected region 2305 @param pt a point inside the region 2306 @param oldColor the old color of the region (RGB list/tuple) 2307 @param newColor the new color of the region (RGB list/tuple) 2308 @return a new qImage with the transformed region 2309 ''' 2310 image = pm.toImage() 2311 oldColor = QColor(oldColor[0], oldColor[1], oldColor[2]).rgb() 2312 newColor = QColor(newColor[0], newColor[1], newColor[2]).rgb() 2313 q = [pt] 2314 2315 # Perform filling operation 2316 while len(q) > 0: 2317 n = q.pop(0) 2318 if QColor(image.pixel(n[0], n[1])).rgb() != oldColor: 2319 continue 2320 2321 w = n 2322 e = [n[0] + 1, n[1]] 2323 while w[0] > 0 and QColor(image.pixel(w[0], w[1])).rgb() == oldColor: 2324 image.setPixel(w[0], w[1], newColor) 2325 if w[1] > 0 and QColor(image.pixel(w[0], w[1] - 1)).rgb() == oldColor: 2326 q.append([w[0], w[1] - 1]) 2327 if w[1] < image.height() - 1 and QColor(image.pixel(w[0], w[1] + 1)).rgb() == oldColor: 2328 q.append([w[0], w[1] + 1]) 2329 w[0] -= 1 2330 2331 while e[0] < image.width() - 1 and QColor(image.pixel(e[0], e[1])).rgb() == oldColor: 2332 image.setPixel(e[0], e[1], newColor) 2333 if e[1] > 0 and QColor(image.pixel(e[0], e[1] - 1)).rgb() == oldColor: 2334 q.append([e[0], e[1] - 1]) 2335 if e[1] < image.height() - 1 and QColor(image.pixel(e[0], e[1] + 1)).rgb() == oldColor: 2336 q.append([e[0], e[1] + 1]) 2337 e[0] += 1 2338 return image
2339 2340 @staticmethod
2341 - def getRandomX11Color():
2342 ''' 2343 Returns a random X11 color string. 2344 ''' 2345 r = random.randint(0, 540) 2346 c = x11ColorDict.keys() 2347 return c[r]
2348 2349 @staticmethod
2350 - def getScreenCenter():
2351 ''' 2352 Returns x, y coordinates tuple of the screen's center point. 2353 ''' 2354 centerPoint = QtGui.QDesktopWidget().availableGeometry().center() 2355 return centerPoint.x(), centerPoint.y()
2356 2357 # ----------------------------- GPane class ------------------------- 2358 ''' 2359 Subclass of GPanel to be used as embedded QWidget in a GUI dialog (QDialog). 2360 '''
2361 -class GPane(GPanel):
2362
2363 - def __init__(self, *args, **kwargs):
2364 ''' 2365 Creates a GPanel with no application window. 2366 ''' 2367 super(GPane, self).__init__(*args, embedded = True)
2368 2369 2370 # ----------------------------- Useful constants ------------------------- 2371 ''' 2372 X11 to RGB color mapping 2373 ''' 2374 x11ColorDict = { 2375 "aqua":[0, 255, 255], 2376 "cornflower":[100, 149, 237], 2377 "crimson":[220, 20, 60], 2378 "fuchsia":[255, 0, 255], 2379 "indigo":[75, 0, 130], 2380 "lime":[50, 205, 50], 2381 "silver":[192, 192, 192], 2382 "ghost white":[248, 248, 255], 2383 "snow":[255, 250, 250], 2384 "ghostwhite":[248, 248, 255], 2385 "white smoke":[245, 245, 245], 2386 "whitesmoke":[245, 245, 245], 2387 "gainsboro":[220, 220, 220], 2388 "floral white":[255, 250, 240], 2389 "floralwhite":[255, 250, 240], 2390 "old lace":[253, 245, 230], 2391 "oldlace":[253, 245, 230], 2392 "linen":[250, 240, 230], 2393 "antique white":[250, 235, 215], 2394 "antiquewhite":[250, 235, 215], 2395 "papaya whip":[255, 239, 213], 2396 "papayawhip":[255, 239, 213], 2397 "blanched almond":[255, 235, 205], 2398 "blanchedalmond":[255, 235, 205], 2399 "bisque":[255, 228, 196], 2400 "peach puff":[255, 218, 185], 2401 "peachpuff":[255, 218, 185], 2402 "navajo white":[255, 222, 173], 2403 "navajowhite":[255, 222, 173], 2404 "moccasin":[255, 228, 181], 2405 "cornsilk":[255, 248, 220], 2406 "ivory":[255, 255, 240], 2407 "lemon chiffon":[255, 250, 205], 2408 "lemonchiffon":[255, 250, 205], 2409 "seashell":[255, 245, 238], 2410 "honeydew":[240, 255, 240], 2411 "mint cream":[245, 255, 250], 2412 "mintcream":[245, 255, 250], 2413 "azure":[240, 255, 255], 2414 "alice blue":[240, 248, 255], 2415 "aliceblue":[240, 248, 255], 2416 "lavender":[230, 230, 250], 2417 "lavender blush":[255, 240, 245], 2418 "lavenderblush":[255, 240, 245], 2419 "misty rose":[255, 228, 225], 2420 "mistyrose":[255, 228, 225], 2421 "white":[255, 255, 255], 2422 "black":[0, 0, 0], 2423 "dark slate gray":[47, 79, 79], 2424 "darkslategray":[47, 79, 79], 2425 "dark slate grey":[47, 79, 79], 2426 "darkslategrey":[47, 79, 79], 2427 "dim gray":[105, 105, 105], 2428 "dimgray":[105, 105, 105], 2429 "dim grey":[105, 105, 105], 2430 "dimgrey":[105, 105, 105], 2431 "slate gray":[112, 128, 144], 2432 "slategray":[112, 128, 144], 2433 "slate grey":[112, 128, 144], 2434 "slategrey":[112, 128, 144], 2435 "light slate gray":[119, 136, 153], 2436 "lightslategray":[119, 136, 153], 2437 "light slate grey":[119, 136, 153], 2438 "lightslategrey":[119, 136, 153], 2439 "gray":[190, 190, 190], 2440 "grey":[190, 190, 190], 2441 "light grey":[211, 211, 211], 2442 "lightgrey":[211, 211, 211], 2443 "light gray":[211, 211, 211], 2444 "lightgray":[211, 211, 211], 2445 "midnight blue":[25, 25, 112], 2446 "midnightblue":[25, 25, 112], 2447 "navy":[0, 0, 128], 2448 "navy blue":[0, 0, 128], 2449 "navyblue":[0, 0, 128], 2450 "cornflower blue":[100, 149, 237], 2451 "cornflowerblue":[100, 149, 237], 2452 "dark slate blue":[72, 61, 139], 2453 "darkslateblue":[72, 61, 139], 2454 "slate blue":[106, 90, 205], 2455 "slateblue":[106, 90, 205], 2456 "medium slate blue":[123, 104, 238], 2457 "mediumslateblue":[123, 104, 238], 2458 "light slate blue":[132, 112, 255], 2459 "lightslateblue":[132, 112, 255], 2460 "medium blue":[0, 0, 205], 2461 "mediumblue":[0, 0, 205], 2462 "royal blue":[65, 105, 225], 2463 "royalblue":[65, 105, 225], 2464 "blue":[0, 0, 255], 2465 "dodger blue":[30, 144, 255], 2466 "dodgerblue":[30, 144, 255], 2467 "deep sky blue":[0, 191, 255], 2468 "deepskyblue":[0, 191, 255], 2469 "sky blue":[135, 206, 235], 2470 "skyblue":[135, 206, 235], 2471 "light sky blue":[135, 206, 250], 2472 "lightskyblue":[135, 206, 250], 2473 "steel blue":[70, 130, 180], 2474 "steelblue":[70, 130, 180], 2475 "light steel blue":[176, 196, 222], 2476 "lightsteelblue":[176, 196, 222], 2477 "light blue":[173, 216, 230], 2478 "lightblue":[173, 216, 230], 2479 "powder blue":[176, 224, 230], 2480 "powderblue":[176, 224, 230], 2481 "pale turquoise":[175, 238, 238], 2482 "paleturquoise":[175, 238, 238], 2483 "dark turquoise":[0, 206, 209], 2484 "darkturquoise":[0, 206, 209], 2485 "medium turquoise":[72, 209, 204], 2486 "mediumturquoise":[72, 209, 204], 2487 "turquoise":[64, 224, 208], 2488 "cyan":[0, 255, 255], 2489 "light cyan":[224, 255, 255], 2490 "lightcyan":[224, 255, 255], 2491 "cadet blue":[95, 158, 160], 2492 "cadetblue":[95, 158, 160], 2493 "medium aquamarine":[102, 205, 170], 2494 "mediumaquamarine":[102, 205, 170], 2495 "aquamarine":[127, 255, 212], 2496 "dark green":[0, 100, 0], 2497 "darkgreen":[0, 100, 0], 2498 "dark olive green":[85, 107, 47], 2499 "darkolivegreen":[85, 107, 47], 2500 "dark sea green":[143, 188, 143], 2501 "darkseagreen":[143, 188, 143], 2502 "sea green":[46, 139, 87], 2503 "seagreen":[46, 139, 87], 2504 "medium sea green":[60, 179, 113], 2505 "mediumseagreen":[60, 179, 113], 2506 "light sea green":[32, 178, 170], 2507 "lightseagreen":[32, 178, 170], 2508 "pale green":[152, 251, 152], 2509 "palegreen":[152, 251, 152], 2510 "spring green":[0, 255, 127], 2511 "springgreen":[0, 255, 127], 2512 "lawn green":[124, 252, 0], 2513 "lawngreen":[124, 252, 0], 2514 "green":[0, 255, 0], 2515 "chartreuse":[127, 255, 0], 2516 "medium spring green":[0, 250, 154], 2517 "mediumspringgreen":[0, 250, 154], 2518 "green yellow":[173, 255, 47], 2519 "greenyellow":[173, 255, 47], 2520 "lime green":[50, 205, 50], 2521 "limegreen":[50, 205, 50], 2522 "yellow green":[154, 205, 50], 2523 "yellowgreen":[154, 205, 50], 2524 "forest green":[34, 139, 34], 2525 "forestgreen":[34, 139, 34], 2526 "olive drab":[107, 142, 35], 2527 "olivedrab":[107, 142, 35], 2528 "dark khaki":[189, 183, 107], 2529 "darkkhaki":[189, 183, 107], 2530 "khaki":[240, 230, 140], 2531 "pale goldenrod":[238, 232, 170], 2532 "palegoldenrod":[238, 232, 170], 2533 "light goldenrod yellow":[250, 250, 210], 2534 "lightgoldenrodyellow":[250, 250, 210], 2535 "light yellow":[255, 255, 224], 2536 "lightyellow":[255, 255, 224], 2537 "yellow":[255, 255, 0], 2538 "gold":[255, 215, 0], 2539 "light goldenrod":[238, 221, 130], 2540 "lightgoldenrod":[238, 221, 130], 2541 "goldenrod":[218, 165, 32], 2542 "dark goldenrod":[184, 134, 11], 2543 "darkgoldenrod":[184, 134, 11], 2544 "rosy brown":[188, 143, 143], 2545 "rosybrown":[188, 143, 143], 2546 "indian red":[205, 92, 92], 2547 "indianred":[205, 92, 92], 2548 "saddle brown":[139, 69, 19], 2549 "saddlebrown":[139, 69, 19], 2550 "sienna":[160, 82, 45], 2551 "peru":[205, 133, 63], 2552 "burlywood":[222, 184, 135], 2553 "beige":[245, 245, 220], 2554 "wheat":[245, 222, 179], 2555 "sandy brown":[244, 164, 96], 2556 "sandybrown":[244, 164, 96], 2557 "tan":[210, 180, 140], 2558 "chocolate":[210, 105, 30], 2559 "firebrick":[178, 34, 34], 2560 "brown":[165, 42, 42], 2561 "dark salmon":[233, 150, 122], 2562 "darksalmon":[233, 150, 122], 2563 "salmon":[250, 128, 114], 2564 "light salmon":[255, 160, 122], 2565 "lightsalmon":[255, 160, 122], 2566 "orange":[255, 165, 0], 2567 "dark orange":[255, 140, 0], 2568 "darkorange":[255, 140, 0], 2569 "coral":[255, 127, 80], 2570 "light coral":[240, 128, 128], 2571 "lightcoral":[240, 128, 128], 2572 "tomato":[255, 99, 71], 2573 "orange red":[255, 69, 0], 2574 "orangered":[255, 69, 0], 2575 "red":[255, 0, 0], 2576 "hot pink":[255, 105, 180], 2577 "hotpink":[255, 105, 180], 2578 "deep pink":[255, 20, 147], 2579 "deeppink":[255, 20, 147], 2580 "pink":[255, 192, 203], 2581 "light pink":[255, 182, 193], 2582 "lightpink":[255, 182, 193], 2583 "pale violet red":[219, 112, 147], 2584 "palevioletred":[219, 112, 147], 2585 "maroon":[176, 48, 96], 2586 "medium violet red":[199, 21, 133], 2587 "mediumvioletred":[199, 21, 133], 2588 "violet red":[208, 32, 144], 2589 "violetred":[208, 32, 144], 2590 "magenta":[255, 0, 255], 2591 "violet":[238, 130, 238], 2592 "plum":[221, 160, 221], 2593 "orchid":[218, 112, 214], 2594 "medium orchid":[186, 85, 211], 2595 "mediumorchid":[186, 85, 211], 2596 "dark orchid":[153, 50, 204], 2597 "darkorchid":[153, 50, 204], 2598 "dark violet":[148, 0, 211], 2599 "darkviolet":[148, 0, 211], 2600 "blue violet":[138, 43, 226], 2601 "blueviolet":[138, 43, 226], 2602 "purple":[160, 32, 240], 2603 "medium purple":[147, 112, 219], 2604 "mediumpurple":[147, 112, 219], 2605 "thistle":[216, 191, 216], 2606 "snow1":[255, 250, 250], 2607 "snow2":[238, 233, 233], 2608 "snow3":[205, 201, 201], 2609 "snow4":[139, 137, 137], 2610 "seashell1":[255, 245, 238], 2611 "seashell2":[238, 229, 222], 2612 "seashell3":[205, 197, 191], 2613 "seashell4":[139, 134, 130], 2614 "antiquewhite1":[255, 239, 219], 2615 "antiquewhite2":[238, 223, 204], 2616 "antiquewhite3":[205, 192, 176], 2617 "antiquewhite4":[139, 131, 120], 2618 "bisque1":[255, 228, 196], 2619 "bisque2":[238, 213, 183], 2620 "bisque3":[205, 183, 158], 2621 "bisque4":[139, 125, 107], 2622 "peachpuff1":[255, 218, 185], 2623 "peachpuff2":[238, 203, 173], 2624 "peachpuff3":[205, 175, 149], 2625 "peachpuff4":[139, 119, 101], 2626 "navajowhite1":[255, 222, 173], 2627 "navajowhite2":[238, 207, 161], 2628 "navajowhite3":[205, 179, 139], 2629 "navajowhite4":[139, 121, 94], 2630 "lemonchiffon1":[255, 250, 205], 2631 "lemonchiffon2":[238, 233, 191], 2632 "lemonchiffon3":[205, 201, 165], 2633 "lemonchiffon4":[139, 137, 112], 2634 "cornsilk1":[255, 248, 220], 2635 "cornsilk2":[238, 232, 205], 2636 "cornsilk3":[205, 200, 177], 2637 "cornsilk4":[139, 136, 120], 2638 "ivory1":[255, 255, 240], 2639 "ivory2":[238, 238, 224], 2640 "ivory3":[205, 205, 193], 2641 "ivory4":[139, 139, 131], 2642 "honeydew1":[240, 255, 240], 2643 "honeydew2":[224, 238, 224], 2644 "honeydew3":[193, 205, 193], 2645 "honeydew4":[131, 139, 131], 2646 "lavenderblush1":[255, 240, 245], 2647 "lavenderblush2":[238, 224, 229], 2648 "lavenderblush3":[205, 193, 197], 2649 "lavenderblush4":[139, 131, 134], 2650 "mistyrose1":[255, 228, 225], 2651 "mistyrose2":[238, 213, 210], 2652 "mistyrose3":[205, 183, 181], 2653 "mistyrose4":[139, 125, 123], 2654 "azure1":[240, 255, 255], 2655 "azure2":[224, 238, 238], 2656 "azure3":[193, 205, 205], 2657 "azure4":[131, 139, 139], 2658 "slateblue1":[131, 111, 255], 2659 "slateblue2":[122, 103, 238], 2660 "slateblue3":[105, 89, 205], 2661 "slateblue4":[71, 60, 139], 2662 "royalblue1":[72, 118, 255], 2663 "royalblue2":[67, 110, 238], 2664 "royalblue3":[58, 95, 205], 2665 "royalblue4":[39, 64, 139], 2666 "blue1":[0, 0, 255], 2667 "blue2":[0, 0, 238], 2668 "blue3":[0, 0, 205], 2669 "blue4":[0, 0, 139], 2670 "dodgerblue1":[30, 144, 255], 2671 "dodgerblue2":[28, 134, 238], 2672 "dodgerblue3":[24, 116, 205], 2673 "dodgerblue4":[16, 78, 139], 2674 "steelblue1":[99, 184, 255], 2675 "steelblue2":[92, 172, 238], 2676 "steelblue3":[79, 148, 205], 2677 "steelblue4":[54, 100, 139], 2678 "deepskyblue1":[0, 191, 255], 2679 "deepskyblue2":[0, 178, 238], 2680 "deepskyblue3":[0, 154, 205], 2681 "deepskyblue4":[0, 104, 139], 2682 "skyblue1":[135, 206, 255], 2683 "skyblue2":[126, 192, 238], 2684 "skyblue3":[108, 166, 205], 2685 "skyblue4":[74, 112, 139], 2686 "lightskyblue1":[176, 226, 255], 2687 "lightskyblue2":[164, 211, 238], 2688 "lightskyblue3":[141, 182, 205], 2689 "lightskyblue4":[96, 123, 139], 2690 "slategray1":[198, 226, 255], 2691 "slategray2":[185, 211, 238], 2692 "slategray3":[159, 182, 205], 2693 "slategray4":[108, 123, 139], 2694 "lightsteelblue1":[202, 225, 255], 2695 "lightsteelblue2":[188, 210, 238], 2696 "lightsteelblue3":[162, 181, 205], 2697 "lightsteelblue4":[110, 123, 139], 2698 "lightblue1":[191, 239, 255], 2699 "lightblue2":[178, 223, 238], 2700 "lightblue3":[154, 192, 205], 2701 "lightblue4":[104, 131, 139], 2702 "lightcyan1":[224, 255, 255], 2703 "lightcyan2":[209, 238, 238], 2704 "lightcyan3":[180, 205, 205], 2705 "lightcyan4":[122, 139, 139], 2706 "paleturquoise1":[187, 255, 255], 2707 "paleturquoise2":[174, 238, 238], 2708 "paleturquoise3":[150, 205, 205], 2709 "paleturquoise4":[102, 139, 139], 2710 "cadetblue1":[152, 245, 255], 2711 "cadetblue2":[142, 229, 238], 2712 "cadetblue3":[122, 197, 205], 2713 "cadetblue4":[83, 134, 139], 2714 "turquoise1":[0, 245, 255], 2715 "turquoise2":[0, 229, 238], 2716 "turquoise3":[0, 197, 205], 2717 "turquoise4":[0, 134, 139], 2718 "cyan1":[0, 255, 255], 2719 "cyan2":[0, 238, 238], 2720 "cyan3":[0, 205, 205], 2721 "cyan4":[0, 139, 139], 2722 "darkslategray1":[151, 255, 255], 2723 "darkslategray2":[141, 238, 238], 2724 "darkslategray3":[121, 205, 205], 2725 "darkslategray4":[82, 139, 139], 2726 "aquamarine1":[127, 255, 212], 2727 "aquamarine2":[118, 238, 198], 2728 "aquamarine3":[102, 205, 170], 2729 "aquamarine4":[69, 139, 116], 2730 "darkseagreen1":[193, 255, 193], 2731 "darkseagreen2":[180, 238, 180], 2732 "darkseagreen3":[155, 205, 155], 2733 "darkseagreen4":[105, 139, 105], 2734 "seagreen1":[84, 255, 159], 2735 "seagreen2":[78, 238, 148], 2736 "seagreen3":[67, 205, 128], 2737 "seagreen4":[46, 139, 87], 2738 "palegreen1":[154, 255, 154], 2739 "palegreen2":[144, 238, 144], 2740 "palegreen3":[124, 205, 124], 2741 "palegreen4":[84, 139, 84], 2742 "springgreen1":[0, 255, 127], 2743 "springgreen2":[0, 238, 118], 2744 "springgreen3":[0, 205, 102], 2745 "springgreen4":[0, 139, 69], 2746 "green1":[0, 255, 0], 2747 "green2":[0, 238, 0], 2748 "green3":[0, 205, 0], 2749 "green4":[0, 139, 0], 2750 "chartreuse1":[127, 255, 0], 2751 "chartreuse2":[118, 238, 0], 2752 "chartreuse3":[102, 205, 0], 2753 "chartreuse4":[69, 139, 0], 2754 "olivedrab1":[192, 255, 62], 2755 "olivedrab2":[179, 238, 58], 2756 "olivedrab3":[154, 205, 50], 2757 "olivedrab4":[105, 139, 34], 2758 "darkolivegreen1":[202, 255, 112], 2759 "darkolivegreen2":[188, 238, 104], 2760 "darkolivegreen3":[162, 205, 90], 2761 "darkolivegreen4":[110, 139, 61], 2762 "khaki1":[255, 246, 143], 2763 "khaki2":[238, 230, 133], 2764 "khaki3":[205, 198, 115], 2765 "khaki4":[139, 134, 78], 2766 "lightgoldenrod1":[255, 236, 139], 2767 "lightgoldenrod2":[238, 220, 130], 2768 "lightgoldenrod3":[205, 190, 112], 2769 "lightgoldenrod4":[139, 129, 76], 2770 "lightyellow1":[255, 255, 224], 2771 "lightyellow2":[238, 238, 209], 2772 "lightyellow3":[205, 205, 180], 2773 "lightyellow4":[139, 139, 122], 2774 "yellow1":[255, 255, 0], 2775 "yellow2":[238, 238, 0], 2776 "yellow3":[205, 205, 0], 2777 "yellow4":[139, 139, 0], 2778 "gold1":[255, 215, 0], 2779 "gold2":[238, 201, 0], 2780 "gold3":[205, 173, 0], 2781 "gold4":[139, 117, 0], 2782 "goldenrod1":[255, 193, 37], 2783 "goldenrod2":[238, 180, 34], 2784 "goldenrod3":[205, 155, 29], 2785 "goldenrod4":[139, 105, 20], 2786 "darkgoldenrod1":[255, 185, 15], 2787 "darkgoldenrod2":[238, 173, 14], 2788 "darkgoldenrod3":[205, 149, 12], 2789 "darkgoldenrod4":[139, 101, 8], 2790 "rosybrown1":[255, 193, 193], 2791 "rosybrown2":[238, 180, 180], 2792 "rosybrown3":[205, 155, 155], 2793 "rosybrown4":[139, 105, 105], 2794 "indianred1":[255, 106, 106], 2795 "indianred2":[238, 99, 99], 2796 "indianred3":[205, 85, 85], 2797 "indianred4":[139, 58, 58], 2798 "sienna1":[255, 130, 71], 2799 "sienna2":[238, 121, 66], 2800 "sienna3":[205, 104, 57], 2801 "sienna4":[139, 71, 38], 2802 "burlywood1":[255, 211, 155], 2803 "burlywood2":[238, 197, 145], 2804 "burlywood3":[205, 170, 125], 2805 "burlywood4":[139, 115, 85], 2806 "wheat1":[255, 231, 186], 2807 "wheat2":[238, 216, 174], 2808 "wheat3":[205, 186, 150], 2809 "wheat4":[139, 126, 102], 2810 "tan1":[255, 165, 79], 2811 "tan2":[238, 154, 73], 2812 "tan3":[205, 133, 63], 2813 "tan4":[139, 90, 43], 2814 "chocolate1":[255, 127, 36], 2815 "chocolate2":[238, 118, 33], 2816 "chocolate3":[205, 102, 29], 2817 "chocolate4":[139, 69, 19], 2818 "firebrick1":[255, 48, 48], 2819 "firebrick2":[238, 44, 44], 2820 "firebrick3":[205, 38, 38], 2821 "firebrick4":[139, 26, 26], 2822 "brown1":[255, 64, 64], 2823 "brown2":[238, 59, 59], 2824 "brown3":[205, 51, 51], 2825 "brown4":[139, 35, 35], 2826 "salmon1":[255, 140, 105], 2827 "salmon2":[238, 130, 98], 2828 "salmon3":[205, 112, 84], 2829 "salmon4":[139, 76, 57], 2830 "lightsalmon1":[255, 160, 122], 2831 "lightsalmon2":[238, 149, 114], 2832 "lightsalmon3":[205, 129, 98], 2833 "lightsalmon4":[139, 87, 66], 2834 "orange1":[255, 165, 0], 2835 "orange2":[238, 154, 0], 2836 "orange3":[205, 133, 0], 2837 "orange4":[139, 90, 0], 2838 "darkorange1":[255, 127, 0], 2839 "darkorange2":[238, 118, 0], 2840 "darkorange3":[205, 102, 0], 2841 "darkorange4":[139, 69, 0], 2842 "coral1":[255, 114, 86], 2843 "coral2":[238, 106, 80], 2844 "coral3":[205, 91, 69], 2845 "coral4":[139, 62, 47], 2846 "tomato1":[255, 99, 71], 2847 "tomato2":[238, 92, 66], 2848 "tomato3":[205, 79, 57], 2849 "tomato4":[139, 54, 38], 2850 "orangered1":[255, 69, 0], 2851 "orangered2":[238, 64, 0], 2852 "orangered3":[205, 55, 0], 2853 "orangered4":[139, 37, 0], 2854 "red1":[255, 0, 0], 2855 "red2":[238, 0, 0], 2856 "red3":[205, 0, 0], 2857 "red4":[139, 0, 0], 2858 "deeppink1":[255, 20, 147], 2859 "deeppink2":[238, 18, 137], 2860 "deeppink3":[205, 16, 118], 2861 "deeppink4":[139, 10, 80], 2862 "hotpink1":[255, 110, 180], 2863 "hotpink2":[238, 106, 167], 2864 "hotpink3":[205, 96, 144], 2865 "hotpink4":[139, 58, 98], 2866 "pink1":[255, 181, 197], 2867 "pink2":[238, 169, 184], 2868 "pink3":[205, 145, 158], 2869 "pink4":[139, 99, 108], 2870 "lightpink1":[255, 174, 185], 2871 "lightpink2":[238, 162, 173], 2872 "lightpink3":[205, 140, 149], 2873 "lightpink4":[139, 95, 101], 2874 "palevioletred1":[255, 130, 171], 2875 "palevioletred2":[238, 121, 159], 2876 "palevioletred3":[205, 104, 137], 2877 "palevioletred4":[139, 71, 93], 2878 "maroon1":[255, 52, 179], 2879 "maroon2":[238, 48, 167], 2880 "maroon3":[205, 41, 144], 2881 "maroon4":[139, 28, 98], 2882 "violetred1":[255, 62, 150], 2883 "violetred2":[238, 58, 140], 2884 "violetred3":[205, 50, 120], 2885 "violetred4":[139, 34, 82], 2886 "magenta1":[255, 0, 255], 2887 "magenta2":[238, 0, 238], 2888 "magenta3":[205, 0, 205], 2889 "magenta4":[139, 0, 139], 2890 "orchid1":[255, 131, 250], 2891 "orchid2":[238, 122, 233], 2892 "orchid3":[205, 105, 201], 2893 "orchid4":[139, 71, 137], 2894 "plum1":[255, 187, 255], 2895 "plum2":[238, 174, 238], 2896 "plum3":[205, 150, 205], 2897 "plum4":[139, 102, 139], 2898 "mediumorchid1":[224, 102, 255], 2899 "mediumorchid2":[209, 95, 238], 2900 "mediumorchid3":[180, 82, 205], 2901 "mediumorchid4":[122, 55, 139], 2902 "darkorchid1":[191, 62, 255], 2903 "darkorchid2":[178, 58, 238], 2904 "darkorchid3":[154, 50, 205], 2905 "darkorchid4":[104, 34, 139], 2906 "purple1":[155, 48, 255], 2907 "purple2":[145, 44, 238], 2908 "purple3":[125, 38, 205], 2909 "purple4":[85, 26, 139], 2910 "mediumpurple1":[171, 130, 255], 2911 "mediumpurple2":[159, 121, 238], 2912 "mediumpurple3":[137, 104, 205], 2913 "mediumpurple4":[93, 71, 139], 2914 "thistle1":[255, 225, 255], 2915 "thistle2":[238, 210, 238], 2916 "thistle3":[205, 181, 205], 2917 "thistle4":[139, 123, 139], 2918 "gray0":[0, 0, 0], 2919 "grey0":[0, 0, 0], 2920 "gray1":[3, 3, 3], 2921 "grey1":[3, 3, 3], 2922 "gray2":[5, 5, 5], 2923 "grey2":[5, 5, 5], 2924 "gray3":[8, 8, 8], 2925 "grey3":[8, 8, 8], 2926 "gray4":[10, 10, 10], 2927 "grey4":[10, 10, 10], 2928 "gray5":[13, 13, 13], 2929 "grey5":[13, 13, 13], 2930 "gray6":[15, 15, 15], 2931 "grey6":[15, 15, 15], 2932 "gray7":[18, 18, 18], 2933 "grey7":[18, 18, 18], 2934 "gray8":[20, 20, 20], 2935 "grey8":[20, 20, 20], 2936 "gray9":[23, 23, 23], 2937 "grey9":[23, 23, 23], 2938 "gray10":[26, 26, 26], 2939 "grey10":[26, 26, 26], 2940 "gray11":[28, 28, 28], 2941 "grey11":[28, 28, 28], 2942 "gray12":[31, 31, 31], 2943 "grey12":[31, 31, 31], 2944 "gray13":[33, 33, 33], 2945 "grey13":[33, 33, 33], 2946 "gray14":[36, 36, 36], 2947 "grey14":[36, 36, 36], 2948 "gray15":[38, 38, 38], 2949 "grey15":[38, 38, 38], 2950 "gray16":[41, 41, 41], 2951 "grey16":[41, 41, 41], 2952 "gray17":[43, 43, 43], 2953 "grey17":[43, 43, 43], 2954 "gray18":[46, 46, 46], 2955 "grey18":[46, 46, 46], 2956 "gray19":[48, 48, 48], 2957 "grey19":[48, 48, 48], 2958 "gray20":[51, 51, 51], 2959 "grey20":[51, 51, 51], 2960 "gray21":[54, 54, 54], 2961 "grey21":[54, 54, 54], 2962 "gray22":[56, 56, 56], 2963 "grey22":[56, 56, 56], 2964 "gray23":[59, 59, 59], 2965 "grey23":[59, 59, 59], 2966 "gray24":[61, 61, 61], 2967 "grey24":[61, 61, 61], 2968 "gray25":[64, 64, 64], 2969 "grey25":[64, 64, 64], 2970 "gray26":[66, 66, 66], 2971 "grey26":[66, 66, 66], 2972 "gray27":[69, 69, 69], 2973 "grey27":[69, 69, 69], 2974 "gray28":[71, 71, 71], 2975 "grey28":[71, 71, 71], 2976 "gray29":[74, 74, 74], 2977 "grey29":[74, 74, 74], 2978 "gray30":[77, 77, 77], 2979 "grey30":[77, 77, 77], 2980 "gray31":[79, 79, 79], 2981 "grey31":[79, 79, 79], 2982 "gray32":[82, 82, 82], 2983 "grey32":[82, 82, 82], 2984 "gray33":[84, 84, 84], 2985 "grey33":[84, 84, 84], 2986 "gray34":[87, 87, 87], 2987 "grey34":[87, 87, 87], 2988 "gray35":[89, 89, 89], 2989 "grey35":[89, 89, 89], 2990 "gray36":[92, 92, 92], 2991 "grey36":[92, 92, 92], 2992 "gray37":[94, 94, 94], 2993 "grey37":[94, 94, 94], 2994 "gray38":[97, 97, 97], 2995 "grey38":[97, 97, 97], 2996 "gray39":[99, 99, 99], 2997 "grey39":[99, 99, 99], 2998 "gray40":[102, 102, 102], 2999 "grey40":[102, 102, 102], 3000 "gray41":[105, 105, 105], 3001 "grey41":[105, 105, 105], 3002 "gray42":[107, 107, 107], 3003 "grey42":[107, 107, 107], 3004 "gray43":[110, 110, 110], 3005 "grey43":[110, 110, 110], 3006 "gray44":[112, 112, 112], 3007 "grey44":[112, 112, 112], 3008 "gray45":[115, 115, 115], 3009 "grey45":[115, 115, 115], 3010 "gray46":[117, 117, 117], 3011 "grey46":[117, 117, 117], 3012 "gray47":[120, 120, 120], 3013 "grey47":[120, 120, 120], 3014 "gray48":[122, 122, 122], 3015 "grey48":[122, 122, 122], 3016 "gray49":[125, 125, 125], 3017 "grey49":[125, 125, 125], 3018 "gray50":[127, 127, 127], 3019 "grey50":[127, 127, 127], 3020 "gray51":[130, 130, 130], 3021 "grey51":[130, 130, 130], 3022 "gray52":[133, 133, 133], 3023 "grey52":[133, 133, 133], 3024 "gray53":[135, 135, 135], 3025 "grey53":[135, 135, 135], 3026 "gray54":[138, 138, 138], 3027 "grey54":[138, 138, 138], 3028 "gray55":[140, 140, 140], 3029 "grey55":[140, 140, 140], 3030 "gray56":[143, 143, 143], 3031 "grey56":[143, 143, 143], 3032 "gray57":[145, 145, 145], 3033 "grey57":[145, 145, 145], 3034 "gray58":[148, 148, 148], 3035 "grey58":[148, 148, 148], 3036 "gray59":[150, 150, 150], 3037 "grey59":[150, 150, 150], 3038 "gray60":[153, 153, 153], 3039 "grey60":[153, 153, 153], 3040 "gray61":[156, 156, 156], 3041 "grey61":[156, 156, 156], 3042 "gray62":[158, 158, 158], 3043 "grey62":[158, 158, 158], 3044 "gray63":[161, 161, 161], 3045 "grey63":[161, 161, 161], 3046 "gray64":[163, 163, 163], 3047 "grey64":[163, 163, 163], 3048 "gray65":[166, 166, 166], 3049 "grey65":[166, 166, 166], 3050 "gray66":[168, 168, 168], 3051 "grey66":[168, 168, 168], 3052 "gray67":[171, 171, 171], 3053 "grey67":[171, 171, 171], 3054 "gray68":[173, 173, 173], 3055 "grey68":[173, 173, 173], 3056 "gray69":[176, 176, 176], 3057 "grey69":[176, 176, 176], 3058 "gray70":[179, 179, 179], 3059 "grey70":[179, 179, 179], 3060 "gray71":[181, 181, 181], 3061 "grey71":[181, 181, 181], 3062 "gray72":[184, 184, 184], 3063 "grey72":[184, 184, 184], 3064 "gray73":[186, 186, 186], 3065 "grey73":[186, 186, 186], 3066 "gray74":[189, 189, 189], 3067 "grey74":[189, 189, 189], 3068 "gray75":[191, 191, 191], 3069 "grey75":[191, 191, 191], 3070 "gray76":[194, 194, 194], 3071 "grey76":[194, 194, 194], 3072 "gray77":[196, 196, 196], 3073 "grey77":[196, 196, 196], 3074 "gray78":[199, 199, 199], 3075 "grey78":[199, 199, 199], 3076 "gray79":[201, 201, 201], 3077 "grey79":[201, 201, 201], 3078 "gray80":[204, 204, 204], 3079 "grey80":[204, 204, 204], 3080 "gray81":[207, 207, 207], 3081 "grey81":[207, 207, 207], 3082 "gray82":[209, 209, 209], 3083 "grey82":[209, 209, 209], 3084 "gray83":[212, 212, 212], 3085 "grey83":[212, 212, 212], 3086 "gray84":[214, 214, 214], 3087 "grey84":[214, 214, 214], 3088 "gray85":[217, 217, 217], 3089 "grey85":[217, 217, 217], 3090 "gray86":[219, 219, 219], 3091 "grey86":[219, 219, 219], 3092 "gray87":[222, 222, 222], 3093 "grey87":[222, 222, 222], 3094 "gray88":[224, 224, 224], 3095 "grey88":[224, 224, 224], 3096 "gray89":[227, 227, 227], 3097 "grey89":[227, 227, 227], 3098 "gray90":[229, 229, 229], 3099 "grey90":[229, 229, 229], 3100 "gray91":[232, 232, 232], 3101 "grey91":[232, 232, 232], 3102 "gray92":[235, 235, 235], 3103 "grey92":[235, 235, 235], 3104 "gray93":[237, 237, 237], 3105 "grey93":[237, 237, 237], 3106 "gray94":[240, 240, 240], 3107 "grey94":[240, 240, 240], 3108 "gray95":[242, 242, 242], 3109 "grey95":[242, 242, 242], 3110 "gray96":[245, 245, 245], 3111 "grey96":[245, 245, 245], 3112 "gray97":[247, 247, 247], 3113 "grey97":[247, 247, 247], 3114 "gray98":[250, 250, 250], 3115 "grey98":[250, 250, 250], 3116 "gray99":[252, 252, 252], 3117 "grey99":[252, 252, 252], 3118 "gray100":[255, 255, 255], 3119 "grey100":[255, 255, 255], 3120 "dark grey":[169, 169, 169], 3121 "darkgrey":[169, 169, 169], 3122 "dark gray":[169, 169, 169], 3123 "darkgray":[169, 169, 169], 3124 "dark blue":[0, 0, 139], 3125 "darkblue":[0, 0, 139], 3126 "dark cyan":[0, 139, 139], 3127 "darkcyan":[0, 139, 139], 3128 "dark magenta":[139, 0, 139], 3129 "darkmagenta":[139, 0, 139], 3130 "dark red":[139, 0, 0], 3131 "darkred":[139, 0, 0], 3132 "light green":[144, 238, 144], 3133 "lightgreen":[144, 238, 144], 3134 "olive":[128, 128, 0], 3135 "teal":[0, 128, 128]} 3136 3137 3138 # ------------- Key constants ------------------------------- 3139 3140 ''' 3141 The key names used by Qt. 3142 Constant Value Description 3143 3144 Qt.Key_Escape 0x01000000 3145 3146 Qt.Key_Tab 0x01000001 3147 3148 Qt.Key_Backtab 0x01000002 3149 3150 Qt.Key_Backspace 0x01000003 3151 3152 Qt.Key_Return 0x01000004 3153 3154 Qt.Key_Enter 0x01000005 Typically located on the keypad. 3155 3156 Qt.Key_Insert 0x01000006 3157 3158 Qt.Key_Delete 0x01000007 3159 3160 Qt.Key_Pause 0x01000008 The Pause/Break key (Note: Not anything to do with pausing media) 3161 3162 Qt.Key_Print 0x01000009 3163 3164 Qt.Key_SysReq 0x0100000a 3165 3166 Qt.Key_Clear 0x0100000b 3167 3168 Qt.Key_Home 0x01000010 3169 3170 Qt.Key_End 0x01000011 3171 3172 Qt.Key_Left 0x01000012 3173 3174 Qt.Key_Up 0x01000013 3175 3176 Qt.Key_Right 0x01000014 3177 3178 Qt.Key_Down 0x01000015 3179 3180 Qt.Key_PageUp 0x01000016 3181 3182 Qt.Key_PageDown 0x01000017 3183 3184 Qt.Key_Shift 0x01000020 3185 3186 Qt.Key_Control 0x01000021 On Mac OS X, this corresponds to the Command keys. 3187 3188 Qt.Key_Meta 0x01000022 On Mac OS X, this corresponds to the Control keys. On Windows keyboards, this key is mapped to the Windows key. 3189 3190 Qt.Key_Alt 0x01000023 3191 3192 Qt.Key_AltGr 0x01001103 On Windows, when the KeyDown event for this key is sent, the Ctrl+Alt modifiers are also set. 3193 3194 Qt.Key_CapsLock 0x01000024 3195 3196 Qt.Key_NumLock 0x01000025 3197 3198 Qt.Key_ScrollLock 0x01000026 3199 3200 Qt.Key_F1 0x01000030 3201 3202 Qt.Key_F2 0x01000031 3203 3204 Qt.Key_F3 0x01000032 3205 3206 Qt.Key_F4 0x01000033 3207 3208 Qt.Key_F5 0x01000034 3209 3210 Qt.Key_F6 0x01000035 3211 3212 Qt.Key_F7 0x01000036 3213 3214 Qt.Key_F8 0x01000037 3215 3216 Qt.Key_F9 0x01000038 3217 3218 Qt.Key_F10 0x01000039 3219 3220 Qt.Key_F11 0x0100003a 3221 3222 Qt.Key_F12 0x0100003b 3223 3224 Qt.Key_F13 0x0100003c 3225 3226 Qt.Key_F14 0x0100003d 3227 3228 Qt.Key_F15 0x0100003e 3229 3230 Qt.Key_F16 0x0100003f 3231 3232 Qt.Key_F17 0x01000040 3233 3234 Qt.Key_F18 0x01000041 3235 3236 Qt.Key_F19 0x01000042 3237 3238 Qt.Key_F20 0x01000043 3239 3240 Qt.Key_F21 0x01000044 3241 3242 Qt.Key_F22 0x01000045 3243 3244 Qt.Key_F23 0x01000046 3245 3246 Qt.Key_F24 0x01000047 3247 3248 Qt.Key_F25 0x01000048 3249 3250 Qt.Key_F26 0x01000049 3251 3252 Qt.Key_F27 0x0100004a 3253 3254 Qt.Key_F28 0x0100004b 3255 3256 Qt.Key_F29 0x0100004c 3257 3258 Qt.Key_F30 0x0100004d 3259 3260 Qt.Key_F31 0x0100004e 3261 3262 Qt.Key_F32 0x0100004f 3263 3264 Qt.Key_F33 0x01000050 3265 3266 Qt.Key_F34 0x01000051 3267 3268 Qt.Key_F35 0x01000052 3269 3270 Qt.Key_Super_L 0x01000053 3271 3272 Qt.Key_Super_R 0x01000054 3273 3274 Qt.Key_Menu 0x01000055 3275 3276 Qt.Key_Hyper_L 0x01000056 3277 3278 Qt.Key_Hyper_R 0x01000057 3279 3280 Qt.Key_Help 0x01000058 3281 3282 Qt.Key_Direction_L 0x01000059 3283 3284 Qt.Key_Direction_R 0x01000060 3285 3286 Qt.Key_Space 0x20 3287 3288 Qt.Key_Any Key_Space 3289 3290 Qt.Key_Exclam 0x21 3291 3292 Qt.Key_QuoteDbl 0x22 3293 3294 Qt.Key_NumberSign 0x23 3295 3296 Qt.Key_Dollar 0x24 3297 3298 Qt.Key_Percent 0x25 3299 3300 Qt.Key_Ampersand 0x26 3301 3302 Qt.Key_Apostrophe 0x27 3303 3304 Qt.Key_ParenLeft 0x28 3305 3306 Qt.Key_ParenRight 0x29 3307 3308 Qt.Key_Asterisk 0x2a 3309 3310 Qt.Key_Plus 0x2b 3311 3312 Qt.Key_Comma 0x2c 3313 3314 Qt.Key_Minus 0x2d 3315 3316 Qt.Key_Period 0x2e 3317 3318 Qt.Key_Slash 0x2f 3319 3320 Qt.Key_0 0x30 3321 3322 Qt.Key_1 0x31 3323 3324 Qt.Key_2 0x32 3325 3326 Qt.Key_3 0x33 3327 3328 Qt.Key_4 0x34 3329 3330 Qt.Key_5 0x35 3331 3332 Qt.Key_6 0x36 3333 3334 Qt.Key_7 0x37 3335 3336 Qt.Key_8 0x38 3337 3338 Qt.Key_9 0x39 3339 3340 Qt.Key_Colon 0x3a 3341 3342 Qt.Key_Semicolon 0x3b 3343 3344 Qt.Key_Less 0x3c 3345 3346 Qt.Key_Equal 0x3d 3347 3348 Qt.Key_Greater 0x3e 3349 3350 Qt.Key_Question 0x3f 3351 3352 Qt.Key_At 0x40 3353 3354 Qt.Key_A 0x41 3355 3356 Qt.Key_B 0x42 3357 3358 Qt.Key_C 0x43 3359 3360 Qt.Key_D 0x44 3361 3362 Qt.Key_E 0x45 3363 3364 Qt.Key_F 0x46 3365 3366 Qt.Key_G 0x47 3367 3368 Qt.Key_H 0x48 3369 3370 Qt.Key_I 0x49 3371 3372 Qt.Key_J 0x4a 3373 3374 Qt.Key_K 0x4b 3375 3376 Qt.Key_L 0x4c 3377 3378 Qt.Key_M 0x4d 3379 3380 Qt.Key_N 0x4e 3381 3382 Qt.Key_O 0x4f 3383 3384 Qt.Key_P 0x50 3385 3386 Qt.Key_Q 0x51 3387 3388 Qt.Key_R 0x52 3389 3390 Qt.Key_S 0x53 3391 3392 Qt.Key_T 0x54 3393 3394 Qt.Key_U 0x55 3395 3396 Qt.Key_V 0x56 3397 3398 Qt.Key_W 0x57 3399 3400 Qt.Key_X 0x58 3401 3402 Qt.Key_Y 0x59 3403 3404 Qt.Key_Z 0x5a 3405 3406 Qt.Key_BracketLeft 0x5b 3407 3408 Qt.Key_Backslash 0x5c 3409 3410 Qt.Key_BracketRight 0x5d 3411 3412 Qt.Key_AsciiCircum 0x5e 3413 3414 Qt.Key_Underscore 0x5f 3415 3416 Qt.Key_QuoteLeft 0x60 3417 3418 Qt.Key_BraceLeft 0x7b 3419 3420 Qt.Key_Bar 0x7c 3421 3422 Qt.Key_BraceRight 0x7d 3423 3424 Qt.Key_AsciiTilde 0x7e 3425 3426 Qt.Key_nobreakspace 0x0a0 3427 3428 Qt.Key_exclamdown 0x0a1 3429 3430 Qt.Key_cent 0x0a2 3431 3432 Qt.Key_sterling 0x0a3 3433 3434 Qt.Key_currency 0x0a4 3435 3436 Qt.Key_yen 0x0a5 3437 3438 Qt.Key_brokenbar 0x0a6 3439 3440 Qt.Key_section 0x0a7 3441 3442 Qt.Key_diaeresis 0x0a8 3443 3444 Qt.Key_copyright 0x0a9 3445 3446 Qt.Key_ordfeminine 0x0aa 3447 3448 Qt.Key_guillemotleft 0x0ab 3449 3450 Qt.Key_notsign 0x0ac 3451 3452 Qt.Key_hyphen 0x0ad 3453 3454 Qt.Key_registered 0x0ae 3455 3456 Qt.Key_macron 0x0af 3457 3458 Qt.Key_degree 0x0b0 3459 3460 Qt.Key_plusminus 0x0b1 3461 3462 Qt.Key_twosuperior 0x0b2 3463 3464 Qt.Key_threesuperior 0x0b3 3465 3466 Qt.Key_acute 0x0b4 3467 3468 Qt.Key_mu 0x0b5 3469 3470 Qt.Key_paragraph 0x0b6 3471 3472 Qt.Key_periodcentered 0x0b7 3473 3474 Qt.Key_cedilla 0x0b8 3475 3476 Qt.Key_onesuperior 0x0b9 3477 3478 Qt.Key_masculine 0x0ba 3479 3480 Qt.Key_guillemotright 0x0bb 3481 3482 Qt.Key_onequarter 0x0bc 3483 3484 Qt.Key_onehalf 0x0bd 3485 3486 Qt.Key_threequarters 0x0be 3487 3488 Qt.Key_questiondown 0x0bf 3489 3490 Qt.Key_Agrave 0x0c0 3491 3492 Qt.Key_Aacute 0x0c1 3493 3494 Qt.Key_Acircumflex 0x0c2 3495 3496 Qt.Key_Atilde 0x0c3 3497 3498 Qt.Key_Adiaeresis 0x0c4 3499 3500 Qt.Key_Aring 0x0c5 3501 3502 Qt.Key_AE 0x0c6 3503 3504 Qt.Key_Ccedilla 0x0c7 3505 3506 Qt.Key_Egrave 0x0c8 3507 3508 Qt.Key_Eacute 0x0c9 3509 3510 Qt.Key_Ecircumflex 0x0ca 3511 3512 Qt.Key_Ediaeresis 0x0cb 3513 3514 Qt.Key_Igrave 0x0cc 3515 3516 Qt.Key_Iacute 0x0cd 3517 3518 Qt.Key_Icircumflex 0x0ce 3519 3520 Qt.Key_Idiaeresis 0x0cf 3521 3522 Qt.Key_ETH 0x0d0 3523 3524 Qt.Key_Ntilde 0x0d1 3525 3526 Qt.Key_Ograve 0x0d2 3527 3528 Qt.Key_Oacute 0x0d3 3529 3530 Qt.Key_Ocircumflex 0x0d4 3531 3532 Qt.Key_Otilde 0x0d5 3533 3534 Qt.Key_Odiaeresis 0x0d6 3535 3536 Qt.Key_multiply 0x0d7 3537 3538 Qt.Key_Ooblique 0x0d8 3539 3540 Qt.Key_Ugrave 0x0d9 3541 3542 Qt.Key_Uacute 0x0da 3543 3544 Qt.Key_Ucircumflex 0x0db 3545 3546 Qt.Key_Udiaeresis 0x0dc 3547 3548 Qt.Key_Yacute 0x0dd 3549 3550 Qt.Key_THORN 0x0de 3551 3552 Qt.Key_ssharp 0x0df 3553 3554 Qt.Key_division 0x0f7 3555 3556 Qt.Key_ydiaeresis 0x0ff 3557 3558 Qt.Key_Multi_key 0x01001120 3559 3560 Qt.Key_Codeinput 0x01001137 3561 3562 Qt.Key_SingleCandidate 0x0100113c 3563 3564 Qt.Key_MultipleCandidate 0x0100113d 3565 3566 Qt.Key_PreviousCandidate 0x0100113e 3567 3568 Qt.Key_Mode_switch 0x0100117e 3569 3570 Qt.Key_Kanji 0x01001121 3571 3572 Qt.Key_Muhenkan 0x01001122 3573 3574 Qt.Key_Henkan 0x01001123 3575 3576 Qt.Key_Romaji 0x01001124 3577 3578 Qt.Key_Hiragana 0x01001125 3579 3580 Qt.Key_Katakana 0x01001126 3581 3582 Qt.Key_Hiragana_Katakana 0x01001127 3583 3584 Qt.Key_Zenkaku 0x01001128 3585 3586 Qt.Key_Hankaku 0x01001129 3587 3588 Qt.Key_Zenkaku_Hankaku 0x0100112a 3589 3590 Qt.Key_Touroku 0x0100112b 3591 3592 Qt.Key_Massyo 0x0100112c 3593 3594 Qt.Key_Kana_Lock 0x0100112d 3595 3596 Qt.Key_Kana_Shift 0x0100112e 3597 3598 Qt.Key_Eisu_Shift 0x0100112f 3599 3600 Qt.Key_Eisu_toggle 0x01001130 3601 3602 Qt.Key_Hangul 0x01001131 3603 3604 Qt.Key_Hangul_Start 0x01001132 3605 3606 Qt.Key_Hangul_End 0x01001133 3607 3608 Qt.Key_Hangul_Hanja 0x01001134 3609 3610 Qt.Key_Hangul_Jamo 0x01001135 3611 3612 Qt.Key_Hangul_Romaja 0x01001136 3613 3614 Qt.Key_Hangul_Jeonja 0x01001138 3615 3616 Qt.Key_Hangul_Banja 0x01001139 3617 3618 Qt.Key_Hangul_PreHanja 0x0100113a 3619 3620 Qt.Key_Hangul_PostHanja 0x0100113b 3621 3622 Qt.Key_Hangul_Special 0x0100113f 3623 3624 Qt.Key_Dead_Grave 0x01001250 3625 3626 Qt.Key_Dead_Acute 0x01001251 3627 3628 Qt.Key_Dead_Circumflex 0x01001252 3629 3630 Qt.Key_Dead_Tilde 0x01001253 3631 3632 Qt.Key_Dead_Macron 0x01001254 3633 3634 Qt.Key_Dead_Breve 0x01001255 3635 3636 Qt.Key_Dead_Abovedot 0x01001256 3637 3638 Qt.Key_Dead_Diaeresis 0x01001257 3639 3640 Qt.Key_Dead_Abovering 0x01001258 3641 3642 Qt.Key_Dead_Doubleacute 0x01001259 3643 3644 Qt.Key_Dead_Caron 0x0100125a 3645 3646 Qt.Key_Dead_Cedilla 0x0100125b 3647 3648 Qt.Key_Dead_Ogonek 0x0100125c 3649 3650 Qt.Key_Dead_Iota 0x0100125d 3651 3652 Qt.Key_Dead_Voiced_Sound 0x0100125e 3653 3654 Qt.Key_Dead_Semivoiced_Sound 0x0100125f 3655 3656 Qt.Key_Dead_Belowdot 0x01001260 3657 3658 Qt.Key_Dead_Hook 0x01001261 3659 3660 Qt.Key_Dead_Horn 0x01001262 3661 3662 Qt.Key_Back 0x01000061 3663 3664 Qt.Key_Forward 0x01000062 3665 3666 Qt.Key_Stop 0x01000063 3667 3668 Qt.Key_Refresh 0x01000064 3669 3670 Qt.Key_VolumeDown 0x01000070 3671 3672 Qt.Key_VolumeMute 0x01000071 3673 3674 Qt.Key_VolumeUp 0x01000072 3675 3676 Qt.Key_BassBoost 0x01000073 3677 3678 Qt.Key_BassUp 0x01000074 3679 3680 Qt.Key_BassDown 0x01000075 3681 3682 Qt.Key_TrebleUp 0x01000076 3683 3684 Qt.Key_TrebleDown 0x01000077 3685 3686 Qt.Key_MediaPlay 0x01000080 A key setting the state of the media player to play 3687 3688 Qt.Key_MediaStop 0x01000081 A key setting the state of the media player to stop 3689 3690 Qt.Key_MediaPrevious 0x01000082 3691 3692 Qt.Key_MediaNext 0x01000083 3693 3694 Qt.Key_MediaRecord 0x01000084 3695 3696 Qt.Key_MediaPause 0x1000085 A key setting the state of the media player to pause (Note: not the pause/break key) 3697 3698 Qt.Key_MediaTogglePlayPause 0x1000086 A key to toggle the play/pause state in the media player (rather than setting an absolute state) 3699 3700 Qt.Key_HomePage 0x01000090 3701 3702 Qt.Key_Favorites 0x01000091 3703 3704 Qt.Key_Search 0x01000092 3705 3706 Qt.Key_Standby 0x01000093 3707 3708 Qt.Key_OpenUrl 0x01000094 3709 3710 Qt.Key_LaunchMail 0x010000a0 3711 3712 Qt.Key_LaunchMedia 0x010000a1 3713 3714 Qt.Key_Launch0 0x010000a2 On X11 this key is mapped to "My Computer" (XF86XK_MyComputer) key for legacy reasons. 3715 3716 Qt.Key_Launch1 0x010000a3 On X11 this key is mapped to "Calculator" (XF86XK_Calculator) key for legacy reasons. 3717 3718 Qt.Key_Launch2 0x010000a4 On X11 this key is mapped to XF86XK_Launch0 key for legacy reasons. 3719 3720 Qt.Key_Launch3 0x010000a5 On X11 this key is mapped to XF86XK_Launch1 key for legacy reasons. 3721 3722 Qt.Key_Launch4 0x010000a6 On X11 this key is mapped to XF86XK_Launch2 key for legacy reasons. 3723 3724 Qt.Key_Launch5 0x010000a7 On X11 this key is mapped to XF86XK_Launch3 key for legacy reasons. 3725 3726 Qt.Key_Launch6 0x010000a8 On X11 this key is mapped to XF86XK_Launch4 key for legacy reasons. 3727 3728 Qt.Key_Launch7 0x010000a9 On X11 this key is mapped to XF86XK_Launch5 key for legacy reasons. 3729 3730 Qt.Key_Launch8 0x010000aa On X11 this key is mapped to XF86XK_Launch6 key for legacy reasons. 3731 3732 Qt.Key_Launch9 0x010000ab On X11 this key is mapped to XF86XK_Launch7 key for legacy reasons. 3733 3734 Qt.Key_LaunchA 0x010000ac On X11 this key is mapped to XF86XK_Launch8 key for legacy reasons. 3735 3736 Qt.Key_LaunchB 0x010000ad On X11 this key is mapped to XF86XK_Launch9 key for legacy reasons. 3737 3738 Qt.Key_LaunchC 0x010000ae On X11 this key is mapped to XF86XK_LaunchA key for legacy reasons. 3739 3740 Qt.Key_LaunchD 0x010000af On X11 this key is mapped to XF86XK_LaunchB key for legacy reasons. 3741 3742 Qt.Key_LaunchE 0x010000b0 On X11 this key is mapped to XF86XK_LaunchC key for legacy reasons. 3743 3744 Qt.Key_LaunchF 0x010000b1 On X11 this key is mapped to XF86XK_LaunchD key for legacy reasons. 3745 3746 Qt.Key_LaunchG 0x0100010e On X11 this key is mapped to XF86XK_LaunchE key for legacy reasons. 3747 3748 Qt.Key_LaunchH 0x0100010f On X11 this key is mapped to XF86XK_LaunchF key for legacy reasons. 3749 3750 Qt.Key_MonBrightnessUp 0x010000b2 3751 3752 Qt.Key_MonBrightnessDown 0x010000b3 3753 3754 Qt.Key_KeyboardLightOnOff 0x010000b4 3755 3756 Qt.Key_KeyboardBrightnessUp 0x010000b5 3757 3758 Qt.Key_KeyboardBrightnessDown 0x010000b6 3759 3760 Qt.Key_PowerOff 0x010000b7 3761 3762 Qt.Key_WakeUp 0x010000b8 3763 3764 Qt.Key_Eject 0x010000b9 3765 3766 Qt.Key_ScreenSaver 0x010000ba 3767 3768 Qt.Key_WWW 0x010000bb 3769 3770 Qt.Key_Memo 0x010000bc 3771 3772 Qt.Key_LightBulb 0x010000bd 3773 3774 Qt.Key_Shop 0x010000be 3775 3776 Qt.Key_History 0x010000bf 3777 3778 Qt.Key_AddFavorite 0x010000c0 3779 3780 Qt.Key_HotLinks 0x010000c1 3781 3782 Qt.Key_BrightnessAdjust 0x010000c2 3783 3784 Qt.Key_Finance 0x010000c3 3785 3786 Qt.Key_Community 0x010000c4 3787 3788 Qt.Key_AudioRewind 0x010000c5 3789 3790 Qt.Key_BackForward 0x010000c6 3791 3792 Qt.Key_ApplicationLeft 0x010000c7 3793 3794 Qt.Key_ApplicationRight 0x010000c8 3795 3796 Qt.Key_Book 0x010000c9 3797 3798 Qt.Key_CD 0x010000ca 3799 3800 Qt.Key_Calculator 0x010000cb On X11 this key is not mapped for legacy reasons. Use Qt.Key_Launch1 instead. 3801 3802 Qt.Key_ToDoList 0x010000cc 3803 3804 Qt.Key_ClearGrab 0x010000cd 3805 3806 Qt.Key_Close 0x010000ce 3807 3808 Qt.Key_Copy 0x010000cf 3809 3810 Qt.Key_Cut 0x010000d0 3811 3812 Qt.Key_Display 0x010000d1 3813 3814 Qt.Key_DOS 0x010000d2 3815 3816 Qt.Key_Documents 0x010000d3 3817 3818 Qt.Key_Excel 0x010000d4 3819 3820 Qt.Key_Explorer 0x010000d5 3821 3822 Qt.Key_Game 0x010000d6 3823 3824 Qt.Key_Go 0x010000d7 3825 3826 Qt.Key_iTouch 0x010000d8 3827 3828 Qt.Key_LogOff 0x010000d9 3829 3830 Qt.Key_Market 0x010000da 3831 3832 Qt.Key_Meeting 0x010000db 3833 3834 Qt.Key_MenuKB 0x010000dc 3835 3836 Qt.Key_MenuPB 0x010000dd 3837 3838 Qt.Key_MySites 0x010000de 3839 3840 Qt.Key_News 0x010000df 3841 3842 Qt.Key_OfficeHome 0x010000e0 3843 3844 Qt.Key_Option 0x010000e1 3845 3846 Qt.Key_Paste 0x010000e2 3847 3848 Qt.Key_Phone 0x010000e3 3849 3850 Qt.Key_Calendar 0x010000e4 3851 3852 Qt.Key_Reply 0x010000e5 3853 3854 Qt.Key_Reload 0x010000e6 3855 3856 Qt.Key_RotateWindows 0x010000e7 3857 3858 Qt.Key_RotationPB 0x010000e8 3859 3860 Qt.Key_RotationKB 0x010000e9 3861 3862 Qt.Key_Save 0x010000ea 3863 3864 Qt.Key_Send 0x010000eb 3865 3866 Qt.Key_Spell 0x010000ec 3867 3868 Qt.Key_SplitScreen 0x010000ed 3869 3870 Qt.Key_Support 0x010000ee 3871 3872 Qt.Key_TaskPane 0x010000ef 3873 3874 Qt.Key_Terminal 0x010000f0 3875 3876 Qt.Key_Tools 0x010000f1 3877 3878 Qt.Key_Travel 0x010000f2 3879 3880 Qt.Key_Video 0x010000f3 3881 3882 Qt.Key_Word 0x010000f4 3883 3884 Qt.Key_Xfer 0x010000f5 3885 3886 Qt.Key_ZoomIn 0x010000f6 3887 3888 Qt.Key_ZoomOut 0x010000f7 3889 3890 Qt.Key_Away 0x010000f8 3891 3892 Qt.Key_Messenger 0x010000f9 3893 3894 Qt.Key_WebCam 0x010000fa 3895 3896 Qt.Key_MailForward 0x010000fb 3897 3898 Qt.Key_Pictures 0x010000fc 3899 3900 Qt.Key_Music 0x010000fd 3901 3902 Qt.Key_Battery 0x010000fe 3903 3904 Qt.Key_Bluetooth 0x010000ff 3905 3906 Qt.Key_WLAN 0x01000100 3907 3908 Qt.Key_UWB 0x01000101 3909 3910 Qt.Key_AudioForward 0x01000102 3911 3912 Qt.Key_AudioRepeat 0x01000103 3913 3914 Qt.Key_AudioRandomPlay 0x01000104 3915 3916 Qt.Key_Subtitle 0x01000105 3917 3918 Qt.Key_AudioCycleTrack 0x01000106 3919 3920 Qt.Key_Time 0x01000107 3921 3922 Qt.Key_Hibernate 0x01000108 3923 3924 Qt.Key_View 0x01000109 3925 3926 Qt.Key_TopMenu 0x0100010a 3927 3928 Qt.Key_PowerDown 0x0100010b 3929 3930 Qt.Key_Suspend 0x0100010c 3931 3932 Qt.Key_ContrastAdjust 0x0100010d 3933 3934 Qt.Key_MediaLast 0x0100ffff 3935 3936 Qt.Key_unknown 0x01ffffff 3937 3938 Qt.Key_Call 0x01100004 A key to answer or initiate a call (see Qt.Key_ToggleCallHangup for a key to toggle current call state) 3939 3940 Qt.Key_Camera 0x01100020 A key to activate the camera shutter 3941 3942 Qt.Key_CameraFocus 0x01100021 A key to focus the camera 3943 3944 Qt.Key_Context1 0x01100000 3945 3946 Qt.Key_Context2 0x01100001 3947 3948 Qt.Key_Context3 0x01100002 3949 3950 Qt.Key_Context4 0x01100003 3951 3952 Qt.Key_Flip 0x01100006 3953 3954 Qt.Key_Hangup 0x01100005 A key to end an ongoing call (see Qt.Key_ToggleCallHangup for a key to toggle current call state) 3955 3956 Qt.Key_No 0x01010002 3957 3958 Qt.Key_Select 0x01010000 3959 3960 Qt.Key_Yes 0x01010001 3961 3962 Qt.Key_ToggleCallHangup 0x01100007 A key to toggle the current call state (ie. either answer, or hangup) depending on current call state 3963 3964 Qt.Key_VoiceDial 0x01100008 3965 3966 Qt.Key_LastNumberRedial 0x01100009 3967 3968 Qt.Key_Execute 0x01020003 3969 3970 Qt.Key_Printer 0x01020002 3971 3972 Qt.Key_Play 0x01020005 3973 3974 Qt.Key_Sleep 0x01020004 3975 3976 Qt.Key_Zoom 0x01020006 3977 3978 Qt.Key_Cancel 0x01020001 3979 ''' 3980