11import sys
2+ import time
23from random import randint
34from PyQt5 .QtCore import QPoint , Qt , QThread , pyqtSignal
45from PyQt5 .QtGui import (QColor , QCursor , QIcon , QImage , QPainter ,
56 QPen , QPixmap )
67from PyQt5 .QtWidgets import (QAction , QApplication , QFileDialog ,
7- QMainWindow , QPushButton , QLabel )
8+ QMainWindow , QPushButton , )
89
910"""
1011Hover on QPaint detection
@@ -69,11 +70,11 @@ def setWindowCursor(cls, currentTool):
6970
7071 for obj in cls .objs :
7172 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+ )
7778
7879
7980class Tool :
@@ -121,13 +122,17 @@ def create_button(self):
121122 tool_btn .setShortcut (self .shortcut )
122123 tool_btn .setStatusTip (self .statusTip )
123124 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+ )
125129 )
126130 self .PaintBoard .toolbar .addAction (tool_btn )
127131
128132
129133class PalletteButton :
130134 """Class for color pallete; allows for mixing colors"""
135+
131136 def __init__ (self , parentBtn ):
132137 self .parentBtn = parentBtn
133138 self .r = randint (0 , 255 )
@@ -160,7 +165,7 @@ def mixColor(self, tool):
160165 ]
161166 )
162167
163- if colorSum and tool .color .alpha () and self .alpha :
168+ if colorSum and tool .color .alpha () and self .alpha :
164169 # self.alpha so that color pallette is not empty
165170 self .r = (self .r + tool .color .red ()) // 2
166171 self .g = (self .g + tool .color .green ()) // 2
@@ -180,7 +185,6 @@ def mixColor(self, tool):
180185 tool .isDipped = True
181186 elif tool .toolName == "A bucket" and self .alpha :
182187 """The pallette gets emptied """
183- print ('bucket selected' )
184188 self .r = 0
185189 self .g = 0
186190 self .b = 0
@@ -193,7 +197,9 @@ def mixColor(self, tool):
193197
194198 self .parentBtn .setStyleSheet (
195199 "background-color: rgba{0}; border-radius:20px" .format (
196- self .palletteColor ))
200+ self .palletteColor
201+ )
202+ )
197203
198204
199205class PaintBoard (QMainWindow ):
@@ -212,6 +218,8 @@ def Setup(self):
212218 self .connectTool ()
213219 self .painter = QPainter (self .canvas )
214220
221+ self .mousePos = QPoint (0 , 0 )
222+
215223 # MENUBARS
216224 mainMenu = self .menuBar ()
217225
@@ -286,7 +294,8 @@ def Setup(self):
286294 )
287295
288296 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" ,
290299 "Ctrl+F" ,
291300 "Erase Your Mistakes, Kid!" ,
292301 (99999 , 99999 )) # infinte duration
@@ -308,8 +317,10 @@ def connectTool(self, curTool=None, curisDipped=False):
308317 else :
309318 self .currentTool .isDipped = curisDipped
310319 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+ )
313324 ColorBox .setWindowCursor (self .currentTool )
314325
315326 self .setCursor (QCursor (
@@ -319,10 +330,17 @@ def connectTool(self, curTool=None, curisDipped=False):
319330 )
320331 )))
321332 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" \
323338 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 )
326344 self .dripper .start ()
327345
328346 def colorBoxRun (self ):
@@ -333,119 +351,38 @@ def colorBoxRun(self):
333351 geo .moveLeft (geo .right ()) # moves window right
334352 self .colorBox .setGeometry (geo )
335353
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 )
432368
433369 # showing toolBox
434370 self .colorBox .showColorBox ()
435371
436- def DripperHandler (self , result ):
372+ def dripperHandler (self , result ):
437373 Dripper = result
438- print ('drip' )
439374 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 ()
441379
442380 def mousePressEvent (self , event ):
443381 if event .button () == Qt .LeftButton and \
444382 self .currentTool is not None :
445383 self .drawing = True
446384 if self .currentTool .toolName == "A bucket filled" \
447385 and self .currentTool .duration >= 0 :
448- print (self .currentTool .toolName )
449386 Pen = QPen ()
450387 Pen .setColor (self .currentTool .color )
451388 Pen .setWidth (self .currentTool .brushSize )
@@ -455,14 +392,14 @@ def mousePressEvent(self, event):
455392 self .currentTool .toolName = "A bucket"
456393 self .currentTool .color = QColor (0 , 0 , 0 , 0 )
457394 self .connectTool (self .currentTool )
458- print ('used bucket' )
459395
460396 self .lastPoint = event .pos ()
461397 self .update ()
462398 else :
463399 return None
464400
465401 def mouseMoveEvent (self , event ):
402+ self .mousePos = event .pos ()
466403 if (event .buttons () and Qt .LeftButton ) and \
467404 self .drawing and self .currentTool is not None :
468405
@@ -471,31 +408,47 @@ def mouseMoveEvent(self, event):
471408 if self .currentTool .duration <= 0.0 :
472409 Pen .setDashPattern ([0 , 0 , 0 , 0 ])
473410 self .drawing = False
411+ self .dripper .stop ()
474412 else :
475413 self .currentTool .duration -= 0.1
476414 if "Brush" in self .currentTool .toolName :
477415 self .currentTool .opacityDuration -= 0.0125
478- # TODO EXTRA: find more fitting duration time
479416 # perhaps divide in class object
480417
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 )))
493445
494446 if self .currentTool .toolName == "Pointy Pen" :
495447 # QSound(SoundEffects['pen write']).play()
496448 Pen .setCapStyle (Qt .RoundCap )
497449 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' :
499452 if self .currentTool .toolName == "Solid Brush" :
500453 Pen .setCapStyle (Qt .RoundCap )
501454 Pen .setJoinStyle (Qt .BevelJoin )
@@ -575,25 +528,34 @@ class DripperEffect(QThread):
575528 def __init__ (self , color , size ):
576529 QThread .__init__ (self )
577530 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
579537
580538 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 )
592554
593555
594556if __name__ == '__main__' :
595557 app = QApplication (sys .argv )
596558 app .setStyleSheet ("QMainWindow{background-color:white}" )
597559 myGUI = PaintBoard ()
598560
599- sys .exit (app .exec_ ())
561+ sys .exit (app .exec_ ())
0 commit comments