Frage

I'm attempting to make a wx.Panel derived class that will display rotated text. However, the moment this widget is added to a wx.Sizer, the text no longer displays. When it is added directly to a wx.Frame, the text displays but is truncated. What am I doing wrong?

import wx

class Win(wx.Frame):
    def __init__(self):
        super(Win, self).__init__(None, wx.ID_ANY)
        self.p = wx.Panel(self, wx.ID_ANY)
        self.p.SetSizer(wx.BoxSizer())
        self.rt = RotatedText(self.p, wx.ID_ANY, 'hello', 90)
        self.p.GetSizer().Add(self.rt)


class RotatedText(wx.Window):
    def __init__(self, parent, id, text, angle, font=None, *args, **kwargs):
        super(RotatedText, self).__init__(parent, id, *args, **kwargs)
        self.text = text
        self.font = font
        self.angle = angle
        self.Bind(wx.EVT_PAINT, self.OnPaint)
        self.Bind(wx.EVT_SIZE, self.OnSize)

    def repaint(self, dc):
        if self.font:
            dc.SetFont(self.font)
        text_height, text_width = dc.GetTextExtent(self.text)
        dc.SetTextForeground(wx.BLACK)
        dc.DrawText(self.text, 0, 0)

    def OnPaint(self, event):
        dc = wx.PaintDC(self)
        self.repaint(dc)
        event.Skip()

    def OnSize(self, event):
        dc = wx.ClientDC(self)
        self.repaint(dc)
        event.Skip()

app = wx.App()
win = Win()
win.Show()
app.MainLoop()

Note that I use dc.DrawText() instead of dc.DrawRotatedText() since I'm attempting to reduce the problem down to it's simplest form. Eventually, I do wish to use dc.DrawRotatedText().

War es hilfreich?

Lösung

When creating your custom window give it an explicit size. I've included an example below.

What is happening is since the custom window doesn't have any controls associated it with it the sizer is assuming it is empty and "squishing" it to as small a size as possible (probably 0,0).

I also added the draw rotated text method call and some arbitrary sizes. You can of course play around with those until it suits your needs.

import wx

class Win(wx.Frame):
    def __init__(self):
        super(Win, self).__init__(None, wx.ID_ANY)
        self.p = wx.Panel(self, wx.ID_ANY)
        self.p.SetSizer(wx.BoxSizer())
        # set the minimum size when creating the custom window so that the sizer doesn't "squash" it to 0,0
        self.rt = RotatedText(self.p, wx.ID_ANY, 'hello', 90,size=(60,60))
        self.p.GetSizer().Add(self.rt)


class RotatedText(wx.Window):
    def __init__(self, parent, id, text, angle, font=None, *args, **kwargs):
        super(RotatedText, self).__init__(parent, id, *args, **kwargs)
        self.text = text
        self.font = font
        self.angle = angle
        self.Bind(wx.EVT_PAINT, self.OnPaint)
        self.Bind(wx.EVT_SIZE, self.OnSize)

        # set our minimum size based on the text with
        dc = wx.MemoryDC()
        self.text_width, self.text_height= dc.GetTextExtent(self.text)
        # height and width are reversed since we are drawing text vertically
        self.SetMinSize((self.text_height,self.text_width)) 

    def repaint(self, dc):
        if self.font:
            dc.SetFont(self.font)
        text_width, text_height = dc.GetTextExtent(self.text)
        dc.SetTextForeground(wx.BLACK)
        #dc.DrawText(self.text, 0, 0) # change this line to start drawing from bottom to top beginning 60 units from top
        dc.DrawRotatedText(self.text, 0, self.text_width, self.angle)

    def OnPaint(self, event):
        dc = wx.PaintDC(self)
        self.repaint(dc)
        event.Skip()

    def OnSize(self, event):
        dc = wx.ClientDC(self)
        self.repaint(dc)
        event.Skip()

app = wx.App()
win = Win()
win.Show()
app.MainLoop()
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top