float类型的数组充当输入。该程序组织图表的显示,拉伸,滚动。写作风格是带有类的C(没有gtkmm)。事实证明,完美的抽象是不完美的。特别是,回调函数会降低封装性能,其中很大一部分变量必须移至公共部分。基本上,回调函数可以与我称为graphic_parameters的类的其余函数一起放在文件中。在GTK中,每种类型的小部件都有其自己的信号,其中一些是继承的。例如,由于GtkEventBox始终采用内容的大小,因此GtkEventBox具有“ button-press-event”信号,但不具有响应小部件调整大小所需的“ configure-event”。内容的大小是手动设置的。您可以使用GtkFrame容器。cairo_surface_t *surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
cairo_t *cr = cairo_create(surface);
在cairo_t中,将创建由cairo_stroke函数显示的行和标签。分析时发现cairo_stroke占用大量处理器时间,因此应尽可能少地使用它,并且
cairo_move_to,cairo_line_to之类的函数的执行时间非常短。在cairo_stroke之后,cairo_t的内容将被清除,再次调用cairo_stroke(cr)将不会输出任何内容。您可以使用
cairo_stroke_preserve保存内容和cairo_save / cairo_restore,但我没有使用它们。
如果更改了尺寸(通过用鼠标拉伸configure_event_cb信号),则对于每个图形,都必须删除并重新创建cairo_surface_t和cairo_t。如果倒带时间表,则无需重新创建
cairo_set_source_rgb(cr,0.8,0.8,0.8);
cairo_paint(cr);
接下来,将cairo_surface_t转换为图像void gtk_image_set_from_surface (GtkImage *image, cairo_surface_t *surface);
然后按如下方式插入此图像eventbox=gtk_event_box_new();
g_signal_connect(eventbox,"button-press-event", G_CALLBACK(eventbox_press_cb), this);
GtkAdjustment *adj_h=gtk_adjustment_new(0,0,100,1,5,10);
GtkAdjustment *adj_v=gtk_adjustment_new(0,0,100,1,5,10);
GtkWidget *viewport=gtk_viewport_new(adj_h, adj_v);
scrolledwindow=gtk_scrolled_window_new(adj_h, adj_v);
g_object_set(scrolledwindow, "hscrollbar-policy", GTK_POLICY_EXTERNAL, "vscrollbar-policy", GTK_POLICY_EXTERNAL, NULL);
gtk_container_add(GTK_CONTAINER(viewport), scrolledwindow);
gtk_widget_set_events(scrolledwindow, GDK_SCROLL_MASK);
g_signal_connect(scrolledwindow,"scroll-event",G_CALLBACK(eventbox_scroll_cb), this);
GtkWidget *box=gtk_box_new(GTK_ORIENTATION_VERTICAL,0);
adj=gtk_adjustment_new(0,0,110,1,5,10);
g_signal_connect(adj,"value-changed", G_CALLBACK(adj_changed_cb), this);
scrollbar=gtk_scrollbar_new(GTK_ORIENTATION_HORIZONTAL,adj);
gtk_box_pack_end(GTK_BOX(box),scrollbar, FALSE,FALSE,0);
image_from_surface=gtk_image_new_from_surface(surface);
gtk_container_add(GTK_CONTAINER(scrolledwindow),image_from_surface);
gtk_box_pack_start(GTK_BOX(box),viewport, TRUE,TRUE,0);
gtk_container_add(GTK_CONTAINER(eventbox),box);
我删除了前缀,例如,scrolledwindow是GtkScrolledWindow类型。附件顺序简要说明image-> scrolledwindow-> viewport-> box-> eventbox->(框架)如果删除scrolledwindow- > viewport容器,则图形只会增加,而不会减少。框添加滚动。您可能会注意到有3个,但是其中2个没有使用,仅在初始化必要的容器时才需要。在适合1个子窗口小部件的容器窗口小部件中,使用gtk_container_add函数插入。g_object_set设置其他属性,尤其是缺少scrolledwindow小部件的滚动条。您还可以通过GValue设置属性 GValue val = G_VALUE_INIT;
g_value_init(&val, G_TYPE_BOOLEAN);
g_value_set_boolean(&val, TRUE);
gtk_container_child_set_property(GTK_CONTAINER(data->notebook), gr, "tab-expand", &val);
滚动机制:将整个段除以100,并在回调函数中计算计划更改。从数字gtk_adjustment_new(0,0,110,1,5,10)中取100作为100 = 110-10。此外,关于参数化。
要参数化文本,我们使用pango库参数化标签。它允许您计算给定字体的文本大小(以像素为单位)及其拓扑大小,并将其导出到cairo层。
PangoLayout* get_width_height_of_text(char *text, char *font, float size, float *w, float *h)
{
GdkScreen *screen = gdk_screen_get_default();
PangoContext *context = gdk_pango_context_get_for_screen (screen);
PangoLayout *layout = pango_layout_new (context);
if(g_utf8_validate(text,-1,0))
{
pango_layout_set_text(layout,text,-1);
PangoFontDescription *desc=pango_font_description_new();
pango_font_description_set_family(desc,font);
pango_font_description_set_size(desc,size*1024);
pango_layout_set_font_description (layout, desc);
int width=0,height=0;
pango_layout_get_size(layout, &width, &height);
*w=(float) width/1024;
*h=(float) height/1024;
pango_font_description_free(desc);
}
else
{
printf(" UTF8\n");
}
return layout;
}
如您所见,pango以自己的单位计算大小。我突出显示了文本及其参数的单独类。class text_layout
{
private:
int fontsize;
public:
GString *text;
GString *font;
PangoLayout *layout;
int width;
int height;
text_layout(char *text, char *font, int fontsize);
void change_text_font_fontsize(char *new_text, char *new_font, int new_fontsize);
~text_layout();
text_layout(float num, char *font, int fontsize);
};
图表参数构成一个单独的类:class graphic_parameters
{
private:
text_layout y_text=text_layout(" y","Liberation Serif", 14);
text_layout x_text=text_layout(" x","Liberation Serif", 14);
text_layout *number=0;
float max=0;
float min=0;
text_layout *max_=0;
text_layout *min_=0;
GtkAdjustment *adj;
GtkWidget *scrollbar;
float gap_x=25;
float gap_y=5;
void create_axes_and_xy_labels(void);
public:
cairo_t *cr;
float *massiv=0;
int len=0;
int count_in_display=0;
float multiplier_x=6;
int offset=0;
float x_null=0;
float y_null=0;
int pos=0;
float margin=16;
int callback_width;
int callback_height;
int widget_width;
int widget_height;
int scroll_height=0;
GtkWidget *eventbox;
GtkWidget *scrolledwindow;
GtkWidget *image_from_surface;
cairo_surface_t *surface;
graphic_parameters(int width, int height);
~graphic_parameters();
void resize_graphic(int new_width, int new_height);
void create_one_dimensional_graphic(float *massiv, int size);
void update_graphic(int offset);
void change_graphic_adj(void);
void create_vertical_line(void);
};
该类加入主应用程序类。class externals
{
public:
graphic_parameters *param;
externals();
};
class appdata : public externals
{
public:
char *glade_name=(char*)"window.glade";
GtkApplication *app;
GtkWidget *win;
GtkNotebook *notebook;
GtkMenuBar *menubar;
appdata();
};
也就是说,在应用程序启动时将创建graphic_parameters类,并根据需要通过检查NULL,0来初始化内容。主要困难是调试所有转换。Segfaults发生了3次:在回调函数中错失了2次返回FALSE,并且没有在redraw函数中设置从数组退出的检查。Qt有一个现成的QCustomPlot类用于绘图,它具有更多的可能性。
链接到github