[gtkmm] display image and draw from non-gui thread
- From: Silviu D Minut <minutsil cse msu edu>
- To: <gtkmm-list gnome org>
- Subject: [gtkmm] display image and draw from non-gui thread
- Date: Mon, 16 Jun 2003 11:48:10 -0400 (EDT)
Following suggestions from the list, I came up with the following code
(attached), in my quest to build a gui for a certain application.
Basically, an image is loaded from the disk and displayed into a drawing
area. The main window has also a toggle button which starts/stops a
non-gui thread. At fixed intervals the non-gui thread must draw something
into the drawing area (random points for now). I managed to do this now
with a Dispatcher. I followed the dispatcher.cc example, but I simplified
it (I don't have the signal_finished() stuff). Could somebody please give
me some feedback on the attached code? I want to make sure that I don't
have memory leaks, that widgets are distroyed when they should, etc.
In other words I want to make sure that everything is clean.
Thanks!
// draw.C - example of loading an image from file and drawing from a
// non-gui thread via a Dispatcher.
//
// Silviu Minut - June 16 2003.
//
// g++ -o draw draw.C `pkg-config --cflags --libs gtkmm-2.0 gthread-2.0`
//
//
// Main window composed of a drawing area and a toggle button.
// An image is loaded from a file and displayed in the drawing area.
// When the toggle button is toggled, a separate thread is started/stopped.
// The thread draws (random points for now) into the drawing area, via a
// Dispatcher.
// This is the recommended approach for drawing from a non-gui thread.
#include <gtkmm/box.h>
#include <gdkmm/colormap.h>
#include <gtkmm/togglebutton.h>
#include <gtkmm/drawingarea.h>
#include <gtkmm/window.h>
#include <gtkmm/image.h>
#include <gtkmm/main.h>
#include <sigc++/class_slot.h>
#include <glibmm.h>
#include <iostream>
#include <cstdlib>
#include <cmath>
using namespace std;
///////////////////////////////////////////////////////////////////////////////
//
// Drawing area with a picture in the background.
//
///////////////////////////////////////////////////////////////////////////////
class ImgViewer : public Gtk::DrawingArea
{
public:
ImgViewer();
~ImgViewer() {};
void load(char * file);
void draw_random_points();
protected:
virtual bool on_expose_event(GdkEventExpose * event);
virtual void on_realize();
// A GC, some colors, and a pixbuf to display an image in the background
Glib::RefPtr<Gdk::GC> gc_;
Gdk::Color green_, black_;
Glib::RefPtr<Gdk::Pixbuf> pixbuf_;
};
ImgViewer::ImgViewer()
{
// Get the colors only. We don't have a window until realized().
Glib::RefPtr<Gdk::Colormap> colormap = get_default_colormap();
green_ = Gdk::Color("green");
black_ = Gdk::Color("black");
colormap->alloc_color(green_);
colormap->alloc_color(black_);
add_events(Gdk::EXPOSURE_MASK);
}
void ImgViewer::on_realize()
{
// We need to call the base on_realize()
Gtk::DrawingArea::on_realize();
// Now we can allocate any additional resources we need
Glib::RefPtr<Gdk::Window> window = get_window();
window->set_background(black_);
window->clear();
gc_ = Gdk::GC::create(window);
gc_->set_foreground(green_);
}
void ImgViewer::load(char * file)
{
u_int rows=0, cols=0;
pixbuf_=Gdk::Pixbuf::create_from_file(file);
rows=pixbuf_->get_height();
cols=pixbuf_->get_width();
cout << rows << "\t" << cols << endl;
set_size_request(cols, rows);
}
bool ImgViewer::on_expose_event(GdkEventExpose * event)
{
// On expose event only draw the image in the background
int winx, winy, winw, winh, wind;
Glib::RefPtr<Gdk::Window> window = get_window();
window->get_geometry(winx, winy, winw, winh, wind);
pixbuf_->render_to_drawable(window, gc_, 0,0, 0,0, winw, winh,
Gdk::RGB_DITHER_NORMAL, 0, 0);
}
void ImgViewer::draw_random_points()
{
int x, y;
int winx, winy, winw, winh, wind;
Glib::RefPtr<Gdk::Window> window = get_window();
window->get_geometry(winx, winy, winw, winh, wind);
// pixbuf_->render_to_drawable(window, gc_, 0,0, 0,0, winw, winh,
// Gdk::RGB_DITHER_NORMAL, 0, 0);
x=rand()%winw;
y=rand()%winh;
window->draw_rectangle(gc_, 1, x,y,5,5);
}
///////////////////////////////////////////////////////////////////////////////
//
// Main window
//
///////////////////////////////////////////////////////////////////////////////
class AppWindow : public Gtk::Window
{
public:
AppWindow();
virtual ~AppWindow();
void load(char * file) { iv.load(file); };
protected:
// GUI stuff
Gtk::VBox m_box;
Gtk::ToggleButton m_button;
ImgViewer iv;
void on_toggle_button_clicked();
// Thread stuff
void thread_function();
Glib::Dispatcher draw_;
u_int iteration;
bool m_run;
void launch();
};
AppWindow::AppWindow()
: m_box(false, 5), m_button("Run"), iteration(0), m_run(0)
{
m_button.signal_clicked().connect(
SigC::slot(*this, &AppWindow::on_toggle_button_clicked) );
// Connect the dispatcher
draw_.connect(SigC::slot(iv, &ImgViewer::draw_random_points));
add_events(Gdk::EXPOSURE_MASK);
m_box.pack_start(iv, Gtk::PACK_EXPAND_WIDGET, 5);
m_box.pack_start(m_button, Gtk::PACK_SHRINK, 5);
add(Gtk::manage(m_box));
show_all();
}
AppWindow::~AppWindow()
{
}
void AppWindow::on_toggle_button_clicked()
{
bool state=m_button.get_active();
if(state){
m_button.set_label("Running");
m_run=1;
launch();
std::cout << "active" << "\t" << m_run << std::endl;
}
else{
m_button.set_label("Stopped");
m_run=0;
std::cout << "inactive" << "\t" << m_run
<< "\t" << iteration << std::endl;
}
}
void AppWindow::thread_function()
{
while(m_run){
if(iteration%10000==0)
draw_(); // tell the GUI to draw
iteration++;
}
}
void AppWindow::launch()
{
// Create a non-joinable thread -- deleted automatically on thread exit.
Glib::Thread::create(SigC::slot_class(*this, &AppWindow::thread_function),
false);
}
void usage(char * prog)
{
cout << endl << "\e[1;31mUsage: \e[0m"
<< prog << " [Options] image_file" << endl
<< endl << endl
<< "\e[1;33mOptions: \e[0m" << endl
<< endl;
exit(-1);
}
int main(int argc, char * argv[])
{
Glib::thread_init();
Gtk::Main mmain(argc, argv);
AppWindow w;
if(argc<2)
usage(argv[0]);
w.load(argv[1]);
Gtk::Main::run(w);
return 0;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]