【问题标题】:How to fix pygame flicker如何修复pygame闪烁
【发布时间】:2019-06-08 23:31:48
【问题描述】:

所以我决定尝试在 pygame 中制作一个应用程序,因为它比 tkinter 更复杂(这也有助于我已经在使用其中的一些)并且我遇到了一个问题,即我的文本只有部分闪烁。 (不是屏幕上的所有文字,只是其中的一部分)

一些环境信息:我在 Windows 10 上运行 python 3.7 on atom。我已经尝试隔离问题,但无法找到问题的根源,我通过正常运行文件来检查它是否是原子,但这没有帮助。

import pygame
from winsound import Beep
from roundrects import aa_round_rect
from time import sleep, time
pygame.init()
pygame.font.init()
window_h = 725
window_w = 1300
bg_grey = (230, 230, 230)
button_grey = (190, 190, 190)
del_button_grey = (165, 165, 165)
white = (255, 255, 255)
black = (0, 0, 0)
normalfont = pygame.font.SysFont("Aileron", 30)
mediumfont = pygame.font.SysFont("Aileron", 60)
largefont = pygame.font.SysFont("Aileron", 70)
window = pygame.display.set_mode((window_w, window_h))
morse_keystrokes = []
class Button: # this class will be used to draw and interact with a Button.
    def __init__(self, x, y, w, h, color, border=0, round=False, text=None, Font=mediumfont, Font_Color=black):
        self.x = x
        self.y = y
        self.w = w
        self.h = h
        self.color = color
        self.border = border
        self.round = round
        self.text = text
        self.Font = Font
        self.Font_Color = Font_Color
        self.draw()
    def draw(self):
        if self.round == False:
            if self.border != 0:
                pygame.draw.rect(window, self.color, (self.x, self.y, self.w, self.h))
                pygame.draw.rect(window, black, (self.x, self.y, self.w, self.h), self.border)
                pygame.display.update()
            else:
                pygame.draw.rect(window, self.color, (self.x, self.y, self.w, self.h))
                pygame.display.update()
        elif self.round == True:
            if self.border != 0:
                aa_round_rect(window, (self.x, self.y, self.w, self.h), black, 30, self.border, self.color)
                pygame.display.update()
            else:
                aa_round_rect(window, (self.x, self.y, self.w, self.h), self.color, 30)
                pygame.display.update()
        if self.text != None:
            self.draw_text()

    def clicked(self):
        mouse = pygame.mouse.get_pos()
        if self.x + self.w > mouse[0] > self.x and self.y + self.h > mouse[1] > self.y:
            return True
        else:
            return False

    def draw_text(self):
        Label(self.text, self.x, self.y, self.w, self.h, self.Font, self.Font_Color)


class Typing_Box:
    def __init__(self, x, y, w, h, color, dbc, border=0, font=normalfont, typing_font=mediumfont, font_color=black):
        self.x = x
        self.y = y
        self.w = w
        self.h = h
        self.color = color
        self.dbc = dbc #delete button color
        self.border = border
        self.font = font
        self.typing_font = typing_font
        self.font_color = font_color
        self.draw()

    def draw(self):
        if self.border != 0:
            pygame.draw.rect(window, self.color, (self.x, self.y, self.w, self.h))
            pygame.draw.rect(window, black, (self.x, self.y, self.w, self.h), self.border)
            pygame.draw.rect(window, self.dbc, ((window_w-self.x)-(self.w/15), self.y, self.w/15, self.h))
            pygame.draw.rect(window, black, ((window_w-self.x)-(self.w/15), self.y, self.w/15, self.h), self.border)
        else:
            pygame.draw.rect(window, self.color, (self.x, self.y, self.w, self.h))
            pygame.draw.rect(window, self.dbc, ((window_w-self.x)-(self.w/15), self.y, self.w/15, self.h))
        Label("DEL", self.x, self.y, self.w, self.h, self.font, self.font_color, (((window_w-self.x)-(self.w/15)+((self.w/15)/2)), (self.y+(self.h/2))))
        Label("".join(morse_keystrokes), self.x, self.y, self.w, self.h, self.font, self.font_color, ((self.x+((self.w/2)-(self.w/15)+35)), (self.y+(self.h/2)-10)))

    def update(self):
        if self.border != 0:
            pygame.draw.rect(window, self.color, (self.x, self.y, self.w, self.h))
            pygame.draw.rect(window, black, (self.x, self.y, self.w, self.h), self.border)
            pygame.draw.rect(window, self.dbc, ((window_w-self.x)-(self.w/15), self.y, self.w/15, self.h))
            pygame.draw.rect(window, black, ((window_w-self.x)-(self.w/15), self.y, self.w/15, self.h), self.border)
        else:
            pygame.draw.rect(window, self.color, (self.x, self.y, self.w, self.h))
            pygame.draw.rect(window, self.dbc, ((window_w-self.x)-(self.w/15), self.y, self.w/15, self.h))
        Label("DEL", self.x, self.y, self.w, self.h, self.font, self.font_color, (((window_w-self.x)-(self.w/15)+((self.w/15)/2)), (self.y+(self.h/2))))
        Label("".join(morse_keystrokes), self.x, self.y, self.w, self.h, self.typing_font, self.font_color, ((self.x+((self.w/2)-(self.w/15)+35)), (self.y+(self.h/2)-10)))

    def clicked(self):
        mouse = pygame.mouse.get_pos()
        if ((window_w-self.x)-(self.w/15)) + self.w > mouse[0] > ((window_w-self.x)-(self.w/15)) and self.y + self.h > mouse[1] > self.y:
            return True
        else:
            return False


class Label:
    def __init__(self, msg, x, y, w, h, font, font_color=black, alternate_center=None):
        self.msg = msg
        self.x = x
        self.y = y
        self.w = w
        self.h = h
        self.font = font
        self.font_color = font_color
        self.alternate_center = alternate_center
        self.draw()

    def render(self):
        textsurface = self.font.render(self.msg, True, self.font_color)
        return textsurface, textsurface.get_rect()

    def draw(self):
        textsurf, textrect = self.render()
        if self.alternate_center == None:
            textrect.center = ((self.x+(self.w/2)-3), (self.y+(self.h/2)))
        else:
            textrect.center = self.alternate_center
        window.blit(textsurf, textrect)
        pygame.display.update()


def Play_Beep(Type, box):
    if Type == 1:
        morse_keystrokes.append(".")
        box.update()
        Beep(800, 300)
    elif Type == 2:
        morse_keystrokes.append("_")
        box.update()
        Beep(800, 600)

def first_screen():
    window.fill(bg_grey)
    dit = Button(20, 40, 450, 250, button_grey, 2, True, "Dit")
    da = Button(20, 370, 450, 250, button_grey, 2, True, "Da")
    first_box = Typing_Box(150, 667, 1000, 55, button_grey, del_button_grey, 2)
    back = Button(-2, 677, 80, 50, button_grey, 2, False, "Back", normalfont)
    run = True
    while run:
        first_box.update()
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                quit()
            if event.type == pygame.MOUSEBUTTONDOWN:
                if dit.clicked():
                    Play_Beep(1, first_box)
                elif da.clicked():
                    Play_Beep(2, first_box)
                elif first_box.clicked():
                    start = time()
                    global morse_keystrokes
                    morse_keystrokes = morse_keystrokes[:-1]

first_screen()

任何帮助将不胜感激, TIA

【问题讨论】:

  • 请考虑创建minimal reproducible example 来展示您的问题。这将使人们更容易帮助您解决问题。我还建议重新排列您的代码,以便您的主循环遵循句柄事件⇒更新状态⇒绘制屏幕设计模式。

标签: python python-3.x windows pygame flicker


【解决方案1】:

感谢您的帮助,但事实证明我正在更新屏幕一帧。

【讨论】:

    【解决方案2】:

    这些文章会很有帮助。

    Flickering dice image when i press my dice button.

    Python Tkinter refresh canvas

    以下是对 tkinter 问题的回答,但与 pygame 问题的回答类似。我会引用这个,因为它似乎更简洁。

    刷新画布的唯一方法是让事件循环为“重绘”事件提供服务。在您的循环中,您永远不会给事件循环更新的机会,因此您看不到任何更改。

    快速解决方法是致电self.canvas.update_idletasks,但这只是一种技巧,并不是正确的解决方案。

    制作动画的正确方法是使用事件循环进行迭代。为此,您可以将要完成的工作放在一个队列中——在本例中为空闲事件队列。您可以使用after 命令将内容放在此队列中。

    你应该做的是编写一个函数来对你的动画进行一次迭代。本质上,把你的 while 循环中的所有东西都移到一个函数中。然后,只要有工作要做,就安排该函数不断被调用。您可以在该函数中调用after,也可以使用单独的函数来控制动画。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-10
      • 2013-05-28
      相关资源
      最近更新 更多