[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Аналог на GDK_INVERT при cairo/GTK 3
From: |
Yavor Doganov |
Subject: |
Re: Аналог на GDK_INVERT при cairo/GTK 3 |
Date: |
Tue, 12 Nov 2019 11:56:04 +0200 |
User-agent: |
Wanderlust/2.15.9 (Almost Unreal) SEMI-EPG/1.14.7 (Harue) FLIM/1.14.9 (Gojō) APEL/10.8 EasyPG/1.0.0 Emacs/26 (x86_64-pc-linux-gnu) MULE/6.0 (HANACHIRUSATO) |
Kaloian Doganov wrote:
> On Mon, 2019-11-11 at 01:40 +0200, Yavor Doganov wrote:
> > Проблемът е, че при движението на мишката правоъгълника се променя и
> > нещо трябва да „трие“ следите.
> Тази (или всяка аналогична на GDK_INVERT) техника, обаче, разчита на
> това, че в даден момент знаем дали на екрана има нарисувана селекция
> или не. [...] Визуално, резултатът е грозен артефакт на екрана.
> Всичко това е демонстрирано в screenshot-ите по- долу.
Да, наистина. Страхотна функция си използвал, много ми помогна да
вникна в нещата, сякаш задейства дремещи когнитивни способности :-).
Винаги съм се чудил защо учители и университетски преподаватели
избягват подобни нагледни примери. А добрият пример е отлична
предпоставка за успешен учебен процес.
> Иронията е, че това разминаване нямаше да се случи ако освен всичко
> друго ::draw рисуваше и селекцията.
Така е, убедих се вече.
> > Да, това е типична практика при много програми, писани за GTK 2 (и
> > 1.2, BTW), работи си без проблем.
>
> Ако това е типична практика, значи масово не са се спазвали правилата
> на GUI framework-а
Ами да. Вече сигурно над 20 програми съм портнал, почти всяка
по-сложна от тях си позволява да рисува извън expose_event. API-то го
позволява, дори и при GTK 3 с gdk_cairo_create и по-новите функции
като gdk_window_begin_draw_frame.
> > Дори и да се чертае само от ::draw, това няма как да промени нещата и
> > няма как да ме улесни по никакъв начин.
>
> Ако рисуването на widget-а включва и рисуването на селекцията (ако има
> активна такава), и в същото време прерисуваш напълно widget-а при
> движение на мишката, това ще реши проблема ти. Няма да има нужда да
> триеш от екрана старото състояние на селекцията, понеже то ще се
> забърсва при изрисуването на графиката.
Разбира се, това е толкоз просто и логично.
> Това, което ти предлагам, е да сложиш рисуването на активната селекция
> на последно място в ::draw.
Това направих. Промених draw_selection и
gtk_plot_canvas_child_draw_selection да приемат аргумент cairo_t,
и включих в края на ::draw:
switch (canvas->action) {
case GTK_PLOT_CANVAS_ACTION_DRAG:
case GTK_PLOT_CANVAS_ACTION_RESIZE:
if (canvas->active_item)
gtk_plot_canvas_child_draw_selection (cr, canvas, canvas->active_item,
canvas->drag_area);
break;
case GTK_PLOT_CANVAS_ACTION_INACTIVE:
if (canvas->active_item && canvas->state == GTK_STATE_SELECTED)
gtk_plot_canvas_child_draw_selection (cr, canvas, canvas->active_item,
canvas->active_item->drag_area);
break;
case GTK_PLOT_CANVAS_ACTION_SELECTION:
draw_selection (cr, canvas, NULL, canvas->drag_area);
break;
default:
break;
}
Навсякъде в event handler-ите замених извикването на тези две функции
с gtk_widget_queue_draw (също и в gtk_plot_canvas_unselect). В
draw_selection, преди действителното чертане, пльоснах
cairo_set_source_rgb (cr, 0, 0, 0);
Това е абсолютно необходимо, за да се извършва действителното чертане,
защото в началото на имплементацията на ::draw имам:
cairo_set_source_surface (cr, pixmap, 0, 0);
Притеснява ме малко gtk_plot_canvas_button_release, където не съм
сигурен дали едно от условията
if (canvas->action != GTK_PLOT_CANVAS_ACTION_INACTIVE && veto)
ще пасне на логиката в ::draw.
> Не само, че не е много сложно, ами е по-просто от това, което
> GtkPlotCanvas прави в момента.
Да, съгласен съм. Единственият недостатък е, че се прерисува всичко
доста пъти. Но по-важното е, че работи.
> > Не, това е генерален проблем при GTK и cairo, който не съществува при
> > GDK 2. Както е писал потребителя във връзката, която дадох.
>
> Не съм съгласен с тази оценка. Поне от това, което виждам дотук, GTK 2
> е бил използван неправилно.
Да, не съм бил прав. Благодаря за насоките.