python画图小游戏课程设计

pyQT6实现画图小游戏,逻辑清晰,界面美观,非常NICE!
在这里插入图片描述

Inspired by PyQt5 Creating Paint Application In 40 Minutes灵感来自PyQt5在40分钟内创建油漆应用程序

https://www.youtube.com/watch?v=qEgyGyVA1ZQ

NB If the menus do not work then click on another application and then click back注意:如果菜单不工作,请单击另一个应用程序,然后单击返回

and they will work https://python-forum.io/Thread-Tkinter-macOS-Catalina-and-Python-menu-issue他们将工作

PyQt documentation links are prefixed with the word ‘documentation’ in the code below and can be accessed automatically

#在下面的代码中,PyQt文档链接的前缀是’documentation’,可以自动访问

in PyCharm using the following technique https://www.jetbrains.com/help/pycharm/inline-documentation.html

在PyCharm中使用以下技术

from PyQt6.QtWidgets import QApplication, QWidget, QMainWindow, QFileDialog, QDockWidget, QPushButton, QVBoxLayout,
QLabel, QMessageBox, QGroupBox, QRadioButton, QToolBar
from PyQt6.QtGui import QIcon, QPainter, QPen, QAction, QPixmap
import sys
import csv, random
from PyQt6.QtCore import Qt, QPoint
import tkinter as tk # 导入tkinter模块。为了方便后续讲解,命名为 tk。
import tkinter.messagebox # 引入弹窗库,防止解释器弹出报错。

from pyqt6_plugins.examplebutton import QtWidgets

class PictionaryGame(QMainWindow): # documentation https://doc.qt.io/qt-6/qwidget.html
‘’’
Painting Application class绘画应用类
‘’’

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

    # set window title设置窗口标题  图画猜字游戏- A2模板
    self.setWindowTitle("Pictionary Game - A2 Template")

    # set the windows dimensions设置窗口尺寸
    top = 400
    left = 400
    width = 800
    height = 600
    self.setGeometry(top, left, width, height)

    # set the icon#设置图标# # Windows版本
    # windows version
    self.setWindowIcon(
        QIcon("./icons/paint-brush.png"))  # documentation: https://doc.qt.io/qt-6/qwidget.html#windowIcon-prop
    # mac version - not yet workingMAC版本-还不能工作
    # self.setWindowIcon(QIcon(QPixmap("./icons/paint-brush.png")))

    # image settings (default)图像设置(默认)
    self.image = QPixmap("./icons/canvas.png")  # documentation: https://doc.qt.io/qt-6/qpixmap.html
    self.image.fill(Qt.GlobalColor.white)  # documentation: https://doc.qt.io/qt-6/qpixmap.html#fill
    mainWidget = QWidget()
    mainWidget.setMaximumWidth(300)

    # draw settings (default)绘制设置(默认)
    self.drawing = False
    self.brushSize = 3
    self.brushColor = Qt.GlobalColor.black  # documentation: https://doc.qt.io/qt-6/qt.html#GlobalColor-enum

    # reference to last point recorded by mouse引用鼠标记录的最后一点
    self.lastPoint = QPoint()  # documentation: https://doc.qt.io/qt-6/qpoint.html

    # set up menus设置菜单
    mainMenu = self.menuBar()  # create a menu bar创建一个菜单栏
    mainMenu.setNativeMenuBar(False)      #将文件菜单添加到菜单栏中,因为Mac中“文件”是保留的,所以需要这个空间
    fileMenu = mainMenu.addMenu(" File")  # add the file menu to the menu bar, the space is required as "File" is reserved in Mac
    brushSizeMenu = mainMenu.addMenu(" Brush Size")  # add the "Brush Size" menu to the menu bar添加“笔刷大小”菜单到菜单栏
    brushColorMenu = mainMenu.addMenu(" Brush Colour")  # add the "Brush Colour" menu to the menu bar添加“笔刷颜色”菜单到菜单栏
    helpMenu = mainMenu.addMenu("Help")

    # save menu item 保存菜单项                                      #创建一个以PNG作为图标的保存操作
    saveAction = QAction(QIcon("./icons/save.png"), "Save", self)  # create a save action with a png as an icon, documentation: https://doc.qt.io/qt-6/qaction.html
    saveAction.setShortcut("Ctrl+S")  # connect this save action to a keyboard shortcut, documentation: https://doc.qt.io/qt-6/qaction.html#shortcut-prop
                                      #将此保存操作连接到键盘快捷方式

    # open
    openAction = QAction(QIcon("./icons/open.png"), "Open", self)
    openAction.setShortcut("Ctrl+O")
    fileMenu.addAction(openAction)
    openAction.triggered.connect(self.open)

                                      #将保存操作添加到文件菜单中
    fileMenu.addAction(saveAction)  # add the save action to the file menu, documentation: https://doc.qt.io/qt-6/qwidget.html#addAction
    saveAction.triggered.connect(self.save)  # when the menu option is selected or the shortcut is used the save slot is triggered, documentation: https://doc.qt.io/qt-6/qaction.html#triggered
                                            #当选择菜单选项或使用快捷方式时,会触发保存槽

    # clear
    clearAction = QAction(QIcon("./icons/clear.png"), "Clear", self)  # create a clear action with a png as an icon用PNG作为图标创建一个清晰的动作
    clearAction.setShortcut("Ctrl+C")  # connect this clear action to a keyboard shortcut将此清除操作连接到键盘快捷键
    fileMenu.addAction(clearAction)  # add this action to the file menu将此操作添加到文件菜单中
    clearAction.triggered.connect(self.clear)  # when the menu option is selected or the shortcut is used the clear slot is triggered
                                                #当选择菜单选项或使用快捷方式时,将触发清除槽

    # exit
    exitAction = QAction(QIcon("./icons/exit.png"), "Exit", self)
    exitAction.setShortcut("Ctrl+Q")
    fileMenu.addAction(exitAction)
    exitAction.triggered.connect(self.close)

    # about
    aboutAction = QAction(QIcon("./icons/about.png"), "about", self)
    aboutAction.setShortcut("Ctrl+A")
    helpMenu.addAction(aboutAction)
    aboutAction.triggered.connect(self.show_message_about)
    # help
    helpAction = QAction(QIcon("./icons/help.png"), "help", self)
    helpAction.setShortcut("Ctrl+H")
    helpMenu.addAction(helpAction)
    helpAction.triggered.connect(self.show_message_help)

    # brush thickness刷厚度
    threepxAction = QAction(QIcon("./icons/threepx.png"), "3px", self)
    threepxAction.setShortcut("Ctrl+3")
    brushSizeMenu.addAction(threepxAction)  # connect the action to the function below将动作连接到下面的函数
    threepxAction.triggered.connect(self.threepx)

    fivepxAction = QAction(QIcon("./icons/fivepx.png"), "5px", self)
    fivepxAction.setShortcut("Ctrl+5")
    brushSizeMenu.addAction(fivepxAction)
    fivepxAction.triggered.connect(self.fivepx)

    sevenpxAction = QAction(QIcon("./icons/sevenpx.png"), "7px", self)
    sevenpxAction.setShortcut("Ctrl+7")
    brushSizeMenu.addAction(sevenpxAction)
    sevenpxAction.triggered.connect(self.sevenpx)

    ninepxAction = QAction(QIcon("./icons/ninepx.png"), "9px", self)
    ninepxAction.setShortcut("Ctrl+9")
    brushSizeMenu.addAction(ninepxAction)
    ninepxAction.triggered.connect(self.ninepx)

    # brush colors
    blackAction = QAction(QIcon("./icons/black.png"), "Black", self)
    blackAction.setShortcut("Ctrl+B")
    brushColorMenu.addAction(blackAction);
    blackAction.triggered.connect(self.black)

    redAction = QAction(QIcon("./icons/red.png"), "Red", self)
    redAction.setShortcut("Ctrl+R")
    brushColorMenu.addAction(redAction);
    redAction.triggered.connect(self.red)

    greenAction = QAction(QIcon("./icons/green.png"), "Green", self)
    greenAction.setShortcut("Ctrl+G")
    brushColorMenu.addAction(greenAction);
    greenAction.triggered.connect(self.green)

    yellowAction = QAction(QIcon("./icons/yellow.png"), "Yellow", self)
    yellowAction.setShortcut("Ctrl+Y")
    brushColorMenu.addAction(yellowAction);
    yellowAction.triggered.connect(self.yellow)

    # Side Dock
    self.dockInfo = QDockWidget()
    self.addDockWidget(Qt.DockWidgetArea.LeftDockWidgetArea, self.dockInfo)

    #widget inside the Dock码头内的小部件1
    playerInfo = QWidget()
    self.vbdock = QVBoxLayout()
    playerInfo.setLayout(self.vbdock)
    playerInfo.setMaximumSize(100, self.height())
    self.player1 = 0
    self.player2 = 0
    self.getList("easy")
    self.currentWord = self.getWord()
    self.currentPlayer = 1
    #add controls to custom widget向自定义小部件1添加控件
    self.lab=QLabel("CurrentTurn:"+str(self.currentPlayer))
    self.vbdock.addWidget(self.lab)
    self.vbdock.addSpacing(20)
    self.vbdock.addWidget(QLabel("Scores:"))
    self.lab1=QLabel("Player 1: "+str(self.player1))
    self.vbdock.addWidget(self.lab1)
    self.lab2=QLabel("Player 2: "+str(self.player2))
    self.vbdock.addWidget(self.lab2)

    #self.vbdock.addWidget(QLabel(self.currentWord))
    self.vbdock.addStretch(1)
    self. correct_guess = QPushButton("Correct Guess")#得一分基础上再得一分
    self.vbdock.addWidget(self.correct_guess)
    self.correct_guess.clicked.connect(self.show_correct_guess)
    self.start=QPushButton("Start")
    self.vbdock.addWidget(self.start)#得一分
    self.start.clicked.connect(self.show_message_word)
    self.skip=QPushButton("Skip Turn")#不得分
    self.vbdock.addWidget(self.skip)
    self.skip.clicked.connect(self.show_message_skipword)
    self.button1 = QRadioButton('yellow', self)
    self.button1.setStyleSheet("QRadioButton::indicator {width:13px;height:13px;border-radius:6px}"
                               "QRadioButton::indicator:checked {background-color:yellow;}"
                               "QRadioButton::indicator:unchecked {background-color:white;}")

    self.button1.clicked.connect(self.yellow)
    self.button2 = QRadioButton('black', self)

    self.button2.setStyleSheet("QRadioButton::indicator {width:13px;height:13px;border-radius:6px}"
                               "QRadioButton::indicator:checked {background-color:black;}"
                               "QRadioButton::indicator:unchecked {background-color:white;}")
    self.button2.clicked.connect(self.black)
    self.button3 = QRadioButton('green', self)

    self.button3.setStyleSheet("QRadioButton::indicator {width:13px;height:13px;border-radius:6px}"
                               "QRadioButton::indicator:checked {background-color:green;}"
                               "QRadioButton::indicator:unchecked {background-color:white;}")
    self.button3.clicked.connect(self.green)
    self.button4 = QRadioButton('red', self)

    self.button4.setStyleSheet("QRadioButton::indicator {width:13px;height:13px;border-radius:6px}"
                               "QRadioButton::indicator:checked {background-color:red;}"
                               "QRadioButton::indicator:unchecked {background-color:white;}")
    self.button4.clicked.connect(self.red)

    self.button5 = QRadioButton('3px', self)
    self.button5.setStyleSheet("QRadioButton::indicator {width:13px;height:13px;border-radius:6px}"
                               "QRadioButton::indicator:checked {background-color:yellow;}"
                               "QRadioButton::indicator:unchecked {background-color:white;}")
    self.button5.clicked.connect(self.threepx)

    self.button6 = QRadioButton('5px', self)
    self.button6.setStyleSheet("QRadioButton::indicator {width:13px;height:13px;border-radius:6px}"
                               "QRadioButton::indicator:checked {background-color:yellow;}"
                               "QRadioButton::indicator:unchecked {background-color:white;}")
    self.button6.clicked.connect(self.fivepx)

    self.button7 = QRadioButton('7px', self)
    self.button7.setStyleSheet("QRadioButton::indicator {width:13px;height:13px;border-radius:6px}"
                               "QRadioButton::indicator:checked {background-color:yellow;}"
                               "QRadioButton::indicator:unchecked {background-color:white;}")
    self.button7.clicked.connect(self.sevenpx)

    self.button8 = QRadioButton('9px', self)
    self.button8.setStyleSheet("QRadioButton::indicator {width:13px;height:13px;border-radius:6px}"
                               "QRadioButton::indicator:checked {background-color:yellow;}"
                               "QRadioButton::indicator:unchecked {background-color:white;}")
    self.button8.clicked.connect(self.ninepx)
    #Setting colour of dock to gray设置码头的颜色为灰色
    playerInfo.setAutoFillBackground(True)
    p = playerInfo.palette()
    p.setColor(playerInfo.backgroundRole(), Qt.GlobalColor.gray)
    playerInfo.setPalette(p)

    #set widget for dock为码头设置小部件
    self.dockInfo.setWidget(playerInfo)



    # QToolBar
    toolbar = QToolBar(self)
    layout = QVBoxLayout()
    self.addToolBar(Qt.ToolBarArea.TopToolBarArea, toolbar)
    toolbar.setWindowTitle("Color")
    toolbar.setStyleSheet("background-color:rgb(166,166,166);")
    action_radio_btn1 = toolbar.addWidget(self.button1)
    action_radio_btn2 = toolbar.addWidget(self.button2)
    action_radio_btn2.setCheckable(True)
    action_radio_btn3 = toolbar.addWidget(self.button3)
    action_radio_btn4 = toolbar.addWidget(self.button4)
    toolbar.addSeparator()
    # QToolBar
    toolbar1 = QToolBar(self)
    layout1 = QVBoxLayout()
    self.addToolBar(Qt.ToolBarArea.RightToolBarArea, toolbar1)
    toolbar1.setWindowTitle("Color")
    toolbar1.setStyleSheet("background-color:rgb(166,166,166);")
    action_radio_btn5 = toolbar1.addWidget(self.button5)
    action_radio_btn6 = toolbar1.addWidget(self.button6)
    action_radio_btn6.setCheckable(True)
    action_radio_btn7 = toolbar1.addWidget(self.button7)
    action_radio_btn8 = toolbar1.addWidget(self.button8)
    toolbar.addSeparator()


# event handlers事件处理程序          #当按下鼠标时
def mousePressEvent(self, event):  # when the mouse is pressed, documentation: https://doc.qt.io/qt-6/qwidget.html#mousePressEvent
    if event.button() == Qt.MouseButton.LeftButton:  # if the pressed button is the left button如果按下的按钮是左键
        self.drawing = True  # enter drawing mode进入绘图模式
        self.lastPoint = event.pos()  # save the location of the mouse press as the lastPoint保存鼠标按下的位置为lastPoint
        print(self.lastPoint)  # print the lastPoint for debugging purposes打印lastPoint以便调试
                                    #当鼠标移动时
def mouseMoveEvent(self, event):  # when the mouse is moved, documenation: documentation: https://doc.qt.io/qt-6/qwidget.html#mouseMoveEvent
    if self.drawing:                     #对象,它允许在图像上进行绘图
        painter = QPainter(self.image)  # object which allows drawing to take place on an image
        # allows the selection of brush colour, brish size, line type, cap type, join type. Images available here http://doc.qt.io/qt-6/qpen.html
        #允许选择笔刷颜色,毛边大小,线型,帽型,连接型。图像可用
        painter.setPen(QPen(self.brushColor, self.brushSize, Qt.PenStyle.SolidLine, Qt.PenCapStyle.RoundCap, Qt.PenJoinStyle.RoundJoin))
        painter.drawLine(self.lastPoint, event.pos())  # draw a line from the point of the orginal press to the point to where the mouse was dragged to
        self.lastPoint = event.pos()  # set the last point to refer to the point we have just moved to, this helps when drawing the next line segment
        #从最初按下的点到鼠标被拖动的点绘制一条线,以设置最后一个点指向我们刚刚移动到的点,这在绘制下一个线段时很有帮助
        self.update()  # call the update method of the widget which calls the paintEvent of this class
                        #调用调用这个类的paintEvent的小部件的update方法

                                        #当鼠标被释放时
def mouseReleaseEvent(self, event):  # when the mouse is released, documentation: https://doc.qt.io/qt-6/qwidget.html#mouseReleaseEvent
    if event.button() == Qt.MouseButton.LeftButton:  # if the released button is the left button, documentation: https://doc.qt.io/qt-6/qt.html#MouseButton-enum ,
        self.drawing = False  # exit drawing mode如果释放按钮是左键,退出绘图模式

# paint events油漆事件
def paintEvent(self, event):
    # you should only create and use the QPainter object in this method, it should be a local variable
    #你应该只在这个方法中创建和使用QPainter对象,它应该是一个局部变量
                                    #创建一个新的QPainter对象
    canvasPainter = QPainter(self)  # create a new QPainter object, documentation: https://doc.qt.io/qt-6/qpainter.html
    canvasPainter.drawPixmap(QPoint(), self.image)  # draw the image , documentation: https://doc.qt.io/qt-6/qpainter.html#drawImage-1
                                                    #绘制图像
# resize event - this function is called调整大小事件——调用这个函数
def resizeEvent(self, event):
    self.image = self.image.scaled(self.width(), self.height())

# slots
def save(self):
    filePath, _ = QFileDialog.getSaveFileName(self, "Save Image", "",
                                              "PNG(*.png);;JPG(*.jpg *.jpeg);;All Files (*.*)")
    if filePath == "":  # if the file path is empty如果文件路径为空
        return  # do nothing and return什么都不做,然后回来
    self.image.save(filePath)  # save file image to the file path将文件图像保存到文件路径

def clear(self):
    self.image.fill(            #用白色填充图像
        Qt.GlobalColor.white)  # fill the image with white, documentation: https://doc.qt.io/qt-6/qimage.html#fill-2
    self.update()  # call the update method of the widget which calls the paintEvent of this class
                    #调用调用这个类的paintEvent的小部件的update方法

def show_message_about(self):
    QMessageBox.about(self, "About", "This is Pictionary Game")

def show_message_help(self):
    QMessageBox.about(self, "Help", "If you have any questions about this Pictionary Game, please contact 123@.com")

def show_message_word(self):
    self.lab.setText("CurrentTurn:" + str(self.currentPlayer))
    QMessageBox.about(self, "Player"+str(self.currentPlayer)+" See Your Word", "Don't Let Others See! Press Details!" + "\n" + "The WORD IS   " + self.currentWord)
    if self.currentPlayer == 1:
        self.player1=self.player1+1
        self.currentPlayer=2
        print("self.player1  "+str(self.player1))
    else:
        self.player2=self.player2+1
        self.currentPlayer=1
        print("self.player2  "+str(self.player2))
    self.lab1.setText("Player 1: " + str(self.player1))
    self.lab2.setText("Player 2: " + str(self.player2))
def show_correct_guess(self):
    self.lab.setText("CurrentTurn:" + str(self.currentPlayer))
    if self.currentPlayer == 2:
        self.player1=self.player1+1
    else:
        self.player2=self.player2+1
    self.lab1.setText("Player 1: " + str(self.player1))
    self.lab2.setText("Player 2: " + str(self.player2))


def show_message_skipword(self):
    self.lab.setText("CurrentTurn:" + str(self.currentPlayer))
    self.currentWord=self.getWord()
    if self.currentPlayer == 1:
        self.currentPlayer = 2
    else:
        self.currentPlayer = 1
    QMessageBox.about(self, "Player See Your Word","Don't Let Others See! Press Details!"+"\n"+"The WORD IS   "+self.currentWord)
    self.lab1.setText("Player 1: " + str(self.player1))
    self.lab2.setText("Player 2: " + str(self.player2))


def threepx(self):  # the brush size is set to 3笔刷大小设置为3
    self.brushSize = 3

def fivepx(self):
    self.brushSize = 5

def sevenpx(self):
    self.brushSize = 7

def ninepx(self):
    self.brushSize = 9

def black(self):  # the brush color is set to black 笔刷的颜色设置为黑色
    self.brushColor = Qt.GlobalColor.black

def black(self):
    self.brushColor = Qt.GlobalColor.black

def red(self):
    self.brushColor = Qt.GlobalColor.red

def green(self):
    self.brushColor = Qt.GlobalColor.green

def yellow(self):
    self.brushColor = Qt.GlobalColor.yellow

#Get a random word from the list read from file
#从文件中读取的列表中获取一个随机单词
def getWord(self):
    randomWord = random.choice(self.wordList)
    print(randomWord)
    return randomWord

#read word list from file
#从文件中读取单词列表
def getList(self, mode):
    with open(mode + 'mode.txt') as csv_file:
        csv_reader = csv.reader(csv_file, delimiter=',')
        line_count = 0
        for row in csv_reader:
            #print(row)
            self.wordList = row
            line_count += 1
        #print(f'Processed {line_count} lines.')

# open a file
#打开文件
def open(self):
    '''
    This is an additional function which is not part of the tutorial. It will allow you to:
     - open a file dialog box,
     - filter the list of files according to file extension
     - set the QImage of your application (self.image) to a scaled version of the file)
     - update the widget
    '''
    '''
        这是一个附加函数,不是本教程的一部分。它将允许您:
         -打开文件对话框,
         -根据文件扩展名过滤文件列表
        -设置你的应用程序的QImage (self.image)为文件的缩放版本)
        -更新小部件
    '''
    filePath, _ = QFileDialog.getOpenFileName(self, "Open Image", "",
                                              "PNG(*.png);;JPG(*.jpg *.jpeg);;All Files (*.*)")
    if filePath == "":  # if not file is selected exit如果不选择文件,则退出
        return
    with open(filePath, 'rb') as f:  # open the file in binary mode for reading以二进制模式打开文件进行读取
        content = f.read()  # read the file读取文件
    self.image.loadFromData(content)  # load the data into the file将数据加载到文件中
    width = self.width()  # get the width of the current QImage in your application获取应用程序中当前QImage的宽度
    height = self.height()  # get the height of the current QImage in your application获取应用程序中当前QImage的高度
    self.image = self.image.scaled(width, height)  # scale the image from file and put it in your QImage缩放图像从文件,并把它放在您的QImage
    self.update()  # call the update method of the widget which calls the paintEvent of this class调用调用这个类的paintEvent的小部件的update方法

this code will be executed if it is the main module but not if the module is imported如果它是主模块,则执行此代码,但如果模块被导入则不执行

https://stackoverflow.com/questions/419163/what-does-if-name-main-do

if name == “main”:

app = QApplication(sys.argv)
window = PictionaryGame()
window.show()
app.exec()  # start the event loop running启动事件循环运行
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值