WX.Statictext更新使用Whitespace较慢?

发布于 2025-02-11 04:26:23 字数 4981 浏览 3 评论 0原文

我正在写一个简单的 roguelike 在Python 3.10中适当的软件体系结构原理。我正在使用WXPYTHON310(4.1.2A2)。

该地图是播放器可能穿越的单元格的八角形网格。我的地图是wx.statictext,它会在每个用户输入后更新。我将其设置为double Buffered,根据建议,我找到了在这里。它的工作真的很好。

最近,我开始实施视野机制,该领域的机制使瓷砖(网格单元)在附近的周围环境之外返回“战争雾”角色,并且只有一旦玩家接近,才显示其实际角色表示(播放器表示为'@'角色):

我注意到,如果我继续握住移动箭头,则wx.statictext在发布之前不会更新。禁用双扣显然会纠正该行为,但使屏幕非常眨眼(如它,它很快闪烁)。更有趣的是,我注意到wx.statictext如果“战争”角色是某个实际角色,而不仅仅是whitespace (以下内容示例,一个下划线):

”在此处输入图像描述”

好像wxstatictext在有大量空间时更新速度较慢,但​​是如果有一个合适的字符,请更快地更新。

我的可重复性。示例代码:

import wx


class MyFrame(wx.Frame):
    def __init__(self, *args, **kwargs):
        super().__init__(None, *args, **kwargs)
        self.Title = 'Stackoverflow example'
        self.SetSize(width=1480, height=600)

        self.panel = MainPanel(self)
        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.panel,1, wx.EXPAND)
        self.SetSizer(sizer)
        self.Center()
        self.Layout()
        self.Show()


class MainPanel(wx.Panel):
    def __init__(self, parent, *args, **kwargs):
        super().__init__(parent, *args, **kwargs)

        self.mymap = MyMap()
        self.x = -1
        self.moveRight = True

        self.SetDoubleBuffered(True)

        font = wx.Font(9, wx.DEFAULT, wx.NORMAL, wx.DEFAULT)
        font.SetFaceName('Courier New')
        self.ST = wx.StaticText(self, label=self.Display(), style=wx.ALIGN_LEFT)
        self.ST.SetFont(font)

        self.Bind(wx.EVT_KEY_DOWN, self.EvaluateCommand)

    def EvaluateCommand(self,e):
        key = e.GetKeyCode()
        if key == 78: # n for newbie!
            self.MoveRectangleOnAMap()
            self.ST.SetLabel(self.Display())
        elif key == wx.WXK_ESCAPE:
            quit()

    def MoveRectangleOnAMap(self):
        all_tiles = self.mymap.FindRectangleOfTiles((0, 0), (self.mymap.width, self.mymap.height))
        for tile in all_tiles:
            tile.SetDisplayToDormant()

        if self.moveRight:
            self.x += 1
            if self.x == self.mymap.width - 15:
                self.moveRight = False
        else:
            self.x -= 1
            if self.x == 0:
                self.moveRight = True

        rectangle = self.mymap.FindRectangleOfTiles((self.x, 10), (self.x + 15, 25))
        for tile in rectangle:
            tile.SetDisplayToActive()

    def Display(self):
        width = self.mymap.width
        height = self.mymap.height
        text = ''

        for y in range(0,height):
            line = ''
            for x in range(0,width):
                line += self.mymap.FindTileFromCoords((x,y)).display
            text += line + '\n'

        return text


class Tile():
    def __init__(self,coords):
        self.coords = coords
        self.SetDisplayToDormant()

    def SetDisplayToActive(self):
        self.display = ' '

    def SetDisplayToDormant(self):
        self.display = '#'


class MyMap():
    def __init__(self):
        self.tiles = dict()
        self.width = 200
        self.height = 35

        for x in range(0,self.width):
            self.tiles[str(x)] = dict()
            for y in range(0,self.height):
                self.tiles[str(x)][str(y)]= Tile((x,y))

    def FindTileFromCoords(self,coords):
        coord_x, coord_y = coords
        return self.tiles[str(coord_x)][str(coord_y)]

    def FindRectangleOfTiles(self,coords_up_left, coords_down_right):
        coords_up_left_x, coords_up_left_y = coords_up_left
        coords_down_right_x, coords_down_right_y = coords_down_right
        tiles = []

        for x in range(coords_up_left_x,coords_down_right_x):
            for y in range(coords_up_left_y,coords_down_right_y):
                tiles.append(self.FindTileFromCoords((x,y)))

        return tiles


app = wx.App()
frame = MyFrame()
app.MainLoop()

如果我执行此代码,然后按键盘上的“ n”(n for newbie!),则矩形以良好而稳定的方式移动。如果您在tile类中切换字符...:

class Tile():
    def __init__(self,coords):
        self.coords = coords
        self.SetDisplayToDormant()

    def SetDisplayToActive(self):
        self.display = '#'

    def SetDisplayToDormant(self):
        self.display = ' '

...并再次按住'n',则stalitctext标签在发布键之前不会更新。

有人可以向我解释为什么这是吗?是否有一些明智的方法来绕过这个问题?

I'm writing a simple roguelike in Python 3.10 as a way to learn the language as well as principles of proper software architecture. I'm using wxPython310 (4.1.2a2).

The map is an octagonal grid of cells that player may traverse. My map is a wx.StaticText that updates once every user input. I set it to DoubleBuffered, as per advice I found here. It works really nice.

Recently I started implementing field of vision mechanics that makes tiles (grid cells) outside of player's nearby surroundings return 'fog of war' character and only display their actual character representation once a player approaches (the player is denoted as '@' character):

The player is @ character.

I noticed that if I keep holding a move arrow, the wx.StaticText doesn't update until I release it. Disabling DoubleBuffered obviously corrects that behaviour, but makes the screen very blinky (as in, it flickers very rapidly). What's more interesting, I noticed that the wx.StaticText updates correctly and quickly if a 'fog of war' character is some actual character, rather than just whitespace (in the following example, an underscore):

enter image description here

It's as if wxStaticText updated slower when there's plenty of whitespace, but quicker if there's a proper character.

My reproducible example code:

import wx


class MyFrame(wx.Frame):
    def __init__(self, *args, **kwargs):
        super().__init__(None, *args, **kwargs)
        self.Title = 'Stackoverflow example'
        self.SetSize(width=1480, height=600)

        self.panel = MainPanel(self)
        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.panel,1, wx.EXPAND)
        self.SetSizer(sizer)
        self.Center()
        self.Layout()
        self.Show()


class MainPanel(wx.Panel):
    def __init__(self, parent, *args, **kwargs):
        super().__init__(parent, *args, **kwargs)

        self.mymap = MyMap()
        self.x = -1
        self.moveRight = True

        self.SetDoubleBuffered(True)

        font = wx.Font(9, wx.DEFAULT, wx.NORMAL, wx.DEFAULT)
        font.SetFaceName('Courier New')
        self.ST = wx.StaticText(self, label=self.Display(), style=wx.ALIGN_LEFT)
        self.ST.SetFont(font)

        self.Bind(wx.EVT_KEY_DOWN, self.EvaluateCommand)

    def EvaluateCommand(self,e):
        key = e.GetKeyCode()
        if key == 78: # n for newbie!
            self.MoveRectangleOnAMap()
            self.ST.SetLabel(self.Display())
        elif key == wx.WXK_ESCAPE:
            quit()

    def MoveRectangleOnAMap(self):
        all_tiles = self.mymap.FindRectangleOfTiles((0, 0), (self.mymap.width, self.mymap.height))
        for tile in all_tiles:
            tile.SetDisplayToDormant()

        if self.moveRight:
            self.x += 1
            if self.x == self.mymap.width - 15:
                self.moveRight = False
        else:
            self.x -= 1
            if self.x == 0:
                self.moveRight = True

        rectangle = self.mymap.FindRectangleOfTiles((self.x, 10), (self.x + 15, 25))
        for tile in rectangle:
            tile.SetDisplayToActive()

    def Display(self):
        width = self.mymap.width
        height = self.mymap.height
        text = ''

        for y in range(0,height):
            line = ''
            for x in range(0,width):
                line += self.mymap.FindTileFromCoords((x,y)).display
            text += line + '\n'

        return text


class Tile():
    def __init__(self,coords):
        self.coords = coords
        self.SetDisplayToDormant()

    def SetDisplayToActive(self):
        self.display = ' '

    def SetDisplayToDormant(self):
        self.display = '#'


class MyMap():
    def __init__(self):
        self.tiles = dict()
        self.width = 200
        self.height = 35

        for x in range(0,self.width):
            self.tiles[str(x)] = dict()
            for y in range(0,self.height):
                self.tiles[str(x)][str(y)]= Tile((x,y))

    def FindTileFromCoords(self,coords):
        coord_x, coord_y = coords
        return self.tiles[str(coord_x)][str(coord_y)]

    def FindRectangleOfTiles(self,coords_up_left, coords_down_right):
        coords_up_left_x, coords_up_left_y = coords_up_left
        coords_down_right_x, coords_down_right_y = coords_down_right
        tiles = []

        for x in range(coords_up_left_x,coords_down_right_x):
            for y in range(coords_up_left_y,coords_down_right_y):
                tiles.append(self.FindTileFromCoords((x,y)))

        return tiles


app = wx.App()
frame = MyFrame()
app.MainLoop()

If I execute this code and press and hold 'n' on keyboard (n for newbie!), the rectangle moves in nice and steady fashion. If you switch around the characters in Tile class...:

class Tile():
    def __init__(self,coords):
        self.coords = coords
        self.SetDisplayToDormant()

    def SetDisplayToActive(self):
        self.display = '#'

    def SetDisplayToDormant(self):
        self.display = ' '

... and hold 'n' again, the StaticText label won't update until you release the key.

Could someone explain to me why that is? And is there some smart way to circumvent that problem?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

百变从容 2025-02-18 04:26:23

WXSTATICTEXT实际上并不是要有效地更新大量文本。您需要实现自己的窗口,这些窗口只需重新绘制真正需要更改的部分。

wxStaticText is really not meant to be used for efficiently updating large blobs of text. You need to implement your own window that would redraw just the parts of it that really need to be changed.

近箐 2025-02-18 04:26:23

1。将Whitespace切换到没有破裂的空格。

as vz。 ``真的是用来更新文本的大斑点。但是,他还提到wxstatictext中的单词包裹是这种口吃行为的可能罪魁祸首。这让我想到,如果这是引起它的单词包装,我该如何规避它?好吧,事实证明,将标准的空格字符(u+0020)切换到无爆破的空间(u+00A0)确实使小部件更新更加流畅!在我可重复的代码示例中,这特别是微不足道的,因为Python 3+使所有字符串UTF-8编码:

class Tile():
    def __init__(self,coords):
        self.coords = coords
        self.SetDisplayToDormant()

    def SetDisplayToActive(self):
        self.display = '#'

    def SetDisplayToDormant(self):
        self.display = '\u00a0'

2。使用genStatictExt而不是。

使用wx.lib.stattext.genstatictext而不是wxstatictext可能也更明智。

1. Switch whitespace to no-break whitespace.

As VZ. mentioned, wxStaticText aren't really meant to be used to update big blobs of text. However, he also mentioned that the word wrapping in wxStaticText is a probable culprit for this stuttery behaviour. This got me thinking, if that's word wrapping that's causing it, how may I circumvent it? Well, it turns out that switching a standard whitespace character (U+0020) to a no-break space (U+00A0) indeed makes the widget updates much more smooth! In my reproducible code example, it's especially trivial, since Python 3+ makes all strings utf-8 encoded:

class Tile():
    def __init__(self,coords):
        self.coords = coords
        self.SetDisplayToDormant()

    def SetDisplayToActive(self):
        self.display = '#'

    def SetDisplayToDormant(self):
        self.display = '\u00a0'

2. Use GenStaticText instead.

It turns out using wx.lib.stattext.GenStaticText instead of wxStaticText also seems to correct the issue and is probably also way more sensible.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文