Python >> Tutoriel Python >  >> Python GUI >> Pygame GUI

Calculatrice de base Pygame

Vous pouvez ajouter un = bouton, donc chaque fois que l'utilisateur clique dessus, calcule l'entrée utilisateur avec python eval() fonction.

Quant à l'entrée utilisateur, vous devez d'abord l'enregistrer globalement . Ensuite, vous pouvez transmettre l'entrée de l'utilisateur au champ de chaîne de inputtap = button((253,100,32),10,280,450,50,"") pour l'afficher sur la fenêtre.

import pygame, math

pygame.init()

window_height = 500
window_width = 600
window  = pygame.display.set_mode((window_height,window_width))

# the buttons for the shop MENU
class button():
    def __init__(self, color, x,y,width,height, text=''):
        self.color = color
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.text = text
        self.over = False

    def draw(self,window,outline=None):
        #Call this method to draw the button on the screen
        if outline:
            pygame.draw.rect(window, outline, (self.x-2,self.y-2,self.width+4,self.height+4),0)
                    
        pygame.draw.rect(window, self.color, (self.x,self.y,self.width,self.height),0)
                
        if self.text != '':
            font = pygame.font.SysFont('comicsans', 60)
            text = font.render(self.text, 1, (0,0,0))
            window.blit(text, (self.x + (self.width/2 - text.get_width()/2), self.y + (self.height/2 - text.get_height()/2)))

    def isOver(self, pos):
        #Pos is the mouse position or a tuple of (x,y) coordinates
        if pos[0] > self.x and pos[0] < self.x + self.width:
            if pos[1] > self.y and pos[1] < self.y + self.height:
                return True
        return False

    def playSoundIfMouseIsOver(self, pos, sound):
        if self.isOver(pos):            
            if not self.over:
                beepsound.play()
                self.over = True
        else:
            self.over = False
                    
white = (255,255,255)
# the numbers for the calcaltor
s_1s = button((0,255,0),40,450,30,30, '1')
s_2s = button((0,255,0),40,400,30,30, '2')
s_3s = button((0,255,0),40,350,30,30, '3')
s_4s = button((0,255,0),100,450,30,30, '4')
s_5s = button((0,255,0),100,400,30,30, '5')
s_6s = button((0,255,0),100,350,30,30, '6')
s_7s = button((0,255,0),150,450,30,30, '7')
s_8s = button((0,255,0),150,400,30,30, '8')
s_9s = button((0,255,0),150,350,30,30, '9')
s_0s = button((0,255,0),200,450,30,30, '0')

numbers = [s_1s,s_2s,s_3s,s_4s,s_5s,s_6s,s_7s,s_8s,s_9s,s_0s]

# the symbols!
d_1s = button((0,255,0),260,450,30,30, '+')
d_2s = button((0,255,0),260,400,30,30, '-')
d_3s = button((0,255,0),260,350,30,30, 'x')
d_4s = button((0,255,0),200,400,30,30, '÷')
d_5s = button((0,255,0),200,350,30,30, '=')
d_6s = button((0,255,0),260,500,30,30, 'C')

symbols = [d_1s,d_2s,d_3s,d_4s,d_5s,d_6s]


# redraw window
def redraw(inputtap):
    # draw all the numbers
    for button in numbers:
        button.draw(window)

    # the symbols
    for button in symbols:
        button.draw(window)

    inputtap.draw(window)

def Symbols():
    global user_input
    global python_input
    global is_finished

    if event.type == pygame.MOUSEBUTTONDOWN:
        pos = pygame.mouse.get_pos()

        try:
            if is_finished or user_input[-1] in ["+", "-", "x", "÷", "="]:
                # User shouldn't type two symbols continuously
                # User shouldn't input any symbols when game finished because there is no number
                return
        except IndexError:
            # User shouldn't input any symbols if there is no number
            return


        if d_1s.isOver(pos):
            print("+")
            user_input += "+"
            python_input += "+"

        if d_2s.isOver(pos):
            print("-")
            user_input += "-"
            python_input += "-"

        if d_3s.isOver(pos):
            print("x")
            user_input += "x"
            python_input += "*"

        if d_4s.isOver(pos):
            print("÷")
            user_input += "÷"
            python_input += "/"

        if d_5s.isOver(pos):
            print("=")
            result = eval(python_input)
            python_input = ""
            user_input += f"={result:.2f}"
            is_finished = True

        if d_6s.isOver(pos):
            print("C")
            python_input = ""
            user_input = ""

def MOUSEOVERnumbers():
    global user_input
    global python_input
    global is_finished

    if event.type == pygame.MOUSEBUTTONDOWN:
        if is_finished:
            user_input = ""
            python_input = ""
            is_finished = False
        pos = pygame.mouse.get_pos()          
        if s_1s.isOver(pos):
            print("1")
            user_input += "1"
            python_input += "1"
        if s_2s.isOver(pos):
            print("2")
            user_input += "2"
            python_input += "2"
        if s_3s.isOver(pos):
            print("3")
            user_input += "3"
            python_input += "3"
        if s_4s.isOver(pos):
            print("4")
            user_input += "4"
            python_input += "4"
        if s_5s.isOver(pos):
            print("5")
            user_input += "5"
            python_input += "5"
        if s_6s.isOver(pos):
            print("6")
            user_input += "6"
            python_input += "6"
        if s_7s.isOver(pos):
            print("7")
            user_input += "7"
            python_input += "7"
        if s_8s.isOver(pos):
            print("8")
            user_input += "8"
            python_input += "8"
        if s_9s.isOver(pos):
            print("9")
            user_input += "9"
            python_input += "9"
        if s_0s.isOver(pos):
            print("0")
            user_input += "0"
            python_input += "0"

# the main loop
run = True
user_input = ""
python_input = ""
is_finished = True

while run:
    # input tap
    inputtap = button((253,100,32),10,280,450,50,f"{user_input}")

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False

        MOUSEOVERnumbers()

        Symbols()

    redraw(inputtap)
    pygame.display.update()

pygame.quit()

Vous pouvez ensuite ajouter un reset bouton pour réinitialiser l'entrée de l'utilisateur. Également après que l'utilisateur a cliqué sur = bouton, démarrez une nouvelle entrée utilisateur plutôt que de concaténer sur l'ancienne.

Le reset le bouton est étiqueté avec C dans cet exemple. Chaque fois que l'utilisateur clique dessus, videz la chaîne d'entrée utilisateur et la chaîne d'entrée python.

J'utilise aussi un is_finished global variable booléenne pour vérifier si l'utilisateur clique sur = bouton. Si l'utilisateur clique dessus, cela signifie qu'il a terminé le calcul, de sorte que la prochaine fois que l'utilisateur clique sur un bouton de symbole, la chaîne d'entrée de l'utilisateur est effacée.

En attendant, l'utilisateur ne doit pas saisir deux symboles sauf C bouton en même temps. Je le juge en comparant les dernières entrées de l'utilisateur du personnage et les entrées de l'utilisateur du personnage actuel.

En outre, l'utilisateur ne doit saisir aucun symbole avant de saisir un nombre. Je le juge avec la variable globale is_finished . Si is_finished est vrai, cela signifie que l'utilisateur ne commence pas à saisir, il n'y a donc pas de valeur dans la chaîne d'entrée de l'utilisateur. J'utilise aussi un IndexError exception juste au cas où car une chaîne d'entrée utilisateur vide ne peut pas fonctionner avec un index négatif.

Pour faire la distinction entre le résultat entier et le résultat flottant, vous pouvez juger s'il y a un point dans le résultat :

>>> '.' in '45.3'
True
>>> '.' in '453'
False

Enfin, vous pouvez aussi simplifier ces if logique avec button.text des propriétés comme ce que fait Rabbid76 :

        for number_button in numbers:
            if number_button.isOver(pos):
                print(number_button.text)
                user_input += number_button.text
                python_input += number_button.text

Implémenter une classe qui peut effectuer des opérations arithmétiques et stocke le texte courant, qui doit être affiché (self.currentText ) à l'écran :

class Calculate:
    def __init__(self):
        self.currentValue = 0
        self.newNumber = 0
        self.currentOperation = None
        self.currentText = ""
    def newDigit(self, text):
        self.newNumber = self.newNumber * 10 + int(text) 
        self.currentText = str(self.newNumber)
    def newOperation(self, op):
        try:
            if self.currentOperation == '+':
                self.currentValue += self.newNumber
            elif self.currentOperation == '-':
                self.currentValue -= self.newNumber
            elif self.currentOperation == 'x':
                self.currentValue *= self.newNumber
            elif self.currentOperation == '÷':
                self.currentValue /= self.newNumber
            elif self.currentOperation != "=":
                self.currentValue = self.newNumber
        except:
            self.currentValue = 0
        self.currentOperation = op
        self.currentText = str(self.currentValue)
        self.newNumber = 0

calculator = Calculate()

Dessinez le texte self.currentText en redraw

def redraw():
    # [...]

    inputtap.draw(window)
    inputtext = font.render(calculator.currentText, True, (0, 0, 0))
    window.blit(inputtext, (inputtap.x + inputtap.width - inputtext.get_width() - 4, inputtap.y + 4))

Appelez calculator.newDigit lorsqu'un chiffre est enfoncé :

def MOUSEOVERnumbers():
    if event.type == pygame.MOUSEBUTTONDOWN:
        for button in numbers:
            if button.isOver(event.pos):
                print(button.text)  
                calculator.newDigit(button.text)

Appelez calculator.newOperation lorsqu'un bouton de fonctionnement est enfoncé :

def Symbols():  
    if event.type == pygame.MOUSEBUTTONDOWN:
        for button in symbols:
            if button.isOver(event.pos):
                print(button.text)
                calculator.newOperation(button.text)
        if clearButton.isOver(event.pos):
            calculator = Calculate()

Voir l'exemple complet :

import pygame,math
pygame.init()

window_height = 500
window_width = 500
window  = pygame.display.set_mode((window_height,window_width))

font = pygame.font.SysFont('comicsans', 60)

    # the buttons for the shop MENU
class Button():
    def __init__(self, color, x,y,width,height, text=''):
        self.color = color
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.text = text
        self.over = False
        self.image = font.render(self.text, 1, (0,0,0))

    def draw(self,window,outline=None):
                #Call this method to draw the button on the screen
        if outline:
            pygame.draw.rect(window, outline, (self.x-2,self.y-4,self.width+4,self.height+8),0)
                    
        pygame.draw.rect(window, self.color, (self.x,self.y-2,self.width,self.height+4),0)
                
        if self.text != '':
            w, h = self.image.get_size()
            window.blit(self.image, (self.x + (self.width//2 - w//2), self.y + (self.height//2 - h//2 + 2)))

    def isOver(self, pos):
                #Pos is the mouse position or a tuple of (x,y) coordinates
        if pos[0] > self.x and pos[0] < self.x + self.width:
            if pos[1] > self.y and pos[1] < self.y + self.height:
                return True
                    
        return False

    def playSoundIfMouseIsOver(self, pos, sound):
        if self.isOver(pos):            
            if not self.over:
                beepsound.play()
                self.over = True
        else:
            self.over = False

class Calculate:
    def __init__(self):
        self.currentValue = 0
        self.newNumber = 0
        self.currentOperation = None
        self.currentText = ""
    def newDigit(self, text):
        self.newNumber = self.newNumber * 10 + int(text) 
        self.currentText = str(self.newNumber)
    def newOperation(self, op):
        try:
            if self.currentOperation == '+':
                self.currentValue += self.newNumber
            elif self.currentOperation == '-':
                self.currentValue -= self.newNumber
            elif self.currentOperation == 'x':
                self.currentValue *= self.newNumber
            elif self.currentOperation == '÷':
                self.currentValue /= self.newNumber
            elif self.currentOperation != "=":
                self.currentValue = self.newNumber
        except:
            self.currentValue = 0
        self.currentOperation = op
        self.currentText = str(self.currentValue)
        self.newNumber = 0

calculator = Calculate()
        
                    
white = (255,255,255)
# the numbers for the calcaltor
s_1s = Button((0,255,0),40,450,30,30, '1')
s_2s = Button((0,255,0),40,400,30,30, '2')
s_3s = Button((0,255,0),40,350,30,30, '3')
s_4s = Button((0,255,0),100,450,30,30, '4')
s_5s = Button((0,255,0),100,400,30,30, '5')
s_6s = Button((0,255,0),100,350,30,30, '6')
s_7s = Button((0,255,0),150,450,30,30, '7')
s_8s = Button((0,255,0),150,400,30,30, '8')
s_9s = Button((0,255,0),150,350,30,30, '9')
s_0s = Button((0,255,0),200,450,30,30, '0')

numbers = [s_1s,s_2s,s_3s,s_4s,s_5s,s_6s,s_7s,s_8s,s_9s,s_0s]

# the symbols!
d_1s = Button((0,255,0),260,450,30,30, '+')
d_2s = Button((0,255,0),260,400,30,30, '-')
d_3s = Button((0,255,0),260,350,30,30, 'x')
d_4s = Button((0,255,0),200,400,30,30, '÷')
d_5s = Button((0,255,0),320,450,30,30, '=')

symbols = [d_1s,d_2s,d_3s,d_4s,d_5s]

clearButton = Button((0,255,0),200,350,30,30, 'C')

allButtons = numbers + symbols + [clearButton]

# input tap
inputtap = Button((253,100,32),10,280,450,50,"")

# redraw window
def redraw():
    for button in allButtons:
        button.draw(window)

    inputtap.draw(window)
    inputtext = font.render(calculator.currentText, True, (0, 0, 0))
    window.blit(inputtext, (inputtap.x + inputtap.width - inputtext.get_width() - 4, inputtap.y + 4))
 
def Symbols():  
    global calculator
    if event.type == pygame.MOUSEBUTTONDOWN:
        for button in symbols:
            if button.isOver(event.pos):
                print(button.text)
                calculator.newOperation(button.text)
        if clearButton.isOver(event.pos):
            calculator = Calculate()
    
def MOUSEOVERnumbers():
    if event.type == pygame.MOUSEBUTTONDOWN:
        for button in numbers:
            if button.isOver(event.pos):
                print(button.text)  
                calculator.newDigit(button.text)

# the main loop
run = True
while run:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False

        MOUSEOVERnumbers()
        Symbols()

    redraw()
    pygame.display.update()
pygmae.quit()