2016-06-21 5 views
-2

Я написал программу в C++ с использованием wxwidgets.Я поместил прямоугольник на изображение и хочу выбрать часть изображения, покрытую прямоугольником, для которого прямоугольник следует перетаскивать. Но проблема в том, что когда я нажимаю кнопку мыши, изображение исчезает, и остается только прямоугольник (который можно перетащить), и это происходит наоборот.Выберите область из изображения с помощью перетаскиваемого прямоугольника с помощью wxwidget в 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

Не копируйте здесь весь свой код. То, что вы попробовали, упомянуто здесь. Кроме того, будьте конкретны, задавая свой вопрос. –

+0

Вы рисуете растровое изображение в родительском фрейме, но вы не указываете, чтобы родительский фрейм перерисовывал. Я думаю, что разделение кода рисования между родительским и дочерним окнами в лучшем случае даст вам изворотливые результаты. –

+0

На самом деле это мое первое сообщение, поэтому я не знал о многом. Во всяком случае, то, что вы сказали о родительском фрейме, нужно перерисовать, вот что я не могу сделать. Если вы можете мне что-то помочь! –

ответ

0

Есть несколько вещей, чтобы объяснить, для того, чтобы ответить на этот вопрос, так что я буду принимать их по одному за раз. Я думаю, что ваша основная идея в порядке, поэтому я не буду подробно разбираться в том, как должен происходить фактический выбор и т. Д.

Во-первых, я бы рекомендовал использовать либо Connect(), либо Bind() вместо таблицы событий. Это позволяет подключать дочерние окна к родительскому окну и обрабатывать их все в одном месте.

Например, если ваш основной класс кадра называется MainFrame и у вас есть wxPanel член называется m_DrawPanel, в MainFrame CTOR вы могли бы:

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; 
} 

Примечание: Я включил переопределение wxEVT_ERASE_BACKGROUND события, потому что в противном случае панели как правило, очищаются, что приводит к мерцанию (это простой подход).

обработчики событий 3 мыши могут реализовать логику выбора (я думаю, что это в основном то, что вы намерены уже):

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(); 
} 

Как уже упоминалось ранее, переопределить wxEVT_ERASE_BACKGROUND событие на панели в ничего не делать:

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

Наконец, я думаю, что это немного, что вы действительно спрашиваете в вашем вопросе (я включил другие, чтобы помочь вам построить рабочую программу):

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); 
    } 
} 

Это обработчик события рисования, поэтому сначала нам нужно создать контекст wxPaintDC. Затем мы рисуем растровое изображение, это гарантирует, что он обновляется каждый раз и не повреждается движением мыши, изменением размера или другими перетаскиваемыми окнами и т. Д. Наконец, если пользователь в данный момент перемещает мышь с нажатой левой кнопкой, затем нарисуйте прямоугольник выделения ,

Есть много других способов достижения того же. Некоторые из них, возможно, лучше или эффективнее, однако это простой рабочий процесс, пока вы не познакомитесь с wxWidgets.

+0

Я рад, что смог решить мою проблему только из-за вас. Я очень благодарен за услугу. –

+0

@diptisharma Если вы хотите сказать «спасибо», проголосовать или [принять] (http://stackoverflow.com/help/accepted-answer) ответ этого человека или просто оплатить его, предоставив отличный ответ кому-либо другой вопрос.Далее читайте: [Что делать, если кто-то отвечает на мой вопрос?] (Http://stackoverflow.com/help/someone-answers) –

+0

@diptisharma, вам очень приятно, рад помочь. Если вы нашли, что мой ответ будет правильным, пожалуйста, вы можете [принять] (http://stackoverflow.com/help/accepted-answer), спасибо, спасибо! – iwbnwif

 Смежные вопросы

  • Нет связанных вопросов^_^