wxwidgets自定义按键大小能获取wxpoint里的值但无法控制按键位置,如何解决?

想获取wxpoint里的值来画矩形以改变按键位置,但是呈现的效果不太正常,输出了一下获取的值,发现与我设置的值是一样的,但不知道为什么画出来是这样的,不知道哪里除了问题,希望大家能指点我如何解决,谢谢!

#include 
#include 
#include 

using namespace std;

class wxCustomButton : public wxWindow
{

    bool pressedDown;
    wxString text;
    int height;
    int width;
    int x;
    int y;

public:

    wxCustomButton(wxFrame* parent, wxString text, wxSize size, wxPoint add);

    void paintEvent(wxPaintEvent & evt);
    void paintNow();

    void render(wxDC& dc);

    // some useful events
    void mouseMoved(wxMouseEvent& event);
    void mouseDown(wxMouseEvent& event);
    void mouseWheelMoved(wxMouseEvent& event);
    void mouseReleased(wxMouseEvent& event);
    void rightClick(wxMouseEvent& event);
    void mouseLeftWindow(wxMouseEvent& event);
    void keyPressed(wxKeyEvent& event);
    void keyReleased(wxKeyEvent& event);

    DECLARE_EVENT_TABLE()
};


BEGIN_EVENT_TABLE(wxCustomButton, wxPanel)

    EVT_MOTION(wxCustomButton::mouseMoved)
    EVT_LEFT_DOWN(wxCustomButton::mouseDown)
    EVT_LEFT_UP(wxCustomButton::mouseReleased)
    EVT_RIGHT_DOWN(wxCustomButton::rightClick)
    EVT_LEAVE_WINDOW(wxCustomButton::mouseLeftWindow)
    EVT_KEY_DOWN(wxCustomButton::keyPressed)
    EVT_KEY_UP(wxCustomButton::keyReleased)
    EVT_MOUSEWHEEL(wxCustomButton::mouseWheelMoved)

    // catch paint events
    EVT_PAINT(wxCustomButton::paintEvent)

END_EVENT_TABLE()



wxCustomButton::wxCustomButton(wxFrame* parent, wxString text, wxSize size, wxPoint add) :
 wxWindow(parent, wxID_ANY)
{
   this->height = size.GetHeight();
   this->width = size.GetWidth();
   SetMinSize( wxSize(width, height) );

   this->x = add.x;
   this->y = add.y;

   this->text = text;
   pressedDown = false;
}

void wxCustomButton::paintEvent(wxPaintEvent & evt)
{
    wxPaintDC dc(this);
    render(dc);
}

void wxCustomButton::paintNow()
{
    wxClientDC dc(this);
    render(dc);
}

void wxCustomButton::render(wxDC&  dc)
{
   if (pressedDown)
       dc.SetBrush( *wxRED_BRUSH );
   else
       dc.SetBrush( *wxGREY_BRUSH );
   cout << "x:" << x << endl;
   cout << "y:" << y << endl;
   cout << endl;
   cout << "w:" << width << endl;
   cout << "h:" << height << endl;
   cout << endl;
   SetPosition( wxPoint(x,y) );
   dc.DrawRectangle( x, y, width, height );

   dc.DrawText( text, 20, 15 );
}

void wxCustomButton::mouseDown(wxMouseEvent& event)
{
    pressedDown = true;
    paintNow();
}
void wxCustomButton::mouseReleased(wxMouseEvent& event)
{
    pressedDown = false;
    paintNow();

    wxMessageBox( wxT("You pressed a custom button") );
}
void wxCustomButton::mouseLeftWindow(wxMouseEvent& event)
{
    if (pressedDown)
    {
        pressedDown = false;
        paintNow();
    }
}

// currently unused events
void wxCustomButton::mouseMoved(wxMouseEvent& event) {}
void wxCustomButton::mouseWheelMoved(wxMouseEvent& event) {}
void wxCustomButton::rightClick(wxMouseEvent& event) {}
void wxCustomButton::keyPressed(wxKeyEvent& event) {}
void wxCustomButton::keyReleased(wxKeyEvent& event) {}

class MyApp: public wxApp
{

    wxFrame *frame;
    wxCustomButton* m_btn_1;
    wxCustomButton* m_btn_2;
    wxCustomButton* m_btn_3;

public:

    bool OnInit()
    {
        wxInitAllImageHandlers();
        frame = new wxFrame(NULL, wxID_ANY, wxT("Hello wxDC"), wxPoint(50,50), wxSize(800,600));

        m_btn_1 = new wxCustomButton( frame, wxT("My Custom Button 11"), wxSize(150, 50), wxPoint(0, 0));
        m_btn_2 = new wxCustomButton( frame, wxT("Hello World!"), wxSize(150, 50), wxPoint(300, 300));

        frame->Show();
        return true;
    }

};

IMPLEMENT_APP(MyApp)


img

img

仅供参考:

"""
A simple sample of using a wx.Overlay to draw a rubberband effect
"""

#import numpy as np
import wx
print(wx.version())

class TestPanel(wx.Panel):
    def __init__(self, *args, **kw):
        wx.Panel.__init__(self, *args, **kw)

        self.Bind(wx.EVT_PAINT   , self.OnPaint    )
        self.Bind(wx.EVT_LEFT_UP , self.OnLeftUp   )
        self.Bind(wx.EVT_RIGHT_UP, self.OnRightUp  )
        self.Bind(wx.EVT_MOTION  , self.OnMouseMove)

        self.startPos = None
        self.overlay = None
        self.bitmap = wx.Bitmap("D:\\test\\bk.jpg", wx.BITMAP_TYPE_ANY)

#       wx.TextCtrl(self, pos=(140,20))
        self.state=0
        self.polygons = [] # List of polygons
        self.points = [] # List of points defining our polygon

    def OnPaint(self, evt):
        # Just some simple stuff to paint in the window for an example
        dc = wx.PaintDC(self)
        dc.DrawBitmap(self.bitmap,0,0)
#       print("in OnPaint,len(self.points):%d,len(self.polygons):%d" %(len(self.points),len(self.polygons)))
        if len(self.points)>=2:
            dc.SetPen(wx.Pen("black", 2))
            dc.SetBrush(wx.Brush(wx.Colour(0xC0, 0xC0, 0xC0, 0x80)))
            for i in range(len(self.points)-1):
                dc.DrawLine(self.points[i],self.points[i+1])
        if len(self.polygons)>0:
            transparent=True
            if not transparent:
                dc.SetPen(wx.Pen("black", 2))
                dc.SetBrush(wx.Brush(wx.Colour(0xFF, 0x00, 0x00, 0x80)))
                for poly in self.polygons:
                    dc.DrawPolygon(poly)
            else:
                gc = wx.GraphicsContext.Create(dc)
                if gc:
                    gc.SetBrush(wx.Brush(wx.Colour(0xFF, 0x00, 0x00, 0x80)))
                    path = gc.CreatePath()
                    for poly in self.polygons:
                        firstpt=True
                        for pt in poly:
                            if firstpt:
                                path.MoveToPoint(pt.x,pt.y)
                                firstpt=False
                            else:
                                path.AddLineToPoint(pt.x,pt.y)
                        path.CloseSubpath()
                    gc.FillPath(path)
                else:
                    print("Fail to wx.GraphicsContext.Create(dc)")

    def OnLeftUp(self, evt):
        if self.state==0:
            # Capture the mouse and save the starting posiiton for the
            # rubber-band
            self.CaptureMouse()
            self.startPos = evt.GetPosition()
            self.state=1
            self.overlay = wx.Overlay()
        elif self.state==1:
            self.points.append(self.startPos)
            self.points.append(evt.GetPosition())
            self.startPos = evt.GetPosition()
            self.state=2
            # When the mouse is released we reset the overlay and it
            # restores the former content to the window.
            self.overlay = wx.Overlay()
            dc = wx.ClientDC(self)
            odc = wx.DCOverlay(self.overlay, dc)
            odc.Clear()
            del odc
#           self.overlay.Reset()
            self.Refresh()
        elif self.state==2:
            self.points.append(evt.GetPosition())
            self.startPos = evt.GetPosition()
            # When the mouse is released we reset the overlay and it
            # restores the former content to the window.
            self.overlay = wx.Overlay()
            dc = wx.ClientDC(self)
            odc = wx.DCOverlay(self.overlay, dc)
            odc.Clear()
            del odc
#           self.overlay.Reset()
            self.Refresh()


    def OnMouseMove(self, evt):
        if self.state==1:
            # Draw the rubber-band rectangle using an overlay so it
            # will manage keeping the rectangle and the former window
            # contents separate.
#           self.overlay = wx.Overlay()
            dc = wx.ClientDC(self)
            odc = wx.DCOverlay(self.overlay, dc)
            odc.Clear()
            del odc

            # Mac's DC is already the same as a GCDC, and it causes
            # problems with the overlay if we try to use an actual
            # wx.GCDC so don't try it.
            if 'wxMac' not in wx.PlatformInfo:
                dc = wx.GCDC(dc)

            dc.SetPen(wx.Pen("black", 2))
            dc.SetBrush(wx.Brush(wx.Colour(0xC0, 0xC0, 0xC0, 0x80)))
#           rect = wx.Rect(self.startPos, evt.GetPosition())
#           dc.DrawRectangle(rect)
            dc.DrawLine(self.startPos, evt.GetPosition())
        elif self.state==2:
            # Draw the rubber-band rectangle using an overlay so it
            # will manage keeping the rectangle and the former window
            # contents separate.
#           self.overlay = wx.Overlay()
            dc = wx.ClientDC(self)
            odc = wx.DCOverlay(self.overlay, dc)
            odc.Clear()
            del odc

            # Mac's DC is already the same as a GCDC, and it causes
            # problems with the overlay if we try to use an actual
            # wx.GCDC so don't try it.
            if 'wxMac' not in wx.PlatformInfo:
                dc = wx.GCDC(dc)

            dc.SetPen(wx.Pen("black", 2))
            dc.SetBrush(wx.Brush(wx.Colour(0xC0, 0xC0, 0xC0, 0x80)))
#           rect = wx.Rect(self.startPos, evt.GetPosition())
#           dc.DrawRectangle(rect)
            dc.DrawLine(self.startPos, evt.GetPosition())


    def OnRightUp(self, evt):
        if self.HasCapture():
            self.ReleaseMouse()
        if self.state==2:
            print("Completing polygon with %d points." % len(self.points))
            if (len(self.points)>=3):
                self.points.append(self.points[0])
#               self.polygons.append(np.array([self.points]))
                self.polygons.append(self.points)
                self.state = 0
                self.points = []
            else:
                self.points = []
            self.Refresh()


app = wx.App(redirect=False)
frm = wx.Frame(None, title="wx.Overlay Test", size=(960+4,540+4))
#frm.SetDoubleBuffered(True)
pnl = TestPanel(frm)
frm.Show()
app.MainLoop()


不知道你这个问题是否已经解决, 如果还没有解决的话:

如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^