gtkmm 2.4 开罗时钟示例在修改为在 HBox 内部而不是主窗口内绘制时不起作用

gtkmm 2.4 cairo clock example does not work when modified to draw inside HBox instead of main window

本文关键字:内部 HBox 不起作用 绘制 窗口 修改 罗时钟 时钟 gtkmm      更新时间:2023-10-16

我在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

我的代码是

测试.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`

这部分对我来说很可疑:

Clock c;  
H2.pack_start(c);

在此范围结束时,c 被销毁。 实际上,我不确定为什么它不会崩溃,但也许其他人可以对此有所了解。 您希望在 TEST 中声明时钟,以便它具有适当的生存期:

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