gtkmm 2.4 cairo clock示例在修改为在HBox内部而不是主窗口中绘制时不起作用

时间:2012-05-10 15:40:19

标签: c++ gtk cairo gtkmm

我在Ubuntu 10.04上使用gtkmm2.4。 (因此我的示例包含on_expose_event()例程而不是on_draw())。似乎VBox中没有窗口引用on_expose_event()中的get_window()。我必须添加吗?

原始代码http://developer.gnome.org/gtkmm-tutorial/2.22/gtkmm-tutorial.html#sec-drawing-clock-example

我的代码是

test.h

#ifndef TEST_H
#define TEST_H

#include <gtkmm.h>


class TEST : public virtual Gtk::Window
{

private:

public:
  TEST();
  virtual ~TEST();

protected:

  Gtk::VBox V;          // Make V Box
  Gtk::HBox H1;     // Upper H Box
  Gtk::HBox H2;     // Lower H Box

class Clock : public virtual Gtk::DrawingArea
{
    public:
        Clock();
        virtual ~Clock();

    protected:
        //Override default signal handler:
        virtual bool on_expose_event(GdkEventExpose* event);
        double m_radius;
        double m_lineWidth;
        bool onSecondElapsed(void);


  Glib::RefPtr<Gdk::Window> m_refGdkWindow;
};

};



#endif // TEST_H

test.cc

#include <ctime>
#include <math.h>
#include <cairommconfig.h>
#include <cairomm/context.h>
#include <cairomm/surface.h>
#include "test.h"

TEST::TEST()
:
V(true,0),
H1(true,0),
H2(true,0)
{

 set_title("test clock");
  set_border_width(10);
  set_size_request(500,500); //set Window Size

  add(V);
  V.pack_start(H1);
  V.pack_start(H2);

  Clock c;  

  H2.pack_start(c);

  show_all(); 


}

TEST::~TEST()
{
}

TEST::Clock::Clock()
    : m_radius(0.42), m_lineWidth(0.05)
{
    Glib::signal_timeout().connect(
                sigc::mem_fun(*this, &Clock::onSecondElapsed), 1000);
}

TEST::Clock::~Clock()
{
}

bool TEST::Clock::on_expose_event(GdkEventExpose* event)
{
  // This is where we draw on the window
  Glib::RefPtr<Gdk::Window> window = get_window();
  if(window)
  {
    Gtk::Allocation allocation = get_allocation();
    const int width = allocation.get_width();
    const int height = allocation.get_height();

    Cairo::RefPtr<Cairo::Context> cr = window->create_cairo_context();

    if (event)
    {
        // clip to the area indicated by the expose event so that we only
        // redraw the portion of the window that needs to be redrawn
        cr->rectangle(event->area.x, event->area.y,
                event->area.width, event->area.height);
        cr->clip();
    }

    // scale to unit square and translate (0, 0) to be (0.5, 0.5), i.e.
    // the center of the window
    cr->scale(width, height);
    cr->translate(0.5, 0.5);
    cr->set_line_width(m_lineWidth);

    cr->save();
    //cr->set_source_rgba(0.337, 0.612, 0.117, 0.9);   // green
    cr->set_source_rgba( 0.712, 0.437, 0.117, 0.7);   // green
    cr->paint();
    cr->restore();
    cr->arc(0, 0, m_radius, 0, 2 * M_PI);
    cr->save();
    cr->set_source_rgba(1.0, 1.0, 1.0, 0.8);
    cr->fill_preserve();
    cr->restore();
    cr->stroke_preserve();
    cr->clip();

    //clock ticks
    for (int i = 0; i < 12; i++)
    {
        double inset = 0.05;

        cr->save();
        cr->set_line_cap(Cairo::LINE_CAP_ROUND);

        if (i % 3 != 0)
        {
            inset *= 0.8;
            cr->set_line_width(0.03);
        }

        cr->move_to(
                (m_radius - inset) * cos (i * M_PI / 6),
                (m_radius - inset) * sin (i * M_PI / 6));
        cr->line_to (
                m_radius * cos (i * M_PI / 6),
                m_radius * sin (i * M_PI / 6));
        cr->stroke();
        cr->restore(); /* stack-pen-size */
    }

    // store the current time
    time_t rawtime;
    time(&rawtime);
    struct tm * timeinfo = localtime (&rawtime);

    // compute the angles of the indicators of our clock
    double minutes = timeinfo->tm_min * M_PI / 30;
    double hours = timeinfo->tm_hour * M_PI / 6;
    double seconds= timeinfo->tm_sec * M_PI / 30;

    cr->save();
    cr->set_line_cap(Cairo::LINE_CAP_ROUND);

    // draw the seconds hand
    cr->save();
    cr->set_line_width(m_lineWidth / 3);
    cr->set_source_rgba(0.7, 0.7, 0.7, 0.8); // gray
    cr->move_to(0, 0);
    cr->line_to(sin(seconds) * (m_radius * 0.9), 
            -cos(seconds) * (m_radius * 0.9));
    cr->stroke();
    cr->restore();

    // draw the minutes hand
    cr->set_source_rgba(0.117, 0.337, 0.612, 0.9);   // blue
    cr->move_to(0, 0);
    cr->line_to(sin(minutes + seconds / 60) * (m_radius * 0.8),
            -cos(minutes + seconds / 60) * (m_radius * 0.8));
    cr->stroke();

    // draw the hours hand
    cr->set_source_rgba(0.337, 0.612, 0.117, 0.9);   // green
    cr->move_to(0, 0);
    cr->line_to(sin(hours + minutes / 12.0) * (m_radius * 0.5),
            -cos(hours + minutes / 12.0) * (m_radius * 0.5));
    cr->stroke();
    cr->restore();

    // draw a little dot in the middle
    cr->arc(0, 0, m_lineWidth / 3.0, 0, 2 * M_PI);
    cr->fill();

  }

  return true;
}


bool TEST::Clock::onSecondElapsed(void)
{
    // force our program to redraw the entire clock.
    Glib::RefPtr<Gdk::Window> win = get_window();
    if (win)
    {
        Gdk::Rectangle r(0, 0, get_allocation().get_width(),
                get_allocation().get_height());
        win->invalidate_rect(r, false);
    }
    return true;
}

main.cc

#include "test.h"
#include <gtkmm.h>

int main(int argc, char** argv)
{
   Gtk::Main kit(argc, argv);

   //Gtk::Window win;
   //win.set_title("Cairomm Clock");

   //Clock c;
   //win.add(c);
   //c.show();

   TEST t;


   Gtk::Main::run(t);

   return 0;
}

编译

    g++ -g test.cc main.cc -o test `pkg-config gtkmm-2.4 cairomm-1.0`

1 个答案:

答案 0 :(得分:5)

这部分对我很怀疑:

Clock c;  
H2.pack_start(c);

在此范围的最后,c被销毁。实际上,我不确定为什么它不会崩溃,但也许其他人可以对此有所了解。你想在TEST中声明Clock,因此它有适当的生命周期:

class TEST {
   ... 
   class Clock ... {
     ...
   };
   Clock c;   // new code
   ...
};