# Coin flip simulator with GUI

from random import randint
from time import sleep
from sys import (exit, argv)
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import (QToolTip, QPushButton, QApplication, QWidget, QLabel)
from PyQt5.QtGui import (QIcon, QPixmap, QFont)

#Creates the main widget which will contain everything else
class coinflipsimulator(QWidget):

def __init__(self):
super().__init__()

self.initUI()

def initUI(self):
#Creates the QLabel 'coin' which will contain the image of the coin
self.coin = QLabel(self)
#Uses QPixmap to place a random coin image (head or tail) into the QLabel 'coin'
self.coin.setPixmap(QPixmap('coin_' + str(randint(1, 2)) + '.png').scaled(162, 302, Qt.KeepAspectRatio, Qt.FastTransformation))
self.coin.move(0.5, 0.5)

#Creates the button that will activate the simulated coin flip when clicked and labels it 'Flip' using QPushButton
self.btn = QPushButton('Flip', self)
#Selects the font/font size for the label on the QPushButton 'btn' using QFont
self.btn.setFont(QFont('SansSerif', 20))
#Creates a tooltip when user hovers over the QPushButton 'btn' using QToolTip
self.btn.setToolTip('Click to Flip Coin')
#Selects the font/font size for the QToolTip above on the QPushButton 'btn' using QFont
QToolTip.setFont(QFont('SansSerif', 10))
#Connects the QPushButton 'btn' to the function 'flipcoin' to activate when the button is clicked
self.btn.clicked.connect(self.flipcoin)
self.btn.resize(166, 43)
self.btn.move(-2, 161)

#Sets where on the screen the window will open and the size of the window respectively using x and y coordinates
self.setGeometry(1427, 30, 162, 201)
#Locks the size of the window and make it impossible for the user to change it
self.setFixedSize(self.size())
self.setWindowTitle('Coin Flip Simulator')
#Sets the window icon to the image file 'icon.png' located in the same folder as the source file
self.setWindowIcon(QIcon('icon.png'))
self.show()

def flipcoin(self):
#Sets the image inside the Qlabel 'coin' to a coin flipping animation...aspect ratio is ignored to get the animation to fit inside the window correctly
self.coin.setPixmap(QPixmap('coin_flipping_animation.png').scaled(162, 302, Qt.KeepAspectRatio, Qt.FastTransformation))
#Processes any change made to the program/window in this case the change of the image in the Qlabel 'coin'
QApplication.processEvents()
#Pauses the execution of any more code for 0.5 seconds
sleep(0.5)
#Sets the image inside the QLabel 'coin' to a random coin image (head or tail) into the QLabel 'coin'
self.coin.setPixmap(QPixmap('coin_' + str(randint(1, 2)) + '.png').scaled(162, 302, Qt.KeepAspectRatio, Qt.FastTransformation))
#Processes the second change to the QLabel 'dice'
QApplication.processEvents()

if __name__ == '__main__':

#Begins the execution of the QApplication

app = QApplication(argv)
ex = coinflipsimulator()
ex.show()
exit(app.exec_())


This is the first GUI I have completed since I started learning to code. It is a simple program which simulates a die roll when the user clicks a button. I am quite proud of myself even though I know it's nothing great still I am always open to advice and suggestions.

Nice program, so only some tips:

First of all, you comments are very useful for you as a beginner but without them your code is much nicer:

class coinflipsimulator(QWidget):

def __init__(self):
super().__init__()

self.initUI()

def initUI(self):
self.coin = QLabel(self)
self.coin.setPixmap(QPixmap('coin_' + str(randint(1, 2)) + '.png').scaled(162, 302, Qt.KeepAspectRatio, Qt.FastTransformation))
self.coin.move(0.5, 0.5)

self.btn = QPushButton('Flip', self)
self.btn.setFont(QFont('SansSerif', 20))
self.btn.setToolTip('Click to Flip Coin')
QToolTip.setFont(QFont('SansSerif', 10))
self.btn.clicked.connect(self.flipcoin)
self.btn.resize(166, 43)
self.btn.move(-2, 161)

self.setGeometry(1427, 30, 162, 201)
self.setFixedSize(self.size())
self.setWindowTitle('Coin Flip Simulator')
self.setWindowIcon(QIcon('icon.png'))
self.show()

def flipcoin(self):
self.coin.setPixmap(QPixmap('coin_flipping_animation.png').scaled(162, 302, Qt.KeepAspectRatio, Qt.FastTransformation))
QApplication.processEvents()
sleep(0.5)
self.coin.setPixmap(QPixmap('coin_' + str(randint(1, 2)) + '.png').scaled(162, 302, Qt.KeepAspectRatio, Qt.FastTransformation))
QApplication.processEvents()

if __name__ == '__main__':

app = QApplication(argv)
ex = coinflipsimulator()
ex.show()
exit(app.exec_())


Follow the DRY principle (Don't Repeat Yourself). In your code is 2 times the same statement

self.coin.setPixmap(QPixmap('coin_' + str(randint(1, 2)) + '.png').scaled(162, 302, Qt.KeepAspectRatio, Qt.FastTransformation))


In them you repeatedly construct one of two picture names:

coin_1.png
coin_2.png


Why not create a list or a tuple of them, e. g.

COINS = ('coin1.png', 'coin_2.png')


(note the use of uppercase letters for its name as a signal that it will not change) and instead of the

randint(1, 2)


use

choice(COINS)


Or - even better - create the list or tuple of 2 QPixmap objects and apply the choice() function on it?

Hard-coded file names (as the 2 mentioned above) are spread in your code so it will be more difficult to search for them in the case for the need of change them.

What about give all of them (together with other constants) appropriate names near the start of your, e. g.

ICON = 'icon.png'
SLEEP_TIME = .5


and then use those names?

You may even create constants for parameter lists of functions / methods - as you use the same again and again - and then use them, e. g.

SCALED_PARMS = 162, 302, Qt.KeepAspectRatio, Qt.FastTransformation


and then use them in the form

.scaled(*SCALED_PARMS)     # This is only the part of your command


(note the asterisk (*) in front of them for unpacking the ones).

• Thank you very much. I'll try what you've recommended. : ) – DaveyH-cks Aug 8 '17 at 10:23