ubuntu下gtk库是默认已安装的,开发部署很方便,以下是我写的自绘控件例子:
EuhatChildWnd.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | #pragma once struct _cairo_surface; struct _GtkWidget; class EuhatChildWnd { public: EuhatChildWnd(int width, int height); ~EuhatChildWnd(); void clear(); void drawBrush(struct _GtkWidget *widget, double x, double y); struct _GtkWidget *drawingArea_; struct _cairo_surface *surface_; double xFrom_; double yFrom_; }; |
EuhatChildWnd.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 | #include "EuhatChildWnd.h" #include <gtk/gtk.h> static gboolean configureEventCb(GtkWidget *widget, GdkEventConfigure *event, gpointer data) { EuhatChildWnd *pThis = (EuhatChildWnd *)data; if (NULL != pThis->surface_) cairo_surface_destroy(pThis->surface_); pThis->surface_ = gdk_window_create_similar_surface(gtk_widget_get_window(widget), CAIRO_CONTENT_COLOR, gtk_widget_get_allocated_width(widget), gtk_widget_get_allocated_height(widget)); pThis->clear(); return TRUE; } static gboolean drawCb(GtkWidget *widget, cairo_t *cr, gpointer data) { EuhatChildWnd *pThis = (EuhatChildWnd *)data; cairo_set_source_surface(cr, pThis->surface_, 0, 0); cairo_paint(cr); return FALSE; } static gboolean buttonPressEventCb(GtkWidget *widget, GdkEventButton *event, gpointer data) { EuhatChildWnd *pThis = (EuhatChildWnd *)data; if (NULL == pThis->surface_) return FALSE; if (event->button == GDK_BUTTON_PRIMARY) { pThis->xFrom_ = event->x; pThis->yFrom_ = event->y; pThis->drawBrush(widget, event->x, event->y); } else if (event->button == GDK_BUTTON_SECONDARY) { pThis->clear(); gtk_widget_queue_draw(widget); } return TRUE; } static gboolean motionNotifyEventCb(GtkWidget *widget, GdkEventMotion *event, gpointer data) { EuhatChildWnd *pThis = (EuhatChildWnd *)data; if (NULL == pThis->surface_) return FALSE; if (event->state & GDK_BUTTON1_MASK) pThis->drawBrush(widget, event->x, event->y); return TRUE; } EuhatChildWnd::EuhatChildWnd(int width, int height) { surface_ = NULL; xFrom_ = 0; yFrom_ = 0; drawingArea_ = gtk_drawing_area_new(); gtk_widget_set_size_request(drawingArea_, width, height); g_signal_connect(drawingArea_, "configure-event", G_CALLBACK(configureEventCb), this); g_signal_connect(drawingArea_, "draw", G_CALLBACK(drawCb), this); g_signal_connect(drawingArea_, "button-press-event", G_CALLBACK(buttonPressEventCb), this); g_signal_connect(drawingArea_, "motion-notify-event", G_CALLBACK(motionNotifyEventCb), this); gtk_widget_set_events(drawingArea_, gtk_widget_get_events(drawingArea_) | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK); } EuhatChildWnd::~EuhatChildWnd() { if (NULL != surface_) cairo_surface_destroy(surface_); } void EuhatChildWnd::clear() { cairo_t *cr; cr = cairo_create(surface_); cairo_set_source_rgb(cr, 1, 1, 1); cairo_paint(cr); cairo_destroy(cr); } void EuhatChildWnd::drawBrush(GtkWidget *widget, gdouble x, gdouble y) { cairo_t *cr; cr = cairo_create(surface_); // cairo_rectangle(cr, x - 3, y - 3, 6, 6); // cairo_fill(cr); // cairo_draw_line(cr, xFrom_, yFrom_, x, y); cairo_set_source_rgb(cr, 1, 1, 1); cairo_paint(cr); cairo_set_source_rgb(cr, 0, 0, 0); cairo_set_line_width(cr, 1); cairo_move_to(cr, xFrom_, yFrom_); cairo_line_to(cr, x, yFrom_); cairo_line_to(cr, x, y); cairo_line_to(cr, xFrom_, y); cairo_line_to(cr, xFrom_, yFrom_); cairo_stroke(cr); cairo_destroy(cr); // gtk_widget_queue_draw_area(widget, x - 3, y - 3, 6, 6); gtk_widget_queue_draw(widget); } |
EuhatWindow.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | #pragma once struct _GtkWidget; class EuhatApp; class EuhatChildWnd; class EuhatWindow { public: EuhatWindow(EuhatApp *app); ~EuhatWindow(); void setTitle(const char *title); void addChildWnd(EuhatChildWnd *childWnd); void showAll(); struct _GtkWidget *window_; // struct _GtkWidget *frame_; struct _GtkWidget *box_; }; |
EuhatWindow.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | #include "EuhatWindow.h" #include "EuhatApp.h" #include "EuhatChildWnd.h" #include <gtk/gtk.h> static void closeWindow(gpointer data) { } EuhatWindow::EuhatWindow(EuhatApp *app) { window_ = gtk_application_window_new(app->app_); g_signal_connect(window_, "destroy", G_CALLBACK(closeWindow), this); gtk_container_set_border_width(GTK_CONTAINER(window_), 8); /* frame_ = gtk_frame_new(NULL); gtk_frame_set_shadow_type(GTK_FRAME(frame_), GTK_SHADOW_IN); gtk_container_add(GTK_CONTAINER(window_), frame_); */ box_ = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 10); gtk_container_add(GTK_CONTAINER(window_), box_); } EuhatWindow::~EuhatWindow() { } void EuhatWindow::setTitle(const char *title) { gtk_window_set_title(GTK_WINDOW(window_), title); } void EuhatWindow::addChildWnd(EuhatChildWnd *childWnd) { // gtk_container_add(GTK_CONTAINER(frame_), childWnd->drawingArea_); gtk_container_add(GTK_CONTAINER(box_), childWnd->drawingArea_); } void EuhatWindow::showAll() { gtk_widget_show_all(window_); } |
EuhatApp.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | #pragma once struct _GtkApplication; class EuhatApp { public: EuhatApp(); ~EuhatApp(); virtual void onActivate(); int run(int argc, char **argv); struct _GtkApplication *app_; }; |
EuhatApp.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | #include "EuhatApp.h" #include <gtk/gtk.h> static void activate(GtkApplication *app, gpointer data) { EuhatApp *pThis = (EuhatApp *)data; pThis->onActivate(); } EuhatApp::EuhatApp() { app_ = gtk_application_new("com.euhat.expert", G_APPLICATION_FLAGS_NONE); g_signal_connect(app_, "activate", G_CALLBACK(activate), this); } EuhatApp::~EuhatApp() { g_object_unref(app_); } void EuhatApp::onActivate() { } int EuhatApp::run(int argc, char **argv) { int status; status = g_application_run(G_APPLICATION(app_), argc, argv); return 1; } |
main.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | #include <EuhatApp.h> #include <EuhatWindow.h> #include <EuhatChildWnd.h> #include <list> #include <vector> #include <string> #include <memory> using namespace std; class TstApp : public EuhatApp { public: void onActivate(); unique_ptr<EuhatWindow> mainWin_; unique_ptr<EuhatChildWnd> childWnd_; unique_ptr<EuhatChildWnd> childWnd2_; }; void TstApp::onActivate() { mainWin_.reset(new EuhatWindow(this)); childWnd_.reset(new EuhatChildWnd(400, 400)); childWnd2_.reset(new EuhatChildWnd(400, 400)); mainWin_->addChildWnd(childWnd_.get()); mainWin_->addChildWnd(childWnd2_.get()); mainWin_->showAll(); } int main(int argc, char **argv) { TstApp app; return app.run(argc, argv); } |
Makefile
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | CPLUSPLUS=g++ CFLAGS=-g -I. -Wl,-Map=test.map -no-pie -rdynamic `pkg-config --cflags gtk+-3.0` LDFLAGS=`pkg-config --libs gtk+-3.0` SOURCES=$(wildcard *.cpp) OBJS=$(SOURCES:%.cpp=release/%.o) TARGET=release/test all: before $(TARGET) before: @test -d release || mkdir -p release $(OBJS): release/%.o: %.cpp $(CPLUSPLUS) -c $(CFLAGS) $< -o $@ $(TARGET): $(OBJS) $(CPLUSPLUS) -o $@ $^ $(LDFLAGS) clean: rm -Rf release |