Re: Window will not expose



On 01/25/2009 06:04 PM, Talguy wrote:
#ifndef DEFAULT_H
#define DEFAULT_H

#include <cairomm/context.h>
#include <gtkmm/drawingarea.h>

class Default : public Gtk::DrawingArea {
   private:
     void processSpeed(double);
     void processRPM(double);
     void processFuel(double);
     void drawGauge(double);
     void drawNeedle(double, double);
     void drawFuelGauge(double);
     virtual bool on_expose_event(GdkEventExpose* event);

     // Variables
     const std::string gauges[];
     double currentSpeedValue, currentRpmValue, currentFuelValue;
     double totalDrawableWidth, totalDrawableHeight;
     double width, height;
     bool initialize;

     Cairo::RefPtr<Cairo::Context> cr;
     Glib::RefPtr<Glib::IOChannel> file_read;

   public:
     Default(void);
     virtual ~Default(void);
     bool Update(Glib::IOCondition);
};

#endif
---------------------------------------
#include "Default.h"

#include <cairomm/context.h>
#include <math.h>
#include <string>
#include <iostream>
using namespace std;

//Variables
const string gauges[3] = {"speed", "rpm", "fuel"};

const double gaugeRadius = 0.225;
const double gaugeWidth = 0.45;
const double gaugePadding = 0.05;
const double gaugeLowerPadding = 0.10; //percentages/100
const double signalArea = 0.15; //15% of the main drawing area will be
devoted tCairo::RefPtr<Cairo::Context> cro drawign the signals
const double drawableArea = 0.8;  //80% of the drawable area will be
devoted to drawing the gauges
const double maxSpeed = 120;
const double maxRPM = 8000;



//Methods
Default::Default(void) {
     currentSpeedValue = 0;
     currentRpmValue = 0;
     currentFuelValue = 0;
     initialize = true;

     file_read = Glib::IOChannel::create_from_file("test.txt", "r");
     Glib::signal_io().connect(sigc::mem_fun(*this, &Default::Update),
file_read, Glib::IO_IN | Glib::IO_HUP);

     #ifndef GLIBMM_DEFAULT_SIGNAL_HANDLERS_ENABLED
     //Connect the signal handler if it isn't already a virtual method
override:
     signal_expose_event().connect(sigc::mem_fun(*this,
&Clock::on_expose_event), false);
     #endif //GLIBMM_DEFAULT_SIGNAL_HANDLERS_ENABLED
}

Default::~Default(void) {
}

bool Default::Update(Glib::IOCondition io_condition) {
     // force the program to redraw the screen
     Glib::RefPtr<Gdk::Window> win = get_window();
     if (win) {
         cout << "forcing\n";
         Gdk::Rectangle r(0, 0, get_allocation().get_width(),
         get_allocation().get_height());
         win->invalidate_rect(r, false);
         cout << "invalidated\n";
     }
     cout << "bye\n\n";
     return true;
}

// use this to draw the intial screen
bool Default::on_expose_event(GdkEventExpose* event) {
     cout << "exposing\n";
     Glib::RefPtr<Gdk::Window> window = get_window();
     if(window) {
         Gtk::Allocation allocation = get_allocation();
         totalDrawableWidth = allocation.get_width();
         totalDrawableHeight = allocation.get_height();

         cr = window->create_cairo_context();
         cr->rectangle(event->area.x, event->area.y, event->area.width,
event->area.height);
         cr->clip();

         if(!initialize) {
             cout << "Updating....\n";

             Glib::ustring buf;
             cout << "created the buffer\n";
             #ifdef GLIBMM_EXCEPTIONS_ENABLED
             file_read->read_line(buf);
             cout << "read in a line\n";
             #else
             auto_ptr<Glib::Error> ex;
             file_read->read_line(buf, ex);
             if(ex.get()) {
                 cout << "ouch\n";
                 cerr << "Error: " << ex->what() << endl;
             }
             #endif //GLIBMM_EXCEPTIONS_ENABLED

             string temp = buf.raw();
             string tempVal = temp.substr(2, temp.length()-1);
             temp.erase(1, temp.length()-1);
             int SensID = atoi(temp.c_str());
             double value = atof(tempVal.c_str());
             cout << "data received\n";
             switch(SensID) {
                 case 0:
                     cout << "speed baby\n";
                     processSpeed(value);
                     break;
                 case 1:
                     processRPM(value);
                     break;
                 case 2:
                     processFuel(value);
                     break;
                 default:
                     cerr << "no luck bud\n";
                     break;
             }
         }
         else {
             // Draw initial gauges
              drawGauge(gaugePadding*totalDrawableWidth);  // Speed Gauge
             drawGauge((gaugeWidth + gaugePadding)*totalDrawableWidth);
// RPM Gauge

             drawNeedle(180, gaugePadding*totalDrawableWidth);  // Speed
Needle
             drawNeedle(180, (gaugeWidth +
gaugePadding)*totalDrawableWidth);  // RPM Needle

             drawFuelGauge(0);
             initialize = false;
             cout << "DONE INTIALIZATION\n";
         }
     }
     return true;
}

void Default::drawGauge(double Offset) {
     cr->set_source_rgb(0,0,0);
     cr->set_line_width(5);
     cr->set_line_join(Cairo::LINE_JOIN_ROUND);

     //draw gauge outlines
     cr->save();
     cr->arc(gaugeRadius * totalDrawableWidth + Offset + 1,
totalDrawableHeight - (gaugePadding * totalDrawableHeight), gaugeRadius
* totalDrawableWidth, M_PI, 0);
     cr->stroke();
     cr->restore();

     // Draw tick marks
     double lineLength = 0;
     bool evens = true;
     int temp = 0;
     int spacer = 0;
     for(int x = 0; x<13; x++) {
         cr->save();
         cr->set_line_join(Cairo::LINE_JOIN_ROUND);
         cr->set_line_width(3);
         spacer = 0;

         if(x%2 == 0) {
             lineLength = gaugePadding * totalDrawableWidth;
             evens = true;
         }
         else {
             lineLength = gaugePadding * totalDrawableWidth/2;
             evens = false;
         }

         cr->move_to(Offset + gaugeRadius * totalDrawableWidth + 1 +
(gaugeRadius * totalDrawableWidth - lineLength) * cos(x*M_PI/12),
totalDrawableHeight - (gaugePadding * totalDrawableHeight) -
(gaugeRadius * totalDrawableWidth - lineLength) * sin(x*M_PI/12));
         cr->line_to(Offset + gaugeRadius * totalDrawableWidth + 1 +
(gaugeRadius * totalDrawableWidth) * cos(x*M_PI/12), totalDrawableHeight
- (gaugePadding * totalDrawableHeight) - (gaugeRadius *
totalDrawableWidth) * sin(x*M_PI/12));

         // write values of even tick marks to the screen
         if(evens) {
             string s;
             stringstream out;
             temp = 120 - 20*x/2;
             out << temp;
             s = out.str();
             if(temp >=100) {
                 spacer = 35;
             }
             if(temp >=60 && temp <=80) {
                 spacer = 10;
             }
             cr->move_to(Offset + gaugeRadius * totalDrawableWidth + 1 +
(gaugeRadius * totalDrawableWidth - lineLength - 7 - spacer) *
cos(x*M_PI/12), totalDrawableHeight - (gaugePadding *
totalDrawableHeight) - (gaugeRadius * totalDrawableWidth - lineLength -
spacer - 7) * sin(x*M_PI/12));
             cr->set_font_size(15);
             cr->text_path(s);
         }

         cr->stroke();
         cr->restore();
     }
     //cout << "here\n";
     //cr->stroke();
     //cout <<"done here\n";
}

void Default::drawFuelGauge(double Nangle) {

     // Process angle
     Nangle = Nangle * M_PI / 180;

     cr->set_source_rgb(0,0,0);
     cr->set_line_width(5);

     cr->save();
     cr->arc((2*gaugeRadius + gaugePadding) * totalDrawableWidth + 1,
totalDrawableHeight - ((gaugePadding + 2*gaugeRadius)*
totalDrawableHeight), gaugeRadius/2 * totalDrawableWidth, M_PI, 0);
     cr->stroke();
     cr->restore();

     // Draw tick marks
     double lineLength = 0;
     bool evens = true;
     int count = 0;
     int temp = 0;
     int spacer = 0;
     string labels[] = {"F","3/4","1/2","1/4","E"};
     for(int x = 0; x<5; x++) {
         cr->save();
         cr->set_line_width(3);
         spacer = 0;

         if(x%2 == 0) {
             lineLength = gaugePadding * totalDrawableWidth;
             evens = true;

         }
         else {
             lineLength = gaugePadding * totalDrawableWidth/2;
             evens = false;
         }

         cr->move_to((2*gaugeRadius + gaugePadding) * totalDrawableWidth
+ 1 + (gaugeRadius/2 * totalDrawableWidth - lineLength) * cos(x*M_PI/4),
totalDrawableHeight - ((gaugePadding + 2*gaugeRadius)*
totalDrawableHeight) - (gaugeRadius/2 * totalDrawableWidth - lineLength)
* sin(x*M_PI/4));
         cr->line_to((2*gaugeRadius + gaugePadding) * totalDrawableWidth
+ 1 + (gaugeRadius/2 * totalDrawableWidth) * cos(x*M_PI/4),
totalDrawableHeight - ((gaugePadding + 2*gaugeRadius)*
totalDrawableHeight) - (gaugeRadius/2 * totalDrawableWidth) *
sin(x*M_PI/4));

         cr->stroke();
         cr->restore();
     }

     //Draw Needle
     //Draw center dot
     cr->save();
     cr->set_source_rgba(1,0.2,0.2,1);
     cr->arc((2*gaugeRadius + gaugePadding) * totalDrawableWidth + 1,
totalDrawableHeight - ((gaugePadding + 2*gaugeRadius)*
totalDrawableHeight), gaugePadding/6*totalDrawableWidth, 0, 2*M_PI);
     cr->fill();
     cr->stroke();
     cr->restore();

     // Draw needle line
     cr->save();
     cr->set_source_rgba(1,0.2,0.2,0.6);
     cr->set_line_width(6);
     cr->set_line_cap(Cairo::LINE_CAP_ROUND);
     cr->move_to((2*gaugeRadius + gaugePadding) * totalDrawableWidth +
1, totalDrawableHeight - ((gaugePadding + 2*gaugeRadius)*
totalDrawableHeight));
     cr->line_to((2*gaugeRadius + gaugePadding) * totalDrawableWidth + 1
+ (gaugeRadius/2 * totalDrawableWidth
-gaugePadding/2*totalDrawableWidth) * cos(Nangle), totalDrawableHeight -
((gaugePadding + 2*gaugeRadius)* totalDrawableHeight) - (gaugeRadius/2 *
totalDrawableWidth - gaugePadding/2*totalDrawableWidth) * sin(Nangle));
     cr->stroke();
     cr->restore();

}

void Default::drawNeedle(double Nangle, double Offset) {
     // Draw center dot
     cr->save();
     cr->set_source_rgba(1,0.2,0.2,1);
     cr->arc(gaugeRadius * totalDrawableWidth + Offset + 1,
totalDrawableHeight - (gaugePadding * totalDrawableHeight),
gaugePadding/6*totalDrawableWidth, 0, 2*M_PI);
     cr->fill();
     cr->stroke();
     cr->restore();

     // Process angle
     Nangle = Nangle * M_PI / 180;

     // Draw needle line
     cr->save();
     cr->set_source_rgba(1,0.2,0.2,0.6);
     cr->set_line_width(6);
     cr->set_line_cap(Cairo::LINE_CAP_ROUND);
     cr->move_to(gaugeRadius * totalDrawableWidth + Offset + 1,
totalDrawableHeight - (gaugePadding * totalDrawableHeight));
     cr->line_to(Offset + gaugeRadius * totalDrawableWidth + 1 +
(gaugeRadius * totalDrawableWidth -gaugePadding/2*totalDrawableWidth) *
cos(Nangle), totalDrawableHeight - (gaugePadding * totalDrawableHeight)
- (gaugeRadius * totalDrawableWidth - gaugePadding/2*totalDrawableWidth)
* sin(Nangle));
     cr->stroke();
     cr->restore();
}

void Default::processSpeed(double value) {
     cout << "updating speed\n";
     //cr->rectangle(gaugePadding * totalDrawableWidth,
gaugeLowerPadding * totalDrawableHeight, gaugeWidth *
totalDrawableWidth, gaugeRadius * totalDrawableHeight);
     //cr->clip();
     currentSpeedValue = value;
     double Nangle = 0;

     if(value <= 120) {
         cout << "I am here - 120\n";
         Nangle = (1-(value/120)) * M_PI;  // Already in radians
     }
     else {
         cout << "I am here - 0\n";
         Nangle = 0;
     }
     cout << "the angle is: " << Nangle << endl;
     cout << "Drawing Gauge\n";
     drawGauge(gaugePadding * totalDrawableWidth);
     cout << "Drawing Needle\n";
     drawNeedle(Nangle, 0);
     cout << "DONE!!!!!!!!!\n";
}

void Default::processRPM(double value) {
     //cr->rectangle((gaugePadding + gaugeWidth) * totalDrawableWidth,
gaugeLowerPadding * totalDrawableHeight, gaugeWidth *
totalDrawableWidth, gaugeRadius * totalDrawableHeight);
     //cr->clip();
     currentRpmValue = value;
     double Nangle = 0;

     if(value <= 8000)
         Nangle = (1 - (value/8000)) * M_PI; // Already in radians
     else
         Nangle = 0;

     drawGauge((gaugePadding + gaugeWidth) * totalDrawableWidth);
     drawNeedle(Nangle, (gaugePadding + gaugeWidth) * totalDrawableWidth);
}

void Default::processFuel(double value) {
     currentFuelValue = value;
     double Nangle = 0;

     if(value <= 100)
         Nangle = (1 - (value/100)) * M_PI; // Already in radians
     else
         Nangle = 0;

     drawFuelGauge(Nangle);
}

---------------------------------------
#include "Default.h"

#include <gtkmm/main.h>
#include <gtkmm/window.h>
#include <string>

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

     Gtk::Window win;
     win.set_title("Dynamic Vehicle Dashboard");
     //win.fullscreen();
     win.maximize();

     Default deFault;
     win.add(deFault);
     deFault.show();

     app.run(win);

     return 0;
}
---------------------------------------
CC = g++
SOURCES = Default.cpp
CFLAGS = -Wall
OBJECTS = $(SOURCES:.cpp=.o)
EXECUTABLE = DynamicVehicleDashboard

GTKMM = `pkg-config --cflags --libs gtkmm-2.4`

all: mainTestDefault.cpp $(OBJECTS)
     $(CC) $(GTKMM) $(OBJECTS) mainTestDefault.cpp -o $(EXECUTABLE)

Default.o: Default.cpp Default.h
     $(CC) `pkg-config --cflags gtkmm-2.4` -c Default.cpp

.PHONY: clean
clean: rm -f DVD $(OBJECTS)


First of all, this makefile is not building anything with debugging information (-g) so I'm guessing that you haven't run this under a debugger to inspect the behavior at all. I'd encourage you to do that rather than relying too heavily on debugging-by-print-statements.

So I think there are a few issues mixed together here. When you register an io handler, it will use the default priority (G_PRIORITY_DEFAULT) unless otherwise specified. This priority is apparently higher than the priority for re-drawing events (see [1]), so if there is io ready to be handled, it seems that it will always take priority over the redraw (in your current code). Combine this with the fact that you're actually calling the read_line() function in your expose handler rather than in your io handler, and what you have is Update() being called in a sort of an infinite loop with no data ever being read. (as a side note, you're never checking the return value of your read_line() call, so even if your read_line() function was getting called as desired, you would continue attempting to process data long after the end of file actually occurred).

I have hacked up a few changes to your code that gets things to a semi-working state, but it'll probably require a bit more work to get it working properly. hopefully it's enough to give you some ideas though.

[1] http://library.gnome.org/devel/glib/unstable/glib-The-Main-Event-Loop.html#G-PRIORITY-HIGH-IDLE:CAPS

Attachment: dynamic-vehicle-dashboard.tar.gz
Description: GNU Zip compressed data



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]