WX.Statictext更新使用Whitespace较慢?
我正在写一个简单的 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):
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):
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 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
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.1。将Whitespace切换到没有破裂的空格。
as vz。 ``真的是用来更新文本的大斑点。但是,他还提到
wxstatictext
中的单词包裹是这种口吃行为的可能罪魁祸首。这让我想到,如果这是引起它的单词包装,我该如何规避它?好吧,事实证明,将标准的空格字符(u+0020
)切换到无爆破的空间(u+00A0
)确实使小部件更新更加流畅!在我可重复的代码示例中,这特别是微不足道的,因为Python 3+使所有字符串UTF-8编码: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 inwxStaticText
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:2. Use
GenStaticText
instead.It turns out using
wx.lib.stattext.GenStaticText
instead ofwxStaticText
also seems to correct the issue and is probably also way more sensible.