精华内容
下载资源
问答
  • 正在尝试着做一个比较完善的画图软件,计划使用tkinter库中的canvas控件来做,目前终于可以拿出来和大家见面了。 不忘初心,方得始终,让我们一起共勉! 好的,言归正传,下面我将详细介绍整个项目的建设过程。 先说...
  • 今天分享给大家的是采用Python3+tkinter制作而成的小项目——黑白棋 tkinter是Python内置的图形化模块,简单易用,一般的小型UI程序可以快速用它实现,具体的tkinter相关知识王老师会在以后开辟专栏单独讲解 我们...

    今天分享给大家的是采用Python3+tkinter制作而成的小项目——黑白棋

    tkinter是Python内置的图形化模块,简单易用,一般的小型UI程序可以快速用它实现,具体的tkinter相关知识王老师会在以后开辟专栏单独讲解

    我们先来看看这个黑白棋项目吧

    一、项目演示

    二、代码

    完整代码如下,用到的素材(图片等)下载地址为:www.itprojects.cn/detail.html…

    from tkinter import *
    from tkinter.messagebox import *
    import random
    
    root = Tk('黑白棋')
    root.title("黑白棋(更多项目实例请访问www.itprojects.cn)")
    # 加载图片
    imgs = [PhotoImage(file='black.png'), PhotoImage(file='white.png'), PhotoImage(file='board.png'), PhotoImage(file='info2.png')]
    
    
    def resetBoard(board):
        """重置棋盘"""
        for x in range(8):
            for y in range(8):
                board[x][y] = 'none'
        # Starting pieces:
        board[3][3] = 'black'
        board[3][4] = 'white'
        board[4][3] = 'white'
        board[4][4] = 'black'
    
    
    def getNewBoard():
        """开局时建立新棋盘"""
        board = []
        for i in range(8):
            board.append(['none'] * 8)
        return board
    
    
    def isValidMove(board, tile, xstart, ystart):
        """是否是合法走法,如果合法返回需要翻转的棋子列表"""
        # 如果该位置已经有棋子或者出界了,返回False
        if not isOnBoard(xstart, ystart) or board[xstart][ystart] != 'none':
            return False
        # 临时将tile 放到指定的位置
        board[xstart][ystart] = tile
        if tile == 'black':
            otherTile = 'white'
        else:
            otherTile = 'black'
        # 要被翻转的棋子
        tilesToFlip = []
        for xdirection, ydirection in [[0, 1], [1, 1], [1, 0], [1, -1], [0, -1], [-1, -1], [-1, 0], [-1, 1]]:
            x, y = xstart, ystart
            x += xdirection
            y += ydirection
            if isOnBoard(x, y) and board[x][y] == otherTile:
                x += xdirection
                y += ydirection
                if not isOnBoard(x, y):
                    continue
                # 一直走到出界或不是对方棋子的位置
                while board[x][y] == otherTile:
                    x += xdirection
                    y += ydirection
                    if not isOnBoard(x, y):
                        break
                # 出界了,则没有棋子要翻转OXXXXX
                if not isOnBoard(x, y):
                    continue
                # 是自己的棋子OXXXXXXO
                if board[x][y] == tile:
                    while True:
                        x -= xdirection
                        y -= ydirection
                        # 回到了起点则结束
                        if x == xstart and y == ystart:
                            break
                        # 需要翻转的棋子
                        tilesToFlip.append([x, y])
        # 将前面临时放上的棋子去掉,即还原棋盘
        board[xstart][ystart] = 'none'  # restore the empty space
        # 没有要被翻转的棋子,则走法非法。翻转棋的规则。
        if len(tilesToFlip) == 0:  # If no tiles were flipped, this is not a valid move.
            return False
        return tilesToFlip
    
    
    def isOnBoard(x, y):
        """是否出界"""
        return x >= 0 and x <= 7 and y >= 0 and y <= 7
    
    
    def getValidMoves(board, tile):
        """获取可落子的位置"""
        validMoves = []
        for x in range(8):
            for y in range(8):
                if isValidMove(board, tile, x, y) != False:
                    validMoves.append([x, y])
        return validMoves
    
    
    def getScoreOfBoard(board):
        """获取棋盘上黑白双方的棋子数"""
        xscore = 0
        oscore = 0
        for x in range(8):
            for y in range(8):
                if board[x][y] == 'black':
                    xscore += 1
                if board[x][y] == 'white':
                    oscore += 1
        return {'black': xscore, 'white': oscore}
    
    
    def whoGoesFirst():
        """决定谁先走"""
        if random.randint(0, 1) == 0:
            return 'computer'
        else:
            return 'player'
    
    
    def makeMove(board, tile, xstart, ystart):
        """将一个tile棋子放到(xstart, ystart)"""
        tilesToFlip = isValidMove(board, tile, xstart, ystart)
        if tilesToFlip == False:
            return False
        board[xstart][ystart] = tile
        for x, y in tilesToFlip:  # tilesToFlip是需要翻转的棋子列表
            board[x][y] = tile  # 翻转棋子
        return True
    
    
    def getBoardCopy(board):
        """复制棋盘"""
        dupeBoard = getNewBoard()
        for x in range(8):
            for y in range(8):
                dupeBoard[x][y] = board[x][y]
        return dupeBoard
    
    
    def isOnCorner(x, y):
        """是否在角上"""
        return (x == 0 and y == 0) or (x == 7 and y == 0) or (x == 0 and y == 7) or (x == 7 and y == 7)
    
    
    def getComputerMove(board, computerTile):
        """电脑走法,AI"""
        # 获取所以合法走法
        possibleMoves = getValidMoves(board, computerTile)
        if not possibleMoves:  # 如果没有合法走法
            print("电脑没有合法走法")
            return None
    
        # 打乱所有合法走法
        random.shuffle(possibleMoves)
        # [x, y]在角上,则优先走,因为角上的不会被再次翻转
        for x, y in possibleMoves:
            if isOnCorner(x, y):
                return [x, y]
        bestScore = -1
        for x, y in possibleMoves:
            dupeBoard = getBoardCopy(board)
            makeMove(dupeBoard, computerTile, x, y)
            # 按照分数选择走法,优先选择翻转后分数最多的走法
            score = getScoreOfBoard(dupeBoard)[computerTile]
            if score > bestScore:
                bestMove = [x, y]
                bestScore = score
        return bestMove
    
    
    def isGameOver(board):
        """是否游戏结束"""
        for x in range(8):
            for y in range(8):
                if board[x][y] == 'none':
                    return False
        return True
    
    
    def drawQiPan():
        """画棋盘"""
        img1 = imgs[2]
        cv.create_image((360, 360), image=img1)
        cv.pack()
    
    
    def callback(event):
        """走棋"""
        global turn
        # print ("clicked at", event.x, event.y,turn)
        # x=(event.x)//40  #换算棋盘坐标
        # y=(event.y)//40
        if (gameOver == False and turn == 'computer'):  # 没轮到玩家走棋
            return
        col = int((event.x - 40) / 80)  # 换算棋盘坐标
        row = int((event.y - 40) / 80)
        if mainBoard[col][row] != "none":
            showinfo(title="提示", message="已有棋子")
        if makeMove(mainBoard, playerTile, col, row) == True:  # 将一个玩家棋子放到(col, row)
            if getValidMoves(mainBoard, computerTile) != []:
                turn = 'computer'
        # 电脑走棋
        if getComputerMove(mainBoard, computerTile) == None:
            turn = 'player'
            showinfo(title="玩家继续", message="玩家继续")
        else:
            computerGo()
            # 重画所有的棋子和棋盘
        drawAll()
        drawCanGo()
        if isGameOver(mainBoard):  # 游戏结束,显示双方棋子数量
            scorePlayer = getScoreOfBoard(mainBoard)[playerTile]
            scoreComputer = getScoreOfBoard(mainBoard)[computerTile]
            outputStr = gameoverStr + "玩家:" + str(scorePlayer) + ":" + "电脑:" + str(scoreComputer)
            showinfo(title="游戏结束提示", message=outputStr)
    
    
    def computerGo():
        """电脑走棋"""
        global turn
        if (gameOver == False and turn == 'computer'):
            x, y = getComputerMove(mainBoard, computerTile)  # 电脑AI走法
            makeMove(mainBoard, computerTile, x, y)
            savex, savey = x, y
            # 玩家没有可行的走法了,则电脑继续,否则切换到玩家走
            if getValidMoves(mainBoard, playerTile) != []:
                turn = 'player'
            else:
                if getValidMoves(mainBoard, computerTile) != []:
                    showinfo(title="电脑继续", message="电脑继续")
                    computerGo()
    
    
    def drawAll():
        """重画所有的棋子和棋盘"""
        drawQiPan()
        for x in range(8):
            for y in range(8):
                if mainBoard[x][y] == 'black':
                    cv.create_image((x * 80 + 80, y * 80 + 80), image=imgs[0])
                    cv.pack()
                elif mainBoard[x][y] == 'white':
                    cv.create_image((x * 80 + 80, y * 80 + 80), image=imgs[1])
                    cv.pack()
    
    
    def drawCanGo():
        """画提示位置"""
        list1 = getValidMoves(mainBoard, playerTile)
        for m in list1:
            x = m[0]
            y = m[1]
            cv.create_image((x * 80 + 80, y * 80 + 80), image=imgs[3])
            cv.pack()
    
    
    if __name__ == '__main__':
        # 初始化
        gameOver = False
        gameoverStr = 'Game Over Score '
        mainBoard = getNewBoard()
        resetBoard(mainBoard)
        turn = whoGoesFirst()
        showinfo(title="游戏开始提示", message=turn + "先走!")
        print(turn, "先走!")
        if turn == 'player':
            playerTile = 'black'
            computerTile = 'white'
        else:
            playerTile = 'white'
            computerTile = 'black'
            computerGo()
    
        # 设置窗口
        cv = Canvas(root, bg='green', width=720, height=780)
        # 重画所有的棋子和棋盘
        drawAll()
        drawCanGo()
        cv.bind("<Button-1>", callback)
        cv.pack()
        root.mainloop()

    本文首发于python黑洞网,csdn同步跟新

     

    展开全文
  • 序言本章介绍tkinter的button控件,本文是python gui系列的第6篇文章,整个约20篇博客,将全面的介绍python tkinter常用控件,最后还将基于tkinter搭建两个比较完整的小项目。2. 环境信息*************************...

    python tkinter之button控件介绍

    1. 序言

    本章介绍tkinter的button控件,本文是python gui系列的第6篇文章,整个约20篇博客,将全面的介绍python tkinter常用控件,最后还将基于tkinter搭建两个比较完整的小项目。

    2. 环境信息

    ********************************

    本系列运行平台:mac os 10.13.4

    python 版本:3.6.4

    ********************************

    3. button控件

    button小部件是一个标准的tkinter的部件,用于实现各种按钮。按钮可以包含文本或图像,您可以调用python函数或方法用于每个按钮。tkinter的按钮被按下时,会自动调用该函数或方法。

    按钮文本可跨越一个以上的行。此外,文本字符可以有下划线,例如标记的键盘快捷键。默认情况下,使用tab键可以移动到一个按钮部件。

    用法:button(根对象, [属性列表]),常用的属性列表如下:

    函数

    描述

    text

    显示文本内容

    command

    指定button的事件处理函数

    compound

    同一个button既显示文本又显示图片,可用此参数将其混叠起来,compound=’bottom’(图像居下),compound=’center’(文字覆盖在图片上),left,right,top略

    bitmap

    指定位图,如bitmap= bitmapimage(file = filepath)

    image

    button不仅可以显示文字,也可以显示图片,image= photoimage(file="../xxx/xxx.gif") ,目前仅支持gif,pgm,ppm格式的图片

    focus_set

    设置当前得到的焦点

    master

    代表了父窗口

    bg

    背景色,如bg=”red”,bg="#ff56ef"

    fg

    前景色,如fg=”red”,fg="#ff56ef"

    font

    字体及大小,如font=("arial", 8),font=("helvetica 16 bold italic")

    height

    设置显示高度、如果未设置此项,其大小以适应内容标签

    relief

    指定外观装饰边界附近的标签,默认是平的,可以设置的参数:flat、groove、raised、ridge、solid、sunken

    width

    设置显示宽度,如果未设置此项,其大小以适应内容标签

    wraplength

    将此选项设置为所需的数量限制每行的字符,数默认为0

    state

    设置组件状态;正常(normal),激活(active),禁用(disabled)

    anchor

    设置button文本在控件上的显示位置,可用值:n(north),s(south),w(west),e(east),和ne,nw,se,sw

    textvariable

    设置button与textvariable属性

    bd

    设置button的边框大小;bd(bordwidth)缺省为1或2个像素

    以下是button常用的函数

    方法

    描述

    flash()

    flash the button. this method redraws the button several times, alternating between active and normal appearance.

    invoke()

    invoke the command associated with the button.

    4. 一组实例

    实例1-创建按钮

    from tkinter import*

    #初始化tk()

    mywindow = tk()

    #设置标题

    mywindow.title('python gui learning')

    #创建两个按钮

    b1=button(mywindow, text='button1',bg="red", relief='raised', width=8, height=2)

    b1.grid(row=0, column=0, sticky=w, padx=5,pady=5)

    b2=button(mywindow, text='button2', font=('helvetica 10 bold'),width=8, height=2)

    b2.grid(row=0, column=1, sticky=w, padx=5, pady=5)

    #进入消息循环

    mywindow.mainloop()

    运行结果:

    实例2-创建按钮并绑定响应函数,输入半径,计算圆面积并输出。

    from tkinter import*

    def printinfo():

    #清理entry2

    entry2.delete(0, end)

    #根据输入半径计算面积

    r=int(entry1.get())

    s= 3.1415926*r*r

    entry2.insert(10, s)

    #清空entry2控件

    entry1.delete(0, end)

    #初始化tk()

    mywindow = tk()

    #设置标题

    mywindow.title('python gui learning')

    #标签控件布局

    label(mywindow, text="input").grid(row=0)

    label(mywindow, text="output").grid(row=1)

    #entry控件布局

    entry1=entry(mywindow)

    entry2=entry(mywindow)

    entry1.grid(row=0, column=1)

    entry2.grid(row=1, column=1)

    #quit按钮退出;run按钮打印计算结果

    button(mywindow, text='quit', command=mywindow.quit).grid(row=2, column=0, sticky=w, padx=5,pady=5)

    button(mywindow, text='run', command=printinfo).grid(row=2, column=1, sticky=w, padx=5, pady=5)

    #进入消息循环

    mywindow.mainloop()

    运行结果:

    输入半径12

    点击按钮“run”,输出结果

    点击按钮“quit”退出

    如您对本文有疑问或者有任何想说的,请点击进行留言回复,万千网友为您解惑!

    展开全文
  • 实现效果:输入一个视频,对视频中的喵酱...face_recognition是一个强大、简单、易上手的人脸识别开源项目,输入一张图像就可以确定人脸的位置。关于face_recognition的更多内容可以了解https://github.com/ageitgey/

    实现效果:写一个图形界面,实现输入一个视频,对视频中的人脸进行捕捉并输出。
    在这里插入图片描述

    技术基础

    本文技术基础将分为三个部分介绍:

    用途
    opencv 视频处理模块
    face_recognition 人脸识别模块
    tkinter 窗口视窗设计模块

    1.face_recognition

    face_recognition是一个强大、简单、易上手的人脸识别开源项目,输入一张图像就可以确定人脸的位置。关于face_recognition的更多内容可以了解https://github.com/ageitgey/face_recognition

    下载

    以下是我亲自尝试过的face_recognition库下载方法,都成功安装了:

    • win10:最开始直接import face_recognition报错,发现Building wheel for dlib报错,也就是dlib的问题。然后pip install dlib仍然报错。发现和我的3.6版本有冲突。于是找到Windows系统安装dlib可直接在网站https://pypi.org/simple/dlib/ 下载3.6版本对应的whl文件,用pip安装。就是下载这个xxx.whl到一个目录,然后cd/d 该目录,pip install xxx.whl安装成功。再次pip install face_recognition即可。
    • linux: 首先安装cmake
    sudo wget  https://cmake.org/files/v3.9/cmake-3.9.0-rc5.tar.gz -O cmake.tar.gz
    sudo tar -xvf cmake.tar.gz
    cd cmake-3.9.0-rc5/
    sudo chmod +x bootstrap
    sudo ./bootstrap
    sudo make
    sudo make install
    

    安装好cmake后,输入

    cmake -version
    

    查看cmake版本是否安装成功。然后安装git来手动安装dlib

     git clone https://github.com/davisking/dlib.git
     cd dlib
    mkdir build
    cd build
    cmake ..
    

    最后安装face_recognition。

    2.Opencv

    Python的cv2库是一个在计算机视觉领域应用非常广泛的库,Python对于视频的读取、处理很多使用cv2库实现。

    了解、安装cv2库可以参考Py之cv2:cv2库(OpenCV,opencv-python)的简介、安装、使用方法(常见函数、方法等)最强详细攻略。在处理图像方面,cv2和其他几种常见的库例如PIL的用法很不一样,可以查看我的另一篇文章可以上Python PIL、cv2、Dataloader、plt读取/显示图像数据集对比实例

    v2使用有一些坑,例如三个通道的顺序是BGR而不是RGB,有时会报奇怪的错误其实就是图像路径没写对,等等。

    3.tkinter

    我们可以用GUI 实现很多直观的功能,比如想开发一个计算器,如果只是一个程序输入,输出窗口的话,是没用用户体验的。所有开发一个图像化的小窗口,就是必要的。

    Tkinter 就是使用 python 进行窗口视窗设计的模块。Tkinter模块(“Tk 接口”)是Python的标准Tk GUI工具包的接口。

    作为 python 特定的GUI界面,是一个图像的窗口,tkinter是python 自带的,不需要另外下载。
    参考:Python GUI之tkinter窗口视窗教程大集合(看这篇就够了)

    实现

    以下给出本文的主要代码,完整代码见我的Github: GUI for video_face_recognition

    视频处理部分

    这一部分主要使用cv2库实现。
    读取视频:

    self.cap = cv2.VideoCapture(self.filename)  
    

    读取fps每秒传输帧数、视频时长(帧总数)

    self.fps = self.cap.get(cv2.CAP_PROP_FPS)
    self.total = int(self.cap.get(cv2.CAP_PROP_FRAME_COUNT))
    

    设定从视频的第几帧开始读取

    self.cap.set(cv2.CAP_PROP_POS_FRAMES, self.start)
    

    如果视频是竖着拍的,在cv2读取进去以后仍然是横向的,所以在人脸识别之前,需要旋转一下。(当然喵酱这些视频都是横着拍的就不用旋转了)
    旋转图像代码:

    ##旋转图像
    def rotate_bound(image,angle):
        #获取图像的尺寸
        #旋转中心
        (h,w) = image.shape[:2]
        (cx,cy) = (w/2,h/2)
        
        #设置旋转矩阵
        M = cv2.getRotationMatrix2D((cx,cy),-angle,1.0)
        cos = np.abs(M[0,0])
        sin = np.abs(M[0,1])
        
        # 计算图像旋转后的新边界
        nW = int((h*sin)+(w*cos))
        nH = int((h*cos)+(w*sin))
        
        # 调整旋转矩阵的移动距离(t_{x}, t_{y})
        M[0,2] += (nW/2) - cx
        M[1,2] += (nH/2) - cy
        
        return cv2.warpAffine(image,M,(nW,nH))
    

    读取视频的每一帧图像:

    ret, frame = self.cap.read()#frame(720, 1280, 3)BGR            
    if not ret:##视频读取结束,退出
        break
    
    ## 旋转图片,否则是横过来的
    if self.rotate == 1:
        frame = rotate_bound(frame,90)
    

    由于喵酱的视频尺寸比较大,需要缩小尺寸。
    然后转成RGB通道。在显示之前还要再转回BGR去。

    ## 缩放
    frame = cv2.resize(frame, (1200, 800))
    ## BGR到RGB
    frame = cv2.cvtColor(frame,cv2.COLOR_BGR2RGB)
    

    然后是辅助功能:在图像上显示当前帧在整个视频上的时间进展

    #计算当前时间进度
    now_seconds=int(self.cnt/self.fps%60)
    now_minutes=int(self.cnt/self.fps/60)
    total_second=int(self.total /self.fps%60)
    total_minutes=int(self.total/self.fps/60)
    #   { <参数序号> : <填充> <对齐)> <宽度> <,> <.精度> <类型>}.
    time_now_vs_total="Time:{:>3}:{:>02}|{:>3}:{:0>2}".format(now_minutes,now_seconds,total_minutes,total_second)
    # 输出到画面上
    font = cv2.FONT_HERSHEY_DUPLEX
    cv2.putText(img, time_now_vs_total, (10, 50), font, 1.0, (255, 255, 255), 1)
    
    

    人脸识别部分

    对于视频场景的人脸识别代码在github上是开源的https://github.com/ageitgey/face_recognition/blob/master/examples/facerec_from_webcam_faster.py,所以选择性的copy就可以了。

    首先,对于一帧图像,找到脸的位置

    face_locations = face_recognition.face_locations(frame)
    

    然后用蓝色框标记出来就ok了

    for (top,right,bottom,left) in face_locations:
        frame = cv2.rectangle(frame, (left, top), (right, bottom), (0, 0, 255), 2)
    

    窗口视窗设计部分

    GUI功能:

    • 对竖着拍的视频,需要进行翻转
    • 对于尺寸过大的视频,需要缩小尺寸显示
    • 对于过长的视频,可以支持从任意一帧开始读取
    • 支持隔帧保存输出图像

    使用:

    • 点击‘选择视频文件’选择视频文件
    • 设置相关参数
    • 点击‘播放’
    • 按q(英文输入法)退出

    我们的窗口设计如下:

    图形大小、标题

    root = Tk()
    root.geometry('250x150+200+200')
    root.title('视频人脸识别 1.0')
    

    Label:

    Label(root,text = '当前播放:').grid(row = 0,sticky = W)
    Label(root,text = '按q退出当前视频').grid(row = 6,column = 0,sticky = W)
    Label(root,text = '按空格暂停').grid(row = 6,column = 1,sticky = W)
    

    两个文本框:

    Label(root,text = '保存帧间隔').grid(row = 3,column = 0) 
    skip_entry = Entry(root)
    skip_entry['width'] = 10
    skip_entry.insert(0,10) ##每10次保存一张图像
    skip_entry.grid(row = 3,column = 1)
     
    Label(root,text = '从第几帧读取').grid(row = 4,column = 0) 
    start_entry = Entry(root)
    start_entry['width'] = 10
    start_entry.insert(0,1) ##每10次保存一张图像
    start_entry.grid(row = 4,column = 1)
    

    两个Checkbutton:

    v = IntVar()
    v.set(1)
    Checkbutton(root,text = '翻转',variable = v,onvalue=1,offvalue=0).grid(row = 5,column = 0) 
    
    v2 = IntVar()
    v2.set(1)
    Checkbutton(root,text = '需要缩放尺寸',variable = v2,onvalue=1,offvalue=0).grid(row = 5,column = 1) 
    

    三个Button

    Button(root,text = '选择视频文件',command = selectpath).grid(row = 2,column = 0,sticky = W)
    Button(root,text = '帮助',background = 'yellow',command = helpful).grid(row = 2,column = 1,sticky = E)
    Button(root,text = '播放',background = 'red',command = thread).grid(row = 2,column = 1,sticky = W)
    

    初次了解tkinter,欢迎各位指教。
    参考:
    https://www.cnblogs.com/mengd/p/7287119.html
    Python Tkinter模块详解(后续持续补充)
    【Python-opencv3.4】视频基本操作(帧率,总视频帧数、从第N帧开始播放、播放进度显示、按键控制视频)

    展开全文
  • 本文目录: ...4、完整代码    ---------------------------------------------------------------------/ 正文 /---------------------------------------------------------------------...

    本文目录:

    1、最终效果

    2、GUI编写

    3、回调函数说明

    4、完整代码

     

               ---------------------------------------------------------------------/ 正文 /---------------------------------------------------------------------

    1、最终效果图

                      

    如图所示,这个计算器要实现最普通的四则混合运算和带括号的计算

    同时,我们可以自己设置小彩蛋或者表白语,如果你想来一个出其不意的表白或者吐槽,可以试试看哦

     

    2、GUI编写

    2.1 tkinter概述

    2.2 各部分编写过程

    这个GUI很简单,主要可以分为三部分:

    • 主窗口    
    • 用于显示算式与计算结果的Label(其实就是现实计算器的显示屏)  
    •  按钮

    2.2.1 主窗口编写

    import tkinter as TK
    # 主窗口
    root = TK.Tk( )                     # 创建TK实例
    root.title("King's Caculator")      # 设置窗口的显示名字
    root.resizable(0,0)                 # 设置主窗口的宽度和高度是否可以通过鼠标进行拉伸改变,此处设置为不能            
    root.geometry('320x420')            # 这里设置主窗口的初始尺寸,因为我们在上面设定了主窗口大小  不可变,因此这个尺寸也就是主窗口一直不变的尺寸了
    
    (# 此处继续编写其他GUI部分或者回调函数)
    
    root.mainloop( )                    # 在编写完所有的GUI与相关函数后,我们要让这个窗口不断的循环,做成一直显示的效果,如果没有这一行,主窗口会出现一瞬间然后消失,像是程序没有运行一样 

     

    2.2.2 用于显示算式与计算结果的Label

    result = TK.StringVar( )               # 用来显示结果的可变文本
    equation = TK.StringVar( )             # 用来显示算式的可变文本
    result.set(' ')                        # 赋初始值
    equation.set('0')                      # 赋初始值
    
    
    # 结果显示框
    show_uresult = TK.Label(root,bg='white',fg = 'black',font =('Arail','15'),bd='0',textvariable =equation,anchor='se')       
    show_dresult = TK.Label(root,bg='white',fg = 'black',font = ('Arail','30'),bd='0',textvariable=result,anchor='se')
    show_uresult.place(x='10',y='10',width='300',height='50')
    show_dresult.place(x='10',y='60',width='300',height='50')

    这里我们使用的是tkinter模块15个主要控件里面的Label控件,然后在Lable上面显示文本

    因为我们的文字是需要根据用户的输入随时发生改变,因此文字要使用StringVar变量,而不要使用普通的字符串

    虽然显示效果上是一个Lable,但其实是两个Lable,这样子可以单独设置算式文本和结果文本的字体大小颜色等,以作区别,当然你也可以设置为一个大Lable,然后分别显示。

    2.2.3 按钮

    # 按钮
    # 第一行按钮
    button_back =TK.Button(root,text='←',bg='DarkGray',command=back)
    button_back.place(x = '10',y='150',width = '60',height='40')
    button_lbracket=TK.Button(root,text='(',bg='DarkGray',command= lambda : getnum('('))
    button_lbracket.place(x = '90',y='150',width = '60',height='40')
    button_rbracket=TK.Button(root,text=')',bg='DarkGray',command= lambda : getnum(')'))
    button_rbracket.place(x = '170',y='150',width = '60',height='40')
    button_division =TK.Button(root,text='÷',bg='DarkGray',command= lambda : getnum('÷'))
    button_division.place(x = '250',y='150',width = '60',height='40')
    # 第二行按钮
    button_7 =TK.Button(root,text='7',bg='DarkGray',command= lambda : getnum('7'))
    button_7.place(x = '10',y='205',width = '60',height='40')
    button_8 =TK.Button(root,text='8',bg='DarkGray',command= lambda : getnum('8'))
    button_8.place(x = '90',y='205',width = '60',height='40')
    button_9 =TK.Button(root,text='9',bg='DarkGray',command= lambda : getnum('9'))
    button_9.place(x = '170',y='205',width = '60',height='40')
    button_multiplication =TK.Button(root,text='X',bg='DarkGray',command= lambda : getnum('x'))
    button_multiplication.place(x = '250',y='205',width = '60',height='40')
    # 第三行按钮
    button_4 =TK.Button(root,text='4',bg='DarkGray',command= lambda : getnum('4'))
    button_4.place(x = '10',y='260',width = '60',height='40')
    button_5 =TK.Button(root,text='5',bg='DarkGray',command= lambda : getnum('5'))
    button_5.place(x = '90',y='260',width = '60',height='40')
    button_6 =TK.Button(root,text='6',bg='DarkGray',command= lambda : getnum('6'))
    button_6.place(x = '170',y='260',width = '60',height='40')
    button_minus =TK.Button(root,text='—',bg='DarkGray',command= lambda : getnum('-'))
    button_minus.place(x = '250',y='260',width = '60',height='40')
    # 第四行按钮
    button_1 =TK.Button(root,text='1',bg='DarkGray',command= lambda :getnum('1'))
    button_1.place(x = '10',y='315',width = '60',height='40')
    button_2 =TK.Button(root,text='2',bg='DarkGray',command= lambda : getnum('2'))
    button_2.place(x = '90',y='315',width = '60',height='40')
    button_3 =TK.Button(root,text='3',bg='DarkGray',command= lambda : getnum('3'))
    button_3.place(x = '170',y='315',width = '60',height='40')
    button_plus =TK.Button(root,text='+',bg='DarkGray',command= lambda : getnum('+'))
    button_plus.place(x = '250',y='315',width = '60',height='40')
    # 第五行按钮
    button_MC =TK.Button(root,text='MC',bg='DarkGray',command = clear)
    button_MC.place(x = '10',y='370',width = '60',height='40')
    button_0 =TK.Button(root,text='0',bg='DarkGray',command= lambda : getnum('0'))
    button_0.place(x = '90',y='370',width = '60',height='40')
    button_point =TK.Button(root,text='.',bg='DarkGray',command= lambda : getnum('.'))
    button_point.place(x = '170',y='370',width = '60',height='40')
    button_equal=TK.Button(root,text='=',bg='DarkGray',command= run)
    button_equal.place(x = '250',y='370',width = '60',height='40')
    

    注意按钮的command参数,这是回调函数,当这个按钮被按下时,回调函数被自动调用,用lambda函数是为了可以传参数给回调函数,否则无法传参。

    3、回调函数说明

    本程序的回调函数一共有4个

    • 按下数字按钮或者四则运算按钮或括号按钮    getnum( )
    • 按下退格按钮    def back( )
    • 按下MC按钮     def clear( )
    • 按下等号按钮   def run( )

    3.1 按下数字按钮或者四则运算按钮或括号按钮    getnum( )

    def getnum(num):
        temp = equation.get( )
        temp2 = result.get( )
        print(temp)
        print(temp2)
        if temp2 != ' ' :
            temp = '0'
            temp2 = ' '
            result.set(temp2)
        if (temp=='0'):
            temp = ''
        temp = temp + num
        equation.set( temp )
        print(equation)

    要考虑两个状态,状态一是结果文本为空,说明还没有进行过计算或者 按下了MC键,这时候输入什么都增加进算式文本,状态二是结果文本不为空, 说明刚进行完一次计算,要开始下一次计算,这时把算式文本和结果文本先初始化,或者再添加用户的新输入。(算式文本初始值是0,当用户输入第一个按钮时记得先把0去掉,否则会出现‘07+9’这类情况出现)

    3.2 按下退格按钮    def back( )

    # 按下退格键时,去除最后一个字符
    def back( ):
        temp = equation.get( )
        equation.set(temp[:-1])

     3.3 按下MC按钮     def clear( )

    # 按下MC时,清空算式行与结果行
    def clear( ):
        equation.set('0')
        result.set(' ')

     3.4 按下等号按钮   def run( )

    # 按下等于号时计算结果
    def run( ):
        temp = equation.get( )
        temp = temp.replace('x','*')             # 为了方便后续调用caculator函数进行运算,因此进行符号处理
        temp = temp.replace('÷','/')             # 为了方便后续调用caculator函数进行运算,因此进行符号处理
        # 写一个小彩蛋,可以用于表白哦
        if temp == '5+2+0+1+3+1+4':               # 暗号
            result.set('xxx我爱你')               # 彩蛋或者表白语
            return 0
        print(temp)
        answer = caculator.caculator(temp)
        answer = '%.2f'%answer                   # 设定结果的小数点个数,可自定义
        result.set(str(answer))

     当按下等于号时,计算算式结果并显示出来

    answer = caculator.caculator(temp)

     这个函数请参见本人上一篇博客 https://blog.csdn.net/a971956955/article/details/81489914

    或者直接使用python自带的 eval()  函数进行计算

     4、完整代码

    import tkinter as TK
    
    #若调用 eval()函数进行计算结果,把下面这一小段代码去掉
    
    #########################################################
    
    import os,sys
    BASE_DIR = os.path.dirname(os.path.dirname(__file__))
    sys.path.append(BASE_DIR)
    
    from caculate import caculator
    
    ##########################################################
    
    # 主窗口
    root = TK.Tk( )
    root.title("King's Caculator")
    root.resizable(0,0)
    root.geometry('320x420')
    
    result = TK.StringVar( )
    equation = TK.StringVar( )
    result.set(' ')
    equation.set('0')
    
    # 获得按下的数字或者符号
    def getnum(num):
        temp = equation.get( )
        temp2 = result.get( )
        print(temp)
        print(temp2)
        if temp2 != ' ' :
            temp = '0'
            temp2 = ' '
            result.set(temp2)
        if (temp=='0'):
            temp = ''
        temp = temp + num
        equation.set( temp )
        print(equation)
    
    # 按下退格键时,去除最后一个字符
    def back( ):
        temp = equation.get( )
        equation.set(temp[:-1])
    
    # 按下MC时,清空算式行与结果行
    def clear( ):
        equation.set('0')
        result.set(' ')
    
    # 按下等于号时计算结果
    def run( ):
        temp = equation.get( )
        temp = temp.replace('x','*')
        temp = temp.replace('÷','/')
        # 写一个小彩蛋,可以用于表白哦
        if temp == '5+2+0+1+3+1+4':               # 暗号
            result.set('xxx我爱你')               # 彩蛋或者表白语
            return 0
        print(temp)
        answer = caculator.caculator(temp)
        answer = '%.2f'%answer
        result.set(str(answer))
    
    
    # 结果显示框
    show_uresult = TK.Label(root,bg='white',fg = 'black',font = ('Arail','15'),bd='0',textvariable =equation,anchor='se')
    show_dresult = TK.Label(root,bg='white',fg = 'black',font = ('Arail','30'),bd='0',textvariable=result,anchor='se')
    show_uresult.place(x='10',y='10',width='300',height='50')
    show_dresult.place(x='10',y='60',width='300',height='50')
    
    # 按钮
    # 第一行按钮
    button_back =TK.Button(root,text='←',bg='DarkGray',command=back)
    button_back.place(x = '10',y='150',width = '60',height='40')
    button_lbracket=TK.Button(root,text='(',bg='DarkGray',command= lambda : getnum('('))
    button_lbracket.place(x = '90',y='150',width = '60',height='40')
    button_rbracket=TK.Button(root,text=')',bg='DarkGray',command= lambda : getnum(')'))
    button_rbracket.place(x = '170',y='150',width = '60',height='40')
    button_division =TK.Button(root,text='÷',bg='DarkGray',command= lambda : getnum('÷'))
    button_division.place(x = '250',y='150',width = '60',height='40')
    # 第二行按钮
    button_7 =TK.Button(root,text='7',bg='DarkGray',command= lambda : getnum('7'))
    button_7.place(x = '10',y='205',width = '60',height='40')
    button_8 =TK.Button(root,text='8',bg='DarkGray',command= lambda : getnum('8'))
    button_8.place(x = '90',y='205',width = '60',height='40')
    button_9 =TK.Button(root,text='9',bg='DarkGray',command= lambda : getnum('9'))
    button_9.place(x = '170',y='205',width = '60',height='40')
    button_multiplication =TK.Button(root,text='X',bg='DarkGray',command= lambda : getnum('x'))
    button_multiplication.place(x = '250',y='205',width = '60',height='40')
    # 第三行按钮
    button_4 =TK.Button(root,text='4',bg='DarkGray',command= lambda : getnum('4'))
    button_4.place(x = '10',y='260',width = '60',height='40')
    button_5 =TK.Button(root,text='5',bg='DarkGray',command= lambda : getnum('5'))
    button_5.place(x = '90',y='260',width = '60',height='40')
    button_6 =TK.Button(root,text='6',bg='DarkGray',command= lambda : getnum('6'))
    button_6.place(x = '170',y='260',width = '60',height='40')
    button_minus =TK.Button(root,text='—',bg='DarkGray',command= lambda : getnum('-'))
    button_minus.place(x = '250',y='260',width = '60',height='40')
    # 第四行按钮
    button_1 =TK.Button(root,text='1',bg='DarkGray',command= lambda :getnum('1'))
    button_1.place(x = '10',y='315',width = '60',height='40')
    button_2 =TK.Button(root,text='2',bg='DarkGray',command= lambda : getnum('2'))
    button_2.place(x = '90',y='315',width = '60',height='40')
    button_3 =TK.Button(root,text='3',bg='DarkGray',command= lambda : getnum('3'))
    button_3.place(x = '170',y='315',width = '60',height='40')
    button_plus =TK.Button(root,text='+',bg='DarkGray',command= lambda : getnum('+'))
    button_plus.place(x = '250',y='315',width = '60',height='40')
    # 第五行按钮
    button_MC =TK.Button(root,text='MC',bg='DarkGray',command = clear)
    button_MC.place(x = '10',y='370',width = '60',height='40')
    button_0 =TK.Button(root,text='0',bg='DarkGray',command= lambda : getnum('0'))
    button_0.place(x = '90',y='370',width = '60',height='40')
    button_point =TK.Button(root,text='.',bg='DarkGray',command= lambda : getnum('.'))
    button_point.place(x = '170',y='370',width = '60',height='40')
    button_equal=TK.Button(root,text='=',bg='DarkGray',command= run)
    button_equal.place(x = '250',y='370',width = '60',height='40')
    
    
    root.mainloop( )

     Github地址:https://github.com/better-king/caculator

    展开全文
  • Python Tkinter 之Frame控件(Python GUI 系列4)

    万次阅读 多人点赞 2018-04-22 13:06:15
    本章介绍Tkinter的Frame控件,本文是Python GUI系列的第4篇文章,整个系统约20篇博客,将全面的介绍Python Tkinter常用控件,最后还将基于Tkinter搭建两个比较完整的小项目。 2. 环境信息 **********************...
  • 项目最终效果见本人b站投稿av81480858简介...其中1234分别对应本项目教程每一部分的最终代码,所以想看完整代码直接看004.py就好。本文已录制视频教程上传b站:https://www.bilibili.com/video/av81480858。视频...
  • 初探在Pycharm中使用QT开发GUI页面,组件安装配置以及一个完整项目目录QT and PyQt5 介绍安装创建一个完整项目使用QTDesigner设计UI界面编写py文件来组合UI界面跟业务逻辑将py文件打包成exe程序 目录 由于项目要求...
  • Python Tkinter 之Button控件(Python GUI 系列6)

    万次阅读 多人点赞 2018-05-05 00:01:56
    本章介绍Tkinter的Button控件,本文是Python GUI系列的第6篇文章,整个系统约20篇博客,将全面的介绍Python Tkinter常用控件,最后还将基于Tkinter搭建两个比较完整的小项目。 2. 环境信息 *******************...
  • 本章介绍Tkinter的Listbox控件,本文是Python GUI系列的第12篇文章,整个系统约20篇博客,将全面的介绍Python Tkinter常用控件,最后还将基于Tkinter搭建两个比较完整的小项目。 2. 环境信息 *******************...
  • 本章介绍Tkinter的Radiobutton控件,本文是Python GUI系列的第8篇文章,整个系统约20篇博客,将全面的介绍Python Tkinter常用控件,最后还将基于Tkinter搭建两个比较完整的小项目。 2. 环境信息 ***************...
  • 本章介绍Tkinter的Entry控件,本文是Python GUI系列的第5篇文章,整个系统约20篇博客,将全面的介绍Python Tkinter常用控件,最后还将基于Tkinter搭建两个比较完整的小项目。 2. 环境信息 **********************...
  • 本章介绍Tkinter的Checkbutton控件,本文是Python GUI系列的第7篇文章,整个系统约20篇博客,将全面的介绍Python Tkinter常用控件,最后还将基于Tkinter搭建两个比较完整的小项目。 2. 环境信息 ***************...
  • 本章介绍Tkinter的Scrollbar控件,本文是Python GUI系列的第13篇文章,整个系统约20篇博客,将全面的介绍Python Tkinter常用控件,最后还将基于Tkinter搭建两个比较完整的小项目。 2. 环境信息 *****************...
  • 本章介绍Tkinter的Message控件,本文是Python GUI系列的第10篇文章,整个系统约20篇博客,将全面的介绍Python Tkinter常用控件,最后还将基于Tkinter搭建两个比较完整的小项目。 2. 环境信息 *******************...
  • 本章介绍Tkinter常用的15种控件,如按钮,标签和文本框,本文是Python GUI系列的第2篇文章,整个系统约20篇博客,将全面的介绍Python Tkinter常用控件,最后还将基于Tkinter搭建两个比较完整的小项目。 2. 环境...
  • 本章介绍Tkinter的Lable控件,本文是Python GUI系列的第3篇文章,整个系统约20篇博客,将全面的介绍Python Tkinter常用控件,最后还将基于Tkinter搭建两个比较完整的小项目。 2. 环境信息 **********************...
  • 本章介绍Tkinter的Menu控件,本文是Python GUI系列的第9篇文章,整个系统约20篇博客,将全面的介绍Python Tkinter常用控件,最后还将基于Tkinter搭建两个比较完整的小项目。 2. 环境信息 **********************...
  • 本章介绍Tkinter的Text控件,本文是Python GUI系列的第15篇文章,整个系统约20篇博客,将全面的介绍Python Tkinter常用控件,最后还将基于Tkinter搭建两个比较完整的小项目。 2. 环境信息 **********************...
  • 序言 本章介绍Tkinter的事件关联,本文是Python GUI系列的第14篇文章,整个系统约20篇博客,将全面的介绍Python Tkinter常用控件,最后还将基于Tkinter搭建两个比较完整的小项目。2. 环境信息********************...
  • 序言 本章介绍Tkinter的Canvas控件,本文是Python GUI系列的第11篇文章,整个系统约20篇博客,将全面的介绍Python Tkinter常用控件,最后还将基于Tkinter搭建两个比较完整的小项目。2. 环境信息******************...
  • Python Tkinter 之窗口创建与布局(Python GUI 系列1)

    万次阅读 多人点赞 2018-04-22 11:28:07
    本文是Python GUI系列的第一篇文章,整个系统约20篇博客,将全面的介绍Python Tkinter常用控件,最后还将基于Tkinter搭建两个比较完整的小项目。 做为Python开发者,用户图形界面(GUI)是开发是必备技能之一。目前...
  • 本教程为我在b站投稿的视频教程av81480858 对应的文字版,项目最终效果见投稿简介部分,视频部分讲解的...其中1234分别对应本项目教程每一部分的最终代码,所以想看完整代码直接看004.py就好。本项目通过python自带...
  • 序言本章介绍Tkinter的Lable控件,本文是Python GUI系列的第3篇文章,整个系统约20篇博客,将全面的介绍Python Tkinter常用控件,最后还将基于Tkinter搭建两个比较完整的小项目。2. 环境信息**********************...
  • Django和Python完整课程,包含完整的真实世界项目Django和python捆绑包:从学习python的所有基本知识到高级python到UI Design TKINTER,再到Django目标了解编程基础学习Python编程语言了解Django和Bootstrap框架为...
  • 第1章 绪论1.1 题目来源本课题来源于计算机网络实践与应用课程的创新型实验,题目为“TCP和UDP数据流的带宽竞争分析”。实验的主要目的是通过编程实现多进程TCP和UDP数据传输模块,编写...1.2 项目意义在实际应用中...
  • 本教程为我在b站投稿的视频教程av81480858 对应的文字版,项目最终效果见投稿简介部分,视频部分讲解的比较...其中1234分别对应本项目教程每一部分的最终代码,所以想看完整代码直接看004.py就好。 本项目通过pyt...
  • #_*_ coding:utf-8 _*_from tkinter import *importrandomimporttimeimporttkinter.messagebox#俄罗斯方块界面的高度HEIGHT = 20#俄罗斯方块界面的宽度WIDTH = 10ACTIVE= 1PASSIVE=0TRUE= 1FALSE=0style=[[[(0,0),(0...
  • 本文旨在抛砖引玉,以实例的开发过程,让读者完整的了解程序开发各个环节。 实例项目的效果及功能简介 实例项目的效果及功能简介 1、自动拉取百度知道,个人中心的待回答问题列表。并且在发现有新问题的时候...

空空如也

空空如也

1 2 3
收藏数 52
精华内容 20
关键字:

tkinter完整项目