wxWidgets:实现面板上对象的选择

问题描述 投票:0回答:1

我想通过允许用户使用鼠标创建一个矩形区域来实现对象选择。 我正在创建一个继承自

TPanel
的面板
wxWindow
来处理某些事件并执行重绘。 然后我向其中添加一个
wxWrapSizer* imageWrapper
,在其中添加
ImageContainer
中的
std::vector<ImageContainer*> imageContent
元素,来自
std::vector<wxImage> images
MyFrame.cpp:

TPanel leftPanel = new TPanel(menuSplitter, &cManager, wxID_ANY, wxDefaultPosition, wxSize(600, 494));

wxWrapSizer imageWrapper = new wxWrapSizer(wxHORIZONTAL);
leftPanel->SetSizer(imageWrapper);

for (auto& img : images) {
    auto image = new ImageContainer(leftPanel, &img, &cManager, wxID_ANY, wxDefaultPosition, wxSize(120, 100));

    imageContent.push_back(image);
    imageWrapper->Add(image, 0, wxALL, FromDIP(10));
}

所以我跟踪我需要的选择区域TPanel.h / TPanel.cpp

class TPanel : public wxScrolled<wxWindow> {
public:
    TPanel(wxWindow* parent, ColorManager* clrM, wxWindowID winid = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxTAB_TRAVERSAL | wxNO_BORDER,  const wxString& name = wxASCII_STR(wxPanelNameStr));

private:
    wxPoint startSel, endSel;
    ColorManager* colorManager;
    bool isSelect = false;
// ... and other minor details
};

void TPanel::OnMouseLeftDown(wxMouseEvent& evt) {
    if (!isSelect) {
        CaptureMouse();
        isSelect = true;
        startSel = ScreenToClient(wxGetMousePosition());
    }
}

void TPanel::OnMouseLeftUp(wxMouseEvent& evt) {
    if (isSelect) {
        ReleaseMouse();
        isSelect = false;
        Refresh();
    }
}

void TPanel::OnMouseMove(wxMouseEvent& evt) {
    if (isSelect) {
        endSel = ScreenToClient(wxGetMousePosition());
        Refresh();
    }
}

void TPanel::OnMouseLost(wxMouseCaptureLostEvent& evt) {
    ReleaseMouse();
    isSelect = false;
    Refresh();
}

void TPanel::OnSize(wxSizeEvent& event) {
    wxSize size = GetClientSize();
    this->SetVirtualSize(size);
    event.Skip();
}

好吧,我可以直接在面板上绘制这个区域,但是然后它会显示在

imageContent
的元素下。我想要的是将其显示在面板的所有子窗口之上,在其边界内。

  1. 我尝试在
    wxWindow
    的构造函数中初始化
    TPanel
    以在上面创建一个透明窗口并在其上绘制选区。窗口确实是在子元素上方创建的,但是
    wxBG_STYLE_TRANSPARENT
    没有提供任何透明度。
  2. 接下来,我尝试查找有关使用设备上下文渲染图形的方法的信息。关于
    wxOverlay
    的信息和示例太少,我无法理解如何正确使用它。在
    wxClientDC
    wxWindowDC
    wxScreenDC
    等方法中,我只用
    wxScreenDC
    就实现了闪烁绘制。在其他情况下,我根本无法显示该区域。

更新。 现在我选择了一个解决方法。

TPanel
生成选择开始事件,
MyFrame
MultiSelection()
中处理该事件。这里,检查矩形描边区域与控件的
wxRect
的交集,并传递需要在子元素上绘制的区域。该方法有效,但我不确定它在大型商业程序或操作系统中是否同样有效。

void MyFrame::MultiSelection(wxCommandEvent& evt) {
    wxRect selectRC = wxRect(leftPanel->strSel, leftPanel->endSel);

    for (auto& item : imageContent) {
        if (item->GetRect().Intersects(selectRC)) {
            item->isMark = true;
            item->isSelect = true;
            item->selectRC = wxRect(selectRC.GetX() - item->GetPosition().x, selectRC.GetY() - item->GetPosition().y,
                selectRC.GetWidth(), selectRC.GetHeight());
        }
        else {
            item->isMark = false;
            item->isSelect = false;
        }
    }
}
wxwidgets gdi
1个回答
0
投票

你应该看看wxOverlay

© www.soinside.com 2019 - 2024. All rights reserved.