[gtkmm] drawing from a non-gui thread.
- From: Silviu D Minut <minutsil cse msu edu>
- To: <gtkmm-list gnome org>
- Subject: [gtkmm] drawing from a non-gui thread.
- Date: Fri, 13 Jun 2003 12:10:48 -0400 (EDT)
I'm writing an application, which has a GUI thread and a work thread. The
work thread runs in a loop and must draw something on the gui every 10000
iterations, say (as opposed to using a timer, as in the radar.cc example).
Please see the attached file.
Since I haven't seen any example doing precisely that (drawing from a
non-gui thread), I'm thinking to contribute this to the examples, but I'd
like to check its correctness with the list. Does anybody see any
obvious flaws?
Thanks!
// Simple thread example: gui thread and work thread.
// After some number of iterations, the work thread draws something on the gui.
//
// The work thread is started/stopped by the "Run" button.
//
// Inspired from radar.cc and thread.cc.
//
// g++ -o draw `pkg-config --cflags --libs gtkmm-2.0 gthread-2.0` draw.C
//
#include <gtkmm/drawingarea.h>
#include <gdkmm/colormap.h>
#include <gdkmm/window.h>
#include <gtkmm/button.h>
#include <gtkmm/togglebutton.h>
#include <gtkmm/box.h>
#include <gtkmm/statusbar.h>
#include <gtkmm/window.h>
#include <gtkmm/main.h>
#include <cmath>
#include <sstream>
#include <iostream>
#include <vector>
#include <glibmm/thread.h>
#include <sigc++/class_slot.h>
#include <gdkmm/general.h>
class m_DrawingArea : public Gtk::DrawingArea
{
public:
m_DrawingArea(const u_int MaxIter=10000);
virtual ~m_DrawingArea() {};
void thread_function();
bool m_run;
protected:
virtual void on_realize();
virtual bool on_expose_event(GdkEventExpose* event);
Glib::RefPtr<Gdk::GC> gc_;
Gdk::Color blue_, red_, green_, black_, white_, grey_, yellow_;
Glib::Mutex mutex_;
u_int loop_variable;
u_int max_iterations;
};
m_DrawingArea::m_DrawingArea(const u_int MaxIter)
: m_run(0), loop_variable(0), max_iterations(MaxIter)
{
// get_window() would return 0 because the Gdk::Window has not yet been realized
// So we can only allocate the colors here - the rest will happen in on_realize().
Glib::RefPtr<Gdk::Colormap> colormap = get_default_colormap();
blue_ = Gdk::Color("blue");
red_ = Gdk::Color("red");
green_ = Gdk::Color("green");
black_ = Gdk::Color("black");
white_ = Gdk::Color("white");
grey_ = Gdk::Color("grey");
yellow_ = Gdk::Color("yellow");
colormap->alloc_color(blue_);
colormap->alloc_color(red_);
colormap->alloc_color(green_);
colormap->alloc_color(black_);
colormap->alloc_color(white_);
colormap->alloc_color(grey_);
colormap->alloc_color(yellow_);
add_events(Gdk::EXPOSURE_MASK);
}
void m_DrawingArea::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();
gc_ = Gdk::GC::create(window);
window->set_background(black_);
window->clear();
gc_->set_foreground(green_);
}
bool m_DrawingArea::on_expose_event(GdkEventExpose * event)
{
Glib::RefPtr<Gdk::Window> window = get_window();
// window geometry: x, y, width, height, depth
int winx, winy, winw, winh, wind;
window->get_geometry(winx, winy, winw, winh, wind);
window->clear();
// More stuff here
return true;
}
void m_DrawingArea::thread_function()
{
u_int i, j;
int winx, winy, winw, winh, wind;
Glib::RefPtr<Gdk::Window> window = get_window();
// window geometry: x, y, width, height, depth
window->get_geometry(winx, winy, winw, winh, wind);
gc_->set_foreground(green_);
// while(m_run && loop_variable<max_iterations){
while(m_run){
if(loop_variable%10000==0){
i=rand()%400;
j=rand()%600;
Glib::Mutex::Lock lock(mutex_);
window->draw_point(gc_, j, i);
// Gdk::flush();
}
loop_variable++;
}
}
class AppWindow : public Gtk::Window
{
public:
AppWindow(const u_int MaxIter=10000);
virtual ~AppWindow();
protected:
// Child widgets
Gtk::VBox m_box;
Gtk::ToggleButton m_button;
m_DrawingArea m_darea;
void on_toggle_button_clicked();
};
AppWindow::AppWindow(const u_int MaxIter)
: m_box(false, 5), m_button("Run"), m_darea(MaxIter)
{
m_button.signal_clicked().connect(
SigC::slot(*this, &AppWindow::on_toggle_button_clicked) );
add_events(Gdk::EXPOSURE_MASK);
m_darea.set_size_request(600,400);
m_box.pack_start(m_darea, Gtk::PACK_EXPAND_WIDGET, 5);
m_box.pack_start(m_button, Gtk::PACK_SHRINK, 5);
add(m_box);
show_all();
}
AppWindow::~AppWindow()
{
}
void AppWindow::on_toggle_button_clicked()
{
bool state=m_button.get_active();
if(state){
std::cout << "active" << std::endl;
m_button.set_label("Running");
m_darea.m_run=1;
Glib::Thread * const Work = Glib::Thread::create(
SigC::slot_class(m_darea, &m_DrawingArea::thread_function), true);
// SigC::slot(&AppWindow::thread_function), true);
}
else{
std::cout << "inactive" << std::endl;
m_button.set_label("Stopped");
m_darea.m_run=0;
}
}
int main(int argc, char** argv)
{
Glib::thread_init();
Gtk::Main main_instance (argc, argv);
AppWindow draw(600*400);
Gtk::Main::run(draw);
return 0;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]