wxPython:wx.PyControl可以包含wx.Sizer吗?

发布于 2024-09-10 10:47:25 字数 1499 浏览 2 评论 0原文

wx.PyControl 可以包含 wx.Sizer 吗?

请注意,我最终想要在这里做的事情(具有浮点值的旋转器)已经在另一个问题中得到了回答。我对在 wx.PyControl 中布局小部件特别感兴趣,如果我需要制作自己的自定义小部件,这项技能可能会很有用。我已经通读了 CreatingCustomControls,但它没有在 wx.PyControl< 中使用 sizer /代码> 子类。

使用下面的代码,我的 CustomWidget 看起来不正确。我还没有做 DoGetBestSize 因为我认为这适用于 作用于小部件的 wx.Sizer。我实际上有一个wx.Sizer内部做它的事情CustomWidget

这是我的代码(没有子小部件之间的事件绑定):
编辑:这是我更正后的类代码,感谢史蒂文·斯普罗特

import wx

class CustomWidget(wx.PyControl):
  def __init__(self, parent):
    wx.PyControl.__init__(self, parent=parent, style=wx.NO_BORDER) # Style added.
    text = wx.TextCtrl(parent=self)
    spin = wx.SpinButton(parent=self, style=wx.SP_VERTICAL)
    sizer = wx.GridBagSizer()
    self.layout(text, spin, sizer)
    self.OnInit(text, sizer)

  def OnInit(self, text, sizer):
    text.SetValue(u"0.000")

  def layout(self, text, spin, sizer):
    self.SetSizer(sizer)
    sizer.Add(text, pos=(0, 0), flag=wx.ALIGN_CENTER)
    sizer.Add(spin, pos=(0, 1), flag=wx.ALIGN_CENTER)
    self.Fit()
    self.Layout() # This is what I lacked. I needed to call .Layout()
    self.CenterOnParent()

Can a wx.PyControl contain a wx.Sizer?

Note that what I am ultimately trying to do here (spinner with float values) is already answered in another question. I am particularly interested in layouting widgets within a wx.PyControl, a skill which might prove useful if I come across a need to make my own custom widgets. I already read through CreatingCustomControls, but it didn't use sizers within the wx.PyControl subclass.

Using my code below, my CustomWidget just doesn't look right. I'm not yet doing a DoGetBestSize because I think that applies to a wx.Sizer acting on a widget. I am actually having a wx.Sizer doing its thing inside a CustomWidget.

Here is my code (without the event bindings between sub-widgets):
EDIT: Here is my corrected class code, thanks to Steven Sproat:

import wx

class CustomWidget(wx.PyControl):
  def __init__(self, parent):
    wx.PyControl.__init__(self, parent=parent, style=wx.NO_BORDER) # Style added.
    text = wx.TextCtrl(parent=self)
    spin = wx.SpinButton(parent=self, style=wx.SP_VERTICAL)
    sizer = wx.GridBagSizer()
    self.layout(text, spin, sizer)
    self.OnInit(text, sizer)

  def OnInit(self, text, sizer):
    text.SetValue(u"0.000")

  def layout(self, text, spin, sizer):
    self.SetSizer(sizer)
    sizer.Add(text, pos=(0, 0), flag=wx.ALIGN_CENTER)
    sizer.Add(spin, pos=(0, 1), flag=wx.ALIGN_CENTER)
    self.Fit()
    self.Layout() # This is what I lacked. I needed to call .Layout()
    self.CenterOnParent()

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

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

发布评论

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

评论(2

南…巷孤猫 2024-09-17 10:47:25

是的,可以。您只需要调用 Layout() 来告诉 sizer 重新计算/布局其子项。

import wx

class Frame(wx.Frame):
  def __init__(self):
    wx.Frame.__init__(self, None)
    blah  = CustomWidget(self)
    self.Show(True)

class CustomWidget(wx.PyControl):
  def __init__(self, parent):
    wx.PyControl.__init__(self, parent=parent)
    text = wx.TextCtrl(parent=self)
    spin = wx.SpinButton(parent=self, style=wx.SP_VERTICAL)
    sizer = wx.GridBagSizer()
    self.layout(text, spin, sizer)
    self.OnInit(text, sizer)

  def OnInit(self, text, sizer):
    text.SetValue(u"0.000")

  def layout(self, text, spin, sizer):
    self.SetSizer(sizer)
    sizer.Add(text, pos=(0, 0), flag=wx.ALIGN_CENTER)
    sizer.Add(spin, pos=(0, 1), flag=wx.ALIGN_CENTER)
    self.Fit()
    self.Layout()
    self.CenterOnParent()

app = wx.App()
f = Frame()
app.MainLoop()

顺便说一下,如果你能像上面那样附加一个可运行的示例,那就太好了:)

Yes, it can. You just need to call Layout() to tell the sizer to recalculate/layout its children.

import wx

class Frame(wx.Frame):
  def __init__(self):
    wx.Frame.__init__(self, None)
    blah  = CustomWidget(self)
    self.Show(True)

class CustomWidget(wx.PyControl):
  def __init__(self, parent):
    wx.PyControl.__init__(self, parent=parent)
    text = wx.TextCtrl(parent=self)
    spin = wx.SpinButton(parent=self, style=wx.SP_VERTICAL)
    sizer = wx.GridBagSizer()
    self.layout(text, spin, sizer)
    self.OnInit(text, sizer)

  def OnInit(self, text, sizer):
    text.SetValue(u"0.000")

  def layout(self, text, spin, sizer):
    self.SetSizer(sizer)
    sizer.Add(text, pos=(0, 0), flag=wx.ALIGN_CENTER)
    sizer.Add(spin, pos=(0, 1), flag=wx.ALIGN_CENTER)
    self.Fit()
    self.Layout()
    self.CenterOnParent()

app = wx.App()
f = Frame()
app.MainLoop()

By the way, it would be nice in the future if you could attach a runnable sample as above :)

碍人泪离人颜 2024-09-17 10:47:25

由于从 wxControl 派生的类通常不用于包含其他小部件,因此不存在自动布局代码,因此当它获取 EVT_SIZE 事件时,它不会调用 Layout()。您可以通过 Bind()ing EVT_SIZE 的处理程序并从那里调用 self.Layout() 轻松地将这种功能添加到您的类中。然后,它的行为就像面板在获取大小事件并具有子项和大小调整器时所做的那样。

Since classes derived from wxControl are not normally used for containing other widgets the auto-layout code is not present and so it will not call Layout() when it gets the EVT_SIZE event. You can easily add that ability to your class by Bind()ing a handler for EVT_SIZE and calling self.Layout() from there. Then it will act just like a panel does when it gets the size event and has children and a sizer.

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