如何构建简单的wxWidgets图像显示

6
我写了一个wxPython程序,现在需要将其翻译成wxWidgets。程序中有一个滚动窗口用于显示图片。根据Rappin的wxPython In Action(清单12.1),我在面板中使用了StaticBitmap。然而,在查阅最新的wxWidgets文档时,我发现了一个严重警告,它指出wxStaticBitmap只适用于非常小的图像。文档中提到:“如果想要便携地显示更大的图像,则应该使用自己的控件。”好吧,那就给我看看。我没有“自己的控件”。
Rappin是错了,还是文档过时了?
问题是 - 无疑是初学者的问题 - 在wxWidgets中如何创建一个简单的图像查看窗口?希望有一个可以替代wxStaticBitmap的类或简单的方法。我查看了wxWidgets“samples”目录中的“image”程序。它和战争与和平一样长。肯定有一个现成的类或简单的方法。

也许 mghie 的意思不是 'Invalidate()',而是 'Refresh()'。(这应该是对答案0的修改,但我不知道如何实现。) - contributor
2个回答

3

不要被“image”示例的大小所迷惑,只需要几行代码就可以实现你想要的功能。

image.cpp文件中搜索MyImageFrame类,它只是一个带有私有位图字段、自定义构造函数设置位图和窗口客户端大小以及EVT_PAINT事件处理程序的类:

void OnPaint(wxPaintEvent& WXUNUSED(event))
{
    wxPaintDC dc( this );
    dc.DrawBitmap( m_bitmap, 0, 0, true /* use mask */ );
}

既然你不想在这里使用frame类,那么你可以按照以下步骤进行操作:创建一个简单的wxWindow子类,该子类具有类似的构造函数、绘画处理程序,并且复制了你在代码中使用的wxStaticBitmap方法。也许只需要一个方法来设置新位图并调整控件大小以适应新位图的尺寸。


我将其标记为答案。看起来很简单。实际上我还没有让它工作,但我刚刚开始。 :-) - Jive Dadson
一个真实的工作示例会很棒。我已经弄清楚在 "wxPaintDC dc(this);" 之后必须添加 "PrepareDC(dc)"。我不知道那是什么或为什么需要它。只是照猫画虎。现在,我已经正确地显示了图像。但是我还没有能够捕捉到图像上的鼠标点击。仍在努力中。继续前进! - Jive Dadson
@Jive:请参考http://docs.wxwidgets.org/2.8/wx_wxscrolledwindow.html#wxscrolledwindowpreparedc,但这是在编写简单的`wxStaticBitmap`替代品之外。有关鼠标单击,请参见http://docs.wxwidgets.org/2.8/wx_wxmouseevent.html#wxmouseevent,您的类应该能够处理这些事件,因此您只需要连接一个处理程序。在*docvwmdi*示例中的*view.cpp*中有一个画布类(`wxScrolledWindow`的后代),它既可以绘制又可以处理鼠标事件,也许研究一下会有所帮助。 - mghie
1
我现在已经解决了那个部分。实际上,我已经解决了。我以为在鼠标处理程序中设置了断点,但实际上没有。傻瓜。在Stackoverflow上提问太容易了!自1971年以来,我一直全职从事这项工作,但我还是像个笨蛋。哦,好吧。接下来是下一个问题。我认为它正在决定垃圾回收我的光标,但我不知道为什么。 - Jive Dadson

2
// A scrolled window for showing an image.
class PictureFrame: public wxScrolledWindow
{   
public:
    PictureFrame()
        : wxScrolledWindow()
        , bitmap(0,0)
    {;}

    void Create(wxWindow *parent, wxWindowID id = -1)
    {
        wxScrolledWindow::Create(parent, id);
    }

    void LoadImage(wxImage &image) {
        bitmap = wxBitmap(image);
        SetVirtualSize(bitmap.GetWidth(), bitmap.GetHeight());
        wxClientDC dc(this);
        PrepareDC(dc);
        dc.DrawBitmap(bitmap, 0, 0);
    }

protected:
    wxBitmap bitmap;

    void OnMouse(wxMouseEvent &event) {
        int xx,yy;
        CalcUnscrolledPosition(event.GetX(), event.GetY(), &xx, &yy);
        event.m_x = xx; event.m_y = yy;
        event.ResumePropagation(1); // Pass along mouse events (e.g. to parent)
        event.Skip();
    }

    void OnPaint(wxPaintEvent &event) {
        wxPaintDC dc(this);
        PrepareDC(dc);
        dc.DrawBitmap(bitmap, 0,0, true);
    }
private:
    DECLARE_EVENT_TABLE()
};

BEGIN_EVENT_TABLE(PictureFrame,wxScrolledWindow)
    EVT_PAINT(PictureFrame::OnPaint)
    EVT_MOUSE_EVENTS(PictureFrame::OnMouse)
END_EVENT_TABLE()

LoadImage()中最好不要调用任何绘制代码,调用Invalidate()应该就足够了。控件将在方便系统的时候重绘。在调用LoadImage()时可能没有必要或者甚至不可能进行绘制。 - mghie
1>------ 开始构建: 项目: Munsell_picker, 配置: Debug Win32 ------ 1>编译中... 1>main.cpp 1>.\main.cpp(114) : 错误 C3861: 'Invalidate': 找不到标识符 - Jive Dadson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接