1
1
import sys
2
+ import time
2
3
from random import randint
3
4
from PyQt5 .QtCore import QPoint , Qt , QThread , pyqtSignal
4
5
from PyQt5 .QtGui import (QColor , QCursor , QIcon , QImage , QPainter ,
5
6
QPen , QPixmap )
6
7
from PyQt5 .QtWidgets import (QAction , QApplication , QFileDialog ,
7
- QMainWindow , QPushButton , QLabel )
8
+ QMainWindow , QPushButton , )
8
9
9
10
"""
10
11
Hover on QPaint detection
@@ -69,11 +70,11 @@ def setWindowCursor(cls, currentTool):
69
70
70
71
for obj in cls .objs :
71
72
obj .setCursor (QCursor (QPixmap ("Design/icons/{}.png" .format (
72
- currentTool .toolName
73
- if currentTool else None )
74
- )
75
- )
76
- )
73
+ currentTool .toolName
74
+ if currentTool else None )
75
+ )
76
+ )
77
+ )
77
78
78
79
79
80
class Tool :
@@ -121,13 +122,17 @@ def create_button(self):
121
122
tool_btn .setShortcut (self .shortcut )
122
123
tool_btn .setStatusTip (self .statusTip )
123
124
tool_btn .triggered .connect (
124
- lambda : self .PaintBoard .connectTool (self , curisDipped = self .isDipped )
125
+ lambda : self .PaintBoard .connectTool (
126
+ self ,
127
+ curisDipped = self .isDipped
128
+ )
125
129
)
126
130
self .PaintBoard .toolbar .addAction (tool_btn )
127
131
128
132
129
133
class PalletteButton :
130
134
"""Class for color pallete; allows for mixing colors"""
135
+
131
136
def __init__ (self , parentBtn ):
132
137
self .parentBtn = parentBtn
133
138
self .r = randint (0 , 255 )
@@ -160,7 +165,7 @@ def mixColor(self, tool):
160
165
]
161
166
)
162
167
163
- if colorSum and tool .color .alpha () and self .alpha :
168
+ if colorSum and tool .color .alpha () and self .alpha :
164
169
# self.alpha so that color pallette is not empty
165
170
self .r = (self .r + tool .color .red ()) // 2
166
171
self .g = (self .g + tool .color .green ()) // 2
@@ -180,7 +185,6 @@ def mixColor(self, tool):
180
185
tool .isDipped = True
181
186
elif tool .toolName == "A bucket" and self .alpha :
182
187
"""The pallette gets emptied """
183
- print ('bucket selected' )
184
188
self .r = 0
185
189
self .g = 0
186
190
self .b = 0
@@ -193,7 +197,9 @@ def mixColor(self, tool):
193
197
194
198
self .parentBtn .setStyleSheet (
195
199
"background-color: rgba{0}; border-radius:20px" .format (
196
- self .palletteColor ))
200
+ self .palletteColor
201
+ )
202
+ )
197
203
198
204
199
205
class PaintBoard (QMainWindow ):
@@ -212,6 +218,8 @@ def Setup(self):
212
218
self .connectTool ()
213
219
self .painter = QPainter (self .canvas )
214
220
221
+ self .mousePos = QPoint (0 , 0 )
222
+
215
223
# MENUBARS
216
224
mainMenu = self .menuBar ()
217
225
@@ -286,7 +294,8 @@ def Setup(self):
286
294
)
287
295
288
296
self .sunbathing_eraser = Tool ("Sunbathing Eraser" , 10 , Qt .white ,
289
- [0 , 0 , 0 , 0.0 ], self , "Design/icons/Sunbathing Eraser" ,
297
+ [0 , 0 , 0 , 0.0 ], self ,
298
+ "Design/icons/Sunbathing Eraser" ,
290
299
"Ctrl+F" ,
291
300
"Erase Your Mistakes, Kid!" ,
292
301
(99999 , 99999 )) # infinte duration
@@ -308,8 +317,10 @@ def connectTool(self, curTool=None, curisDipped=False):
308
317
else :
309
318
self .currentTool .isDipped = curisDipped
310
319
if self .currentTool .toolName == "Pointy Pen" :
311
- self .currentTool .duration = randint (0 ,
312
- self .currentTool .constDuration )
320
+ self .currentTool .duration = randint (
321
+ 0 ,
322
+ self .currentTool .constDuration
323
+ )
313
324
ColorBox .setWindowCursor (self .currentTool )
314
325
315
326
self .setCursor (QCursor (
@@ -319,10 +330,17 @@ def connectTool(self, curTool=None, curisDipped=False):
319
330
)
320
331
)))
321
332
if self .currentTool is not None :
322
- if self .currentTool .toolName != "Pointy Pen" or "A bucket" or "Sunbathing Eraser" \
333
+ if self .currentTool .toolName != \
334
+ "Pointy Pen" or \
335
+ "A bucket" or \
336
+ "Sunbathing Eraser" or \
337
+ "A bucket filled" \
323
338
and self .currentTool .isDipped :
324
- self .dripper = DripperEffect (self .currentTool .color , self .currentTool .brushSize )
325
- self .dripper .drip .connect (self .DripperHandler )
339
+ self .dripper = DripperEffect (
340
+ self .currentTool .color ,
341
+ self .currentTool .brushSize
342
+ )
343
+ self .dripper .drip .connect (self .dripperHandler )
326
344
self .dripper .start ()
327
345
328
346
def colorBoxRun (self ):
@@ -333,119 +351,38 @@ def colorBoxRun(self):
333
351
geo .moveLeft (geo .right ()) # moves window right
334
352
self .colorBox .setGeometry (geo )
335
353
336
- p1 , p2 , p3 , p4 , p5 ,\
337
- p6 , p7 , p8 , p9 , p10 ,\
338
- p11 , p12 , p13 , p14 ,\
339
- p15 , p16 , p17 , p18 = (QPushButton () for _ in range (18 ))
340
-
341
- c1 = PalletteButton (p1 )
342
- c2 = PalletteButton (p2 )
343
- c3 = PalletteButton (p3 )
344
- c4 = PalletteButton (p4 )
345
- c5 = PalletteButton (p5 )
346
- c6 = PalletteButton (p6 )
347
- c7 = PalletteButton (p7 )
348
- c8 = PalletteButton (p8 )
349
- c9 = PalletteButton (p9 )
350
- c10 = PalletteButton (p10 )
351
- c11 = PalletteButton (p11 )
352
- c12 = PalletteButton (p12 )
353
- c13 = PalletteButton (p13 )
354
- c14 = PalletteButton (p14 )
355
- c15 = PalletteButton (p15 )
356
- c16 = PalletteButton (p16 )
357
- c17 = PalletteButton (p17 )
358
- c18 = PalletteButton (p18 )
359
-
360
- p1 .setStyleSheet ("background-color: rgba{0}; border-radius:20px"
361
- .format (c1 .palletteColor ))
362
- p1 .clicked .connect (lambda : c1 .mixColor (self .currentTool ))
363
- self .colorBox .addPallette (p1 )
364
- p2 .setStyleSheet ("background-color: rgba{0}; border-radius:20px"
365
- .format (c2 .palletteColor ))
366
- p2 .clicked .connect (lambda : c2 .mixColor (self .currentTool ))
367
- self .colorBox .addPallette (p2 )
368
- p3 .setStyleSheet ("background-color: rgba{0}; border-radius:20px"
369
- .format (c3 .palletteColor ))
370
- p3 .clicked .connect (lambda : c3 .mixColor (self .currentTool ))
371
- self .colorBox .addPallette (p3 )
372
- p4 .setStyleSheet ("background-color: rgba{0}; border-radius:20px;"
373
- .format (c4 .palletteColor ))
374
- p4 .clicked .connect (lambda : c4 .mixColor (self .currentTool ))
375
- self .colorBox .addPallette (p4 )
376
- p5 .setStyleSheet ("background-color: rgba{0}; border-radius:20px"
377
- .format (c5 .palletteColor ))
378
- p5 .clicked .connect (lambda : c5 .mixColor (self .currentTool ))
379
- self .colorBox .addPallette (p5 )
380
- p6 .setStyleSheet ("background-color: rgba{0}; border-radius:20px"
381
- .format (c6 .palletteColor ))
382
- p6 .clicked .connect (lambda : c6 .mixColor (self .currentTool ))
383
- self .colorBox .addPallette (p6 )
384
- p7 .setStyleSheet ("background-color: rgba{0}; border-radius:20px"
385
- .format (c7 .palletteColor ))
386
- p7 .clicked .connect (lambda : c7 .mixColor (self .currentTool ))
387
- self .colorBox .addPallette (p7 )
388
- p8 .setStyleSheet ("background-color: rgba{0}; border-radius:20px"
389
- .format (c8 .palletteColor ))
390
- p8 .clicked .connect (lambda : c8 .mixColor (self .currentTool ))
391
- self .colorBox .addPallette (p8 )
392
- p9 .setStyleSheet ("background-color: rgba{0}; border-radius:20px"
393
- .format (c9 .palletteColor ))
394
- p9 .clicked .connect (lambda : c9 .mixColor (self .currentTool ))
395
- self .colorBox .addPallette (p9 )
396
- p10 .setStyleSheet ("background-color: rgba{0}; border-radius:20px"
397
- .format (c10 .palletteColor ))
398
- p10 .clicked .connect (lambda : c10 .mixColor (self .currentTool ))
399
- self .colorBox .addPallette (p10 )
400
- p11 .setStyleSheet ("background-color: rgba{0}; border-radius:20px"
401
- .format (c11 .palletteColor ))
402
- p11 .clicked .connect (lambda : c11 .mixColor (self .currentTool ))
403
- self .colorBox .addPallette (p11 )
404
- p12 .setStyleSheet ("background-color: rgba{0}; border-radius:20px"
405
- .format (c12 .palletteColor ))
406
- p12 .clicked .connect (lambda : c12 .mixColor (self .currentTool ))
407
- self .colorBox .addPallette (p12 )
408
- p13 .setStyleSheet ("background-color: rgba{0}; border-radius:20px"
409
- .format (c13 .palletteColor ))
410
- p13 .clicked .connect (lambda : c13 .mixColor (self .currentTool ))
411
- self .colorBox .addPallette (p13 )
412
- p14 .setStyleSheet ("background-color: rgba{0}; border-radius:20px"
413
- .format (c14 .palletteColor ))
414
- p14 .clicked .connect (lambda : c14 .mixColor (self .currentTool ))
415
- self .colorBox .addPallette (p14 )
416
- p15 .setStyleSheet ("background-color: rgba{0}; border-radius:20px"
417
- .format (c15 .palletteColor ))
418
- p15 .clicked .connect (lambda : c15 .mixColor (self .currentTool ))
419
- self .colorBox .addPallette (p15 )
420
- p16 .setStyleSheet ("background-color: rgba{0}; border-radius:20px"
421
- .format (c16 .palletteColor ))
422
- p16 .clicked .connect (lambda : c16 .mixColor (self .currentTool ))
423
- self .colorBox .addPallette (p16 )
424
- p17 .setStyleSheet ("background-color: rgba{0}; border-radius:20px"
425
- .format (c17 .palletteColor ))
426
- p17 .clicked .connect (lambda : c17 .mixColor (self .currentTool ))
427
- self .colorBox .addPallette (p17 )
428
- p18 .setStyleSheet ("background-color: rgba{0}; border-radius:20px"
429
- .format (c18 .palletteColor ))
430
- p18 .clicked .connect (lambda : c18 .mixColor (self .currentTool ))
431
- self .colorBox .addPallette (p18 )
354
+ number_of_buttons = 18
355
+ PalletteButtons = {PalletteButton (button ): button for button in [
356
+ QPushButton () for _ in range (number_of_buttons )
357
+ ]
358
+ }
359
+
360
+ style_sheet_str = "background-color: rgba{0}; border-radius:20px"
361
+
362
+ for button_index in range (number_of_buttons ):
363
+ c = list (PalletteButtons .keys ())[button_index ]
364
+ p = PalletteButtons [list (PalletteButtons .keys ())[button_index ]]
365
+ p .setStyleSheet (style_sheet_str .format (c .palletteColor ))
366
+ p .clicked .connect (lambda : c .mixColor (self .currentTool ))
367
+ self .colorBox .addPallette (p )
432
368
433
369
# showing toolBox
434
370
self .colorBox .showColorBox ()
435
371
436
- def DripperHandler (self , result ):
372
+ def dripperHandler (self , result ):
437
373
Dripper = result
438
- print ('drip' )
439
374
self .painter .setPen (Dripper )
440
- self .painter .drawLine (self .lastPoint , self .lastPoint )
375
+ point = QPoint (self .cursor ().pos ().x (), self .cursor ().pos ().y ())
376
+ point = self .mapFromGlobal (point )
377
+ self .painter .drawLine (point , point )
378
+ self .update ()
441
379
442
380
def mousePressEvent (self , event ):
443
381
if event .button () == Qt .LeftButton and \
444
382
self .currentTool is not None :
445
383
self .drawing = True
446
384
if self .currentTool .toolName == "A bucket filled" \
447
385
and self .currentTool .duration >= 0 :
448
- print (self .currentTool .toolName )
449
386
Pen = QPen ()
450
387
Pen .setColor (self .currentTool .color )
451
388
Pen .setWidth (self .currentTool .brushSize )
@@ -455,14 +392,14 @@ def mousePressEvent(self, event):
455
392
self .currentTool .toolName = "A bucket"
456
393
self .currentTool .color = QColor (0 , 0 , 0 , 0 )
457
394
self .connectTool (self .currentTool )
458
- print ('used bucket' )
459
395
460
396
self .lastPoint = event .pos ()
461
397
self .update ()
462
398
else :
463
399
return None
464
400
465
401
def mouseMoveEvent (self , event ):
402
+ self .mousePos = event .pos ()
466
403
if (event .buttons () and Qt .LeftButton ) and \
467
404
self .drawing and self .currentTool is not None :
468
405
@@ -471,31 +408,47 @@ def mouseMoveEvent(self, event):
471
408
if self .currentTool .duration <= 0.0 :
472
409
Pen .setDashPattern ([0 , 0 , 0 , 0 ])
473
410
self .drawing = False
411
+ self .dripper .stop ()
474
412
else :
475
413
self .currentTool .duration -= 0.1
476
414
if "Brush" in self .currentTool .toolName :
477
415
self .currentTool .opacityDuration -= 0.0125
478
- # TODO EXTRA: find more fitting duration time
479
416
# perhaps divide in class object
480
417
481
- # this here is to add more realism to the point when its breaking
482
- if self .currentTool .duration <= 0.5 and self .currentTool .toolName == "Pointy Pen" :
483
- broken_pen = QPen ()
484
- broken_pen .setCapStyle (Qt .RoundCap )
485
- broken_pen .setJoinStyle (Qt .MiterJoin )
486
- broken_pen .setWidth (1 )
487
- broken_pen .setColor (self .currentTool .color )
488
- broken_pen .setDashPattern ([25 , 50 , 25 , 50 ])
489
- broken_pen .setStyle (Qt .DashDotDotLine )
490
- self .painter .setPen (broken_pen )
491
- self .painter .drawLine (self .lastPoint + QPoint (randint (10 , 15 ), randint (1 , 5 )),
492
- self .lastPoint + QPoint (randint (5 , 10 ), randint (1 , 10 )))
418
+ # this here is to add more realism
419
+ # to the point when its breaking
420
+ if self .currentTool .duration <= 0.2 :
421
+ dots = QPen ()
422
+ broken_tools = QPen ()
423
+ if self .currentTool .toolName == "Pointy Pen" :
424
+ dots .setColor (Qt .black )
425
+ dots .setWidth (1 )
426
+ if self .currentTool .toolName == "Solid Brush" :
427
+ broken_tools .setColor (self .currentTool .color )
428
+ broken_tools .setCapStyle (Qt .SquareCap )
429
+ broken_tools .setJoinStyle (Qt .BevelJoin )
430
+ broken_tools .setWidth (self .currentTool .brushSize - 2 )
431
+ self .painter .setPen (broken_tools )
432
+ self .painter .drawLine (self .lastPoint , self .lastPoint )
433
+ dots .setCapStyle (Qt .RoundCap )
434
+ dots .setJoinStyle (Qt .RoundJoin )
435
+ dots .setColor (self .currentTool .color )
436
+ dots .setDashPattern ([25 , 50 , 25 , 50 ])
437
+ dots .setStyle (Qt .DashDotDotLine )
438
+ self .painter .setPen (dots )
439
+ self .painter .drawLine (self .lastPoint +
440
+ QPoint (randint (10 , 15 ),
441
+ randint (1 , 5 )),
442
+ self .lastPoint +
443
+ QPoint (randint (5 , 10 ),
444
+ randint (1 , 10 )))
493
445
494
446
if self .currentTool .toolName == "Pointy Pen" :
495
447
# QSound(SoundEffects['pen write']).play()
496
448
Pen .setCapStyle (Qt .RoundCap )
497
449
Pen .setJoinStyle (Qt .MiterJoin )
498
- elif self .currentTool .toolName == 'Straggly Paintbrush' or 'Solid Brush' :
450
+ elif self .currentTool .toolName == \
451
+ 'Straggly Paintbrush' or 'Solid Brush' :
499
452
if self .currentTool .toolName == "Solid Brush" :
500
453
Pen .setCapStyle (Qt .RoundCap )
501
454
Pen .setJoinStyle (Qt .BevelJoin )
@@ -575,25 +528,34 @@ class DripperEffect(QThread):
575
528
def __init__ (self , color , size ):
576
529
QThread .__init__ (self )
577
530
self .color = color
578
- self .size = size
531
+ self .size = size * 2
532
+ print ('size: ' + str (self .size ))
533
+ self ._stop = False
534
+
535
+ def stop (self ):
536
+ self ._stop = True
579
537
580
538
def run (self ):
581
- drip_chance = randint (0 , 1 )
582
- if drip_chance == 1 :
583
- Drip = QPen ()
584
- Drip .setWidth (self .size )
585
- Drip .setStyle (Qt .DotLine )
586
- Drip .setColor (self .color )
587
- Drip .setJoinStyle (Qt .RoundJoin )
588
- Drip .setCapStyle (Qt .RoundCap )
589
- self .drip .emit (Drip )
590
- else :
591
- pass
539
+ while not self ._stop :
540
+ drip_chance = randint (0 , 5 )
541
+ # 1/3 chance it drips
542
+ if drip_chance < 2 :
543
+ Drip = QPen ()
544
+ Drip .setWidth (self .size )
545
+ Drip .setStyle (Qt .DotLine )
546
+ Drip .setColor (self .color )
547
+ Drip .setJoinStyle (Qt .RoundJoin )
548
+ Drip .setCapStyle (Qt .RoundCap )
549
+ self .drip .emit (Drip )
550
+ print ('drip' )
551
+ else :
552
+ pass
553
+ time .sleep (0.5 )
592
554
593
555
594
556
if __name__ == '__main__' :
595
557
app = QApplication (sys .argv )
596
558
app .setStyleSheet ("QMainWindow{background-color:white}" )
597
559
myGUI = PaintBoard ()
598
560
599
- sys .exit (app .exec_ ())
561
+ sys .exit (app .exec_ ())
0 commit comments