Tcl

Tk

Tcl/Tk

Статьи

Завуалированная тривиальность

Единая страна

Завуалированная тривиальность

Завуалированная тривиальность - doro.poltava.ua

Завуалированная тривиальность

Ускорение выполнения команды expr

Команда expr выполняет двойную подстановку своих аргументов. Сначала препроцессором команд, затем препроцессором выражений. Двойная подстановка замедляет скорость выполнения команды expr. Но, в подавляющем большинстве случаев, двойная подстановка не требуется. Чтобы избежать двойной подстановки, необходимо выражение заключить в фигурные скобки { }.

Например:

set a 5
set b 1

# Чаще всего, пишем так:
expr $a - $b

# Заключим в фигурные скобки, повысыв скорость в несколько раз:
expr { $a - $b }

Но, бывают случаи, когда без двойной подстановки не обойтись. Например:

set a 5
set b 1
set sign -

expr $a $sign $b

Выбор способа хранения структурированых данных

Пусть вам необходимо каким-то способом организовать хранение, в памяти программы, данных следующей структуры:

# id - уникальный идентификатор
# data - некие данные по уникальному идентификатору
# id | data
 1 {Это данные для один}
 2 {Это данные для два}
 ...
 N {Это данные для N}

Эти данные можно хранить как список списков:

lappend ldata [list 1 {Это данные для один}]
lappend ldata [list 2 {Это данные для два}]
 ...
lappend ldata [list N {Это данные для N}]

или как массив:

set ldata(1) {Это данные для один}
set ldata(2) {Это данные для два}
 ...
set ldata(N) {Это данные для N}

В последующем, понадобится извлечение данных по уникальному идентификатору. Получение денных из списка

lsearch -index 0 -integer -inline $ldata $искомый_id

работает в несколько сот раз медленнее, чем извлечение данных из массива

$ldata($искомый_id)

Хотя, если предполагается последовательный доступ к данным

foreach el $ldata {
  # код по обработке одного элемента списка
}

хранение в списке - более предпочтительно.

Десятисекундный таймер

proc Timer10Seconds {
  # некий код функционала таймера
  # . . .
  after 10000 Timer10Seconds
}

Вынос тела цикла в отдельную процедуру

Если у вас есть длинный цикл, оформление тела цикла отдельной процедурой, будет работать быстрее.

# Первоначальный код цикла
for { set i 0 } { $i < 1000000 } { incr i } {
  expr { $i * $i }
}


# Модифицированный, работающий быстрее, код цикла
proc Body { i } {
  expr { $i * $i }
}

for { set i 0 } { $i < 1000000 } { incr i } {
  Body $i
}

"Размораживание" интерфейса Tk

Рассмотрим случай, когда необходимо выполнять какую-либо длительную операцию (чтение по сети, загрузка локального файла), с небоходимостью максимально возможно обрабатывать пользовательские итерфейсные события - управление мышкой, клавиатурой и вызуализацией данных, полученных как результат длительной операции.

Допустим нам необходимо получить по сети некий графический файл, и вызуализировать его в каком-то Tk виджете. Лучший способ для исключения "замораживания" интерфейса - выполнить длительную операцию в отдельном потоке. Но мы работаем с ограниченными по памяти системными ресурсами, как пример - MapTour под WinCE, и работа в потоке исключена.

В таком случае, как один из способов, можно использовать механизм виртуальных событий Tk.

# Создаём виртуальное событие на несуразную комбинацию клавиш
event add <<TilesRecived>> <Control-Shift-Meta-a>
# привязываем новосозданное событие к окну canvas
bind $cnv <<TilesRecived>> [list Tiles:Visual $cnv %d]
# Запускаем в нужный момент процедуру получения тайла (графического файла) из сети
after idle [list Tiles:Get $cnv]

proc Tiles:Get { cnv } {
  # Код по получению изображения из сети
  # . . .
  # бинарные данные изображения хранятся в переменной bdata

  # Получив данные, генерируем виртуальное событие
  # которое запустит функцию создания и визуализации изображения
  after idle [list event generate $cnv <<TilesRecived>> -data $bdata]
}

proc Tiles:Visual { cnv bdata } {
  # Создаём изображение
  set iname [image create photo -height 256 -width 256]
  $iname put $bdata
  # Визуализируем изображение на canvas в координате x,y
  $cnv create image $x $y -image $iname
}

Wrapping

Часто необходимо урезать/расширить функционал стандартных функций или полностью его переопределить.
Для этого можно воспользоваться командой rename.

Добавим для виджета label команду определения координат верхнего левого угла:

# создаем виджет label с надписью "Coords"
# виджет порождает новую команду - .l 
pack [label .l -text Coords] -padx 10 -pady 10
# переименуем команду .l в .l_old
rename .l .l_old
# опишем новое поведение для вызовов команды .l
proc .l { args } {
  set cmd [lindex $args 0]
  if { $cmd eq "coords" } {
    # код новой команды определения координат
    update idletasks
    return [list [winfo rootx .l] [winfo rooty .l]]
  } else {
    # выполняем все стандартные команды виджета label
    eval .l_old $args
  }
}
# визуализируем координаты в label
.l configure -text [.l coords]

Подобный приём можно использовать в довольно многих случаях. Например, для создания мегавиджетов - это виджет, состоящий из нескольких стандартных виджетов, но воспринимающийся системой как атомарный, целостный виджет.

Полупрозрачность примитивов Canvas

Как известно, примитивы canvas (линии, полигоны, ...) не обладают возможностью програчности. Но, данную проблему можно решить используя маску bitmap изображения.

Так выглядит регион (подложка для кнопок) в обычном случае (без применения bitmap маски):

Регион без применения bitmap маски
Регион без применения bitmap маски

# код примитива Регион без применения bitmap маски
$canvas create rectangle $x1 $y1 $x2 $y2 -outline cyan4 -fill grey90

А так выглядит регион (подложка для кнопок) с bitmap маской:

Регион с bitmap маской
Регион с bitmap маской

# код примитива Регион с bitmap маской
$canvas create rectangle $x1 $y1 $x2 $y2 -outline cyan4 -fill grey90 -stipple transparent.xbm

Предварительно, необходимо создать bitmap-файл transparent.xbm следующей структуры:

# bitmap-файл transparent.xbm
#define transparent_width 2
#define transparent_height 2
static unsigned char transparent_bits[] = {
   0x01, 0x02 };

В результате получили визуальную полупрозрачность подложки для кнопок.



Главная
Программные продукты
Freesource программные продукты
Статьи
Нечто стихотворное
Контакт
GPSMTA - GPS трекер / GPS мониторинг для Android
GPSM - программно-аппаратный комплекс GPS мониторинга
MapTour - GPS навигация для Туристов
MapSurfing - просмотрщик географических карт
DGraf - визуализация графов
ViCer - домашняя система видеонаблюдения
FPS - бесплатная система GPS мониторинга
Jeans - Финансово-складской учёт
Cerber - Финансовый учёт игорного зала
Visimap - Визуальная карта
BIB - Картотека книг
2DO - Учёт рабочего времени
Выписка - склад
Расчёт зарплаты
Krp - визуализатор связанных структур
Xboat - проэктировщик малых судов
XSQLite - visualisator DB SQLite
Текстовый редактор XEdJ
Copyright © Эдуард Зозуля
Проверка PR и ТИЦ