2016-06-21 10 views
-2

Ich habe ein Programm in C++ mit wxwidgets.Ich platziere ein Rechteck auf dem Bild und möchte den Teil des Bildes durch Rechteck, für das das Rechteck sollte ziehbar sein. Aber das Problem ist, wenn ich mit der Maus klicke verschwindet das Bild und das einzige Rechteck (das gezogen werden kann) bleibt und es passiert umgekehrt.Wählen Sie einen Bereich aus einem Bild mit einem ziehbaren Rechteck mit wxwidget in C++

`

class BasicDrawPane : public wxPanel 
{ 

public: 
    BasicDrawPane(); 
    BasicDrawPane(wxFrame* parent); 

    void paintEvent(wxPaintEvent & evt); 

    void render(wxDC& dc); 
    void mouseMoved(wxMouseEvent& event); 
    void mouseDown(wxMouseEvent& event); 
    void mouseWheelMoved(wxMouseEvent& event); 
    void mouseReleased(wxMouseEvent& event); 
    void rightClick(wxMouseEvent& event); 
    void mouseLeftWindow(wxMouseEvent& event); 
    DECLARE_EVENT_TABLE() 

}; 
class MyFrame: public wxFrame{ 
public: 
    MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size); 
    wxString path; 
    BasicDrawPane panel; 
private: 
    void OnHello(wxCommandEvent& event); 
    void OnExit(wxCommandEvent& event); 
    void OnAbout(wxCommandEvent& event); 
    void OnOpen(wxCommandEvent& event); 
    void OnPaint(wxCommandEvent& event); 
    void OnRect(wxCommandEvent& event); 
    void OnSave(wxCommandEvent& event); 

    DECLARE_EVENT_TABLE(); 

    wxBitmap bmp; 
    wxMemoryDC memDC; 
}; 

enum 
{ 
    ID_Hello = 1, ID_PAINT = 2, ID_RECT = 3, ID_SAVE = 4 

}; 
BEGIN_EVENT_TABLE(MyFrame, wxFrame) 
    EVT_MENU(ID_Hello,MyFrame::OnHello) 
    EVT_MENU(wxID_EXIT,MyFrame::OnExit) 
    EVT_MENU(wxID_ABOUT,MyFrame::OnAbout) 
    EVT_MENU(wxID_OPEN,MyFrame::OnOpen) 
    EVT_MENU(ID_PAINT,MyFrame::OnPaint) 
    EVT_MENU(ID_RECT,MyFrame::OnRect) 
    EVT_MENU(ID_SAVE,MyFrame::OnSave) 

END_EVENT_TABLE() 
void MyFrame::OnPaint(wxCommandEvent& event) 
{ 
    //wxPaintDC dc(this); 
    //dc.DrawBitmap(m_bitmap, 0, 0, true /* use mask */); 

    //wxStaticBitmap *b1 = new wxStaticBitmap(this, -1, wxBitmap(wxImage(path))); 



    bmp.LoadFile((path),wxBITMAP_TYPE_ANY); 
// bmp.LoadFile((path),wxBITMAP_TYPE_PNG); 

    memDC.SelectObject(bmp); 

    //memDC.SetBackground(*wxWHITE_BRUSH); 
    //memDC.Clear(); 
/* memDC.SetPen(*wxGREEN_PEN); 
    memDC.SetBrush(*wxTRANSPARENT_BRUSH); 
    memDC.DrawRectangle(m_x, m_y, WIDTH, HEIGHT);*/ 
    //Check(); 
    memDC.SelectObject(wxNullBitmap); 

    // wxSize sz(512,384); 
    // wxSize sz(900,600); 
    wxStaticBitmap *b1 = new wxStaticBitmap(/* dynamic_cast<wxFrame*>*/this, -1, bmp, wxDefaultPosition); 

    Refresh(); 

} 
class MyApp: public wxApp 
{ 
public: 
    virtual bool OnInit(); 
    //MyFrame *frame; 
    BasicDrawPane * drawPane; 
    }; 

IMPLEMENT_APP(MyApp) 


bool MyApp::OnInit() 
{ 
    // wxBoxSizer* sizer = new wxBoxSizer(wxHORIZONTAL); 
    //frame = new MyFrame((wxFrame *)NULL, -1, wxT("Hello wxDC"), wxPoint(50,50), wxSize(800,600)); 
    MyFrame *frame = new MyFrame(_T("Hello World"), wxPoint(50, 50), wxSize(600, 600)); 
// drawPane = new BasicDrawPane((wxFrame*) frame); 
    // sizer->Add(drawPane, 1, wxEXPAND); 

    //frame->SetSizer(sizer); 
// /* dynamic_cast<wxFrame*>(this)*/ frame-> SetAutoLayout(true); 
    /* dynamic_cast<wxFrame*>(this)*/frame -> Show(); 
    return true; 
} 

BEGIN_EVENT_TABLE(BasicDrawPane, wxPanel) 

EVT_MOTION(BasicDrawPane::mouseMoved) 
EVT_LEFT_DOWN(BasicDrawPane::mouseDown) 
EVT_LEFT_UP(BasicDrawPane::mouseReleased) 
EVT_RIGHT_DOWN(BasicDrawPane::rightClick) 
EVT_LEAVE_WINDOW(BasicDrawPane::mouseLeftWindow) 
EVT_MOUSEWHEEL(BasicDrawPane::mouseWheelMoved) 
EVT_PAINT(BasicDrawPane::paintEvent) 
// catch paint events 


END_EVENT_TABLE() 




void BasicDrawPane::mouseDown(wxMouseEvent& event) 
{ 
    /* if (event.GetPosition().x >= m_x && event.GetPosition().x <= m_x + WIDTH && 
     event.GetPosition().y >= m_y && event.GetPosition().y <= m_y + HEIGHT) 
    { 
     m_dragging = true; 
     m_previous_mouse_x = event.GetPosition().x; 
     m_previous_mouse_y = event.GetPosition().y; 
    }*/ 
} 
void BasicDrawPane::mouseWheelMoved(wxMouseEvent& event) {} 

void BasicDrawPane::mouseReleased(wxMouseEvent& event) 
{ 
    m_dragging = true; 
} 

void BasicDrawPane::mouseMoved(wxMouseEvent& event) 
{ 
    if (m_dragging && event.Dragging()) 
    { 
     int delta_x = event.GetPosition().x - m_previous_mouse_x; 
     int delta_y = event.GetPosition().y - m_previous_mouse_y; 

     m_x += delta_x; 
     m_y += delta_y; 

     m_previous_mouse_x = event.GetPosition().x; 
     m_previous_mouse_y = event.GetPosition().y; 
     // trigger paint event 
     Refresh(); 

    } 
} 

void BasicDrawPane::mouseLeftWindow(wxMouseEvent& event) 
{ 
    m_dragging = true; 
} 

void BasicDrawPane::rightClick(wxMouseEvent& event) {} 
BasicDrawPane::BasicDrawPane(wxFrame* parent) : 
wxPanel(parent) 
{ 
// m_dragging = true; 
// m_x = 100; 
// m_y = 100; 
} 

/* 
* Called by the system of by wxWidgets when the panel needs 
* to be redrawn. You can also trigger this call by 
* calling Refresh()/Update(). 
*/ 
void BasicDrawPane::paintEvent(wxPaintEvent & evt) 
{ 
//wxCommandEvent w1(wxEVT_NULL, ID_PAINT); 
    //OnPaint(w1); 
    wxPaintDC dc(this); 
    render(dc); 
} 


void BasicDrawPane::render(wxDC& dc) 
{ 
    dc.SetPen(*wxGREEN_PEN); 
    dc.SetBrush(*wxTRANSPARENT_BRUSH); 
    dc.DrawRectangle(m_x, m_y, WIDTH, HEIGHT); 
} 

` 
+4

Kopieren Sie nicht den gesamten Code hier. Was du versucht hast, hier erwähnt. Beziehen Sie sich auch auf Ihre Frage. –

+0

Sie zeichnen die Bitmap im übergeordneten Frame, aber Sie geben nicht an, dass der übergeordnete Frame neu gezeichnet werden soll. Ich denke, dass das Aufteilen des Zeichnungscodes zwischen dem Eltern- und dem Kindfenster bestenfalls zweifelhafte Ergebnisse bringt. –

+0

Eigentlich ist dies mein erster Beitrag, so dass mir viele Dinge als solche nicht bewusst waren. Wie auch immer, was du über den Elternrahmen gesagt hast, um neu gezeichnet zu werden, das ist die Sache, die ich nicht kann. Wenn du mir mit etwas helfen kannst !! –

Antwort

0

Es gibt mehrere Dinge, um zu erklären, diese Frage zu beantworten, also werde ich sie einer nach dem anderen nehmen. Ich denke, Ihre Grundidee ist in Ordnung, also werde ich nicht auf viele Details eingehen, wie die tatsächliche Auswahl stattfinden sollte usw.

Erstens würde ich empfehlen, entweder Connect() oder Bind() anstelle einer Ereignistabelle zu verwenden. Dadurch können Sie untergeordnete Fensterereignisse wieder mit dem übergeordneten Fenster verbinden und sie alle an einem Ort behandeln.

Zum Beispiel, wenn Ihre Hauptrahmenklasse MainFrame genannt wird, und Sie haben ein wxPanel Mitglied m_DrawPanel genannt, in dem Großrechner Ctor könnten Sie haben:

MainFrame::MainFrame(wxWindow* parent) 
{ 
    // Connect mouse event handlers. 
    m_DrawPanel->Connect(wxEVT_LEFT_DOWN, 
     wxMouseEventHandler(MainFrame::OnPanelLDown), NULL, this); 
    m_DrawPanel->Connect(wxEVT_LEFT_UP, 
     wxMouseEventHandler(MainFrame::OnPanelLUp), NULL, this); 
    m_DrawPanel->Connect(wxEVT_MOTION, 
     wxMouseEventHandler(MainFrame::OnPanelMotion), NULL, this); 

    // Connect paint and erase handlers. 
    m_DrawPanel->Connect(wxEVT_PAINT, 
     wxPaintEventHandler(MainFrame::OnPanelPaint), NULL, this); 
    m_DrawPanel->Connect(wxEVT_ERASE_BACKGROUND, 
     wxEraseEventHandler(MainFrame::OnPanelErase), NULL, this); 

    // Load the bitmap and set the mode to 'not currently selecting'. 
    m_Picture.LoadFile ("wxwidgets.png", wxBITMAP_TYPE_PNG); 
    m_SelectionMode = false; 
} 

Hinweis: I enthalten ein wxEVT_ERASE_BACKGROUND Ereignis überschreiben, da sonst Platten neigen dazu, gelöscht zu werden, was zu Flimmern führt (dies ist ein einfacher Ansatz).

Die 3 Maus-Event-Handler Ihre Auswahllogik implementieren können (ich denke, das ist im Grunde, was Sie beabsichtigen, bereits):

void MainFrame::OnPanelLDown(wxMouseEvent& event) 
{ 
    m_SelectionMode = true; 
    m_SelectionRect = wxRect(event.GetPosition(), wxSize(0, 0)); 
} 

void MainFrame::OnPanelLUp(wxMouseEvent& event) 
{ 
    m_SelectionMode = false; 

    // ... handle what to do with the selection here 
    // (selected area is defined by m_SelectionRect). 
    // ... 

    // Zero the selection rectangle for neatness (not really required). 
    m_SelectionRect = wxRect(); 
} 

void MainFrame::OnPanelMotion(wxMouseEvent& event) 
{ 
    m_SelectionRect = wxRect(m_SelectionRect.GetTopLeft(), event.GetPosition()); 

    // Call Refresh() to trigger a paint event. 
    m_mainPanel->Refresh(); 
} 

Wie bereits erwähnt, die wxEVT_ERASE_BACKGROUND Veranstaltung Panel außer Kraft setzen, nichts zu tun:

void MainFrame::OnPanelErase(wxEraseEvent& event) 
{ 
} 

Schließlich ich denke, das ist das Bit, das Sie wirklich in Ihrer Frage fragen (ich eingeschlossen, die andere zu helfen, ein Arbeitsprogramm erstellen):

void MainFrame::OnPanelPaint(wxPaintEvent& event) 
{ 
    // Obtain a wxPaintDC. 
    wxPaintDC pdc (m_mainPanel); 

    // Draw our image. 
    pdc.DrawBitmap(m_Picture, wxPoint(0, 0)); 

    // If the user is currently selecting (left mouse button is down) 
    // then draw the selection rectangle. 
    if (m_SelectionMode) 
    { 
     pdc.SetPen(*wxRED_PEN); 
     pdc.SetBrush(*wxTRANSPARENT_BRUSH); 
     pdc.DrawRectangle(m_SelectionRect); 
    } 
} 

Dies ist ein Paint-Event-Handler, also zuerst müssen wir einen wxPaintDC Kontext erstellen. Als nächstes malen wir die Bitmap, das stellt sicher, dass sie jedes Mal aktualisiert wird und nicht durch Mausbewegungen, Größenänderung oder andere Fenster usw. beschädigt wird. Wenn der Benutzer die Maus bei gedrückter linker Maustaste bewegt, zeichnen Sie das Auswahlrechteck .

Es gibt viele andere Möglichkeiten, dasselbe zu erreichen. Einige von ihnen sind möglicherweise besser oder effizienter, jedoch ist dies ein einfacher Arbeitsweg, bis Sie mit wxWidgets vertrauter werden.

+0

Ich bin froh, dass ich mein Problem nur wegen dir lösen konnte. Ich bin wirklich dankbar für den Gefallen. –

+0

@diptisharma Wenn Sie "Danke" sagen möchten, stimmen Sie ab oder [akzeptieren] (http://stackoverflow.com/help/accepted-answer) die Antwort dieser Person, oder zahlen Sie sie einfach weiter, indem Sie jemandem eine großartige Antwort geben die Frage von anderen.Weiter lesen: [Was soll ich tun, wenn jemand meine Frage beantwortet?] (Http://stackoverflow.com/help/someone-answers) –

+0

@diptissharma Sie sind sehr willkommen, glücklich zu helfen. Wenn Sie meine Antwort korrekt gefunden haben, können Sie bitte [akzeptieren] (http://stackoverflow.com/help/accepted-answer) es, danke! – iwbnwif

Verwandte Themen