Две идеи рядом:
1. Сделать мышь для компьютера на акселерометре. В простейшем варианте будут проблемы с движением по негоризонтальным поверхностям, но, возможно, не сильно хитрой математикой + статистикой удастся обеспечить распознавание угла наклона;
2. Опять таки мышь, но в виде приложения для смартфона. Bluetooth там есть, камера с достаточным разрешением тоже, процессор, графический ускоритель -- фотографируй, рассчитывай, куда двинули корпус, отдавай в компьютер по Bluetooth-у. Нажатие кнопок, прокрутка -- сенсорный экран. Можно на него ещё и функцию трекбола навесить, чтобы корпус смарта не тягать, а по экрану пальцами, пальцами. А ещё в смартфонах бывает акселерометр (см. идею 1).
Заняться на досуге, что ли?
четверг, 14 августа 2014 г.
пятница, 30 августа 2013 г.
Makefile для проектов на контроллерах STM32
Проекты, если иное не указано явно, состоят из четырёх пользовательских файлов: main.cpp, main.hpp, interrupts.cpp и interrupts.hpp. Предполагается, что среда сборки настроена в соответствии с рекомендациями, приведёнными в предыдущей заметке.
Для обеспечения быстрой смены компилятора (при выходе новой версии) и/или программатора пути к их каталогам и некоторые команды вынесены в отдельные файлы, подключаемые в проект. Путь к компилятору находится в файле GccDir.mk, путь к программатору и его команды -- в Programmator.mk. Оба этих файла находятся в директории на уровень выше (../), что обеспечивает возможность централизованного перехода на новые версии компилятора/программатора для всех проектов сразу.
Makefile с путями к компилятору
Makefile с путями и командами программаторов OpenOCD и ST-Link. OpenOCD успел обновиться до версии 0.8.0.
Makefile проекта.
Для обеспечения быстрой смены компилятора (при выходе новой версии) и/или программатора пути к их каталогам и некоторые команды вынесены в отдельные файлы, подключаемые в проект. Путь к компилятору находится в файле GccDir.mk, путь к программатору и его команды -- в Programmator.mk. Оба этих файла находятся в директории на уровень выше (../), что обеспечивает возможность централизованного перехода на новые версии компилятора/программатора для всех проектов сразу.
Makefile с путями к компилятору
# GccDir.mk GCCDIRNAME = /d/bin/gcc-arm-none-eabi-4_8-2014q1-20140314-win32 #GCCDIRNAME = /d/bin/gcc-arm-none-eabi-4_8-2013q4-20131204-win32 #GCCDIRNAME = /d/bin/gcc-arm-none-eabi-4_7-2013q3-20130916-win32 #GCCDIRNAME = /d/bin/gcc-arm-none-eabi-4_7-2013q2-20130614-win32 #GCCDIRNAME = /d/bin/gcc-arm-none-eabi-4_7-2013q1-20130313-win32 # Вот сколько версий вышло с момента публикации
Makefile с путями и командами программаторов OpenOCD и ST-Link. OpenOCD успел обновиться до версии 0.8.0.
# Programmator.mk # ********************************************************************************************** # FLASH PROGRAMMING # # Alternate make target for flash programming only # # OpenOCD is run in "batch" mode with a special configuration file and a script file containing # the flash commands. When flash programming completes, OpenOCD terminates. # # Note that the script file of flash commands (script.ocd) is part of the project # # Programmers: Martin Thomas, Joseph M Dupre, James P Lynch # ********************************************************************************************** # OpenOCD directory OPENOCDDIR = $(GCCDIRNAME)/downloads/openocd-0.8.0 # OpenOCD binary OPENOCD = $(OPENOCDDIR)/bin-x64/openocd-x64-0.8.0.exe # OpenOCD config OPENOCDCONFIG =\ -f $(OPENOCDDIR)/scripts/interface/stlink-v2.cfg\ -f $(OPENOCDDIR)/scripts/board/stm32f3discovery.cfg ifeq ($(STARTFROMRAM), true) LOADCOMMAND = "load_image $(TARGET)-$(MCU)-$(BINFILESUFFIX).bin $(STARTADDRESS) bin" else LOADCOMMAND = "program $(TARGET)-$(MCU)-$(BINFILESUFFIX).bin $(STARTADDRESS) verify" endif # OpenOCD command OPENOCDCOMMAND =\ -c "init"\ -c "halt"\ -c $(LOADCOMMAND)\ -c "reset run"\ -c "shutdown" ## To unlock chip use next commands after "halt": # -c "flash protect 0 0 last off"\ # -c "shutdown" # ********************************************************************************************** # ST-Link programmator # ********************************************************************************************** STLINKDIR = "/c/Program Files (x86)/STMicroelectronics/STM32 ST-LINK Utility/ST-LINK Utility" STLINK = $(STLINKDIR)/ST-LINK_CLI.exe STLINKCOMMAND = -c SWD UR -Halt -P "$(TARGET)-$(MCU)-$(BINFILESUFFIX).bin" $(STARTADDRESS) -Rst -V program: @echo "STARTADDRESS = $(STARTADDRESS)" # $(STLINK) $(STLINKCOMMAND) $(OPENOCD) $(OPENOCDCONFIG) $(OPENOCDCOMMAND)
Makefile проекта.
TARGET = main # Использовать драйверы периферийных устройств, предоставленные ST DEFS = -DUSE_STDPERIPH_DRIVER # Адрес начала внутренней FLASH-памяти контроллера STARTADDRESS = 0x08000000 BINFILESUFFIX = flash # Выбор типа контроллера и названия демонстрационной платы MCU = cortex-m4 CHIP = STM32F37x BOARD = STM32373C-EVAL # Подключаем файлы с путями и командами компилятора и программатора include ../GccDir.mk include ../Programmator.mk # Путь к каталогу стандартный драйверов периферии, и вспомогательных библиотек STM32BASE = $(GCCDIRNAME)/downloads/$(CHIP)_DSP_StdPeriph_Lib_V1.0.0/Libraries # Путь к каталогу специфичных для демонстрационной платы определений и функций STM32373CBASE = $(STM32BASE)/../Utilities/STM32_EVAL # Пути поиска заголовочных файлов, и файлов исходных кодов INCLUDES =\ -I.\ -I'$(STM32BASE)/$(CHIP)_StdPeriph_Driver/inc'\ -I'$(STM32BASE)/$(CHIP)_StdPeriph_Driver/src'\ -I'$(STM32BASE)/CMSIS/Device/ST/$(CHIP)/Include'\ -I'$(STM32BASE)/CMSIS/Device/ST/$(CHIP)/Source/Templates'\ -I'$(STM32BASE)/CMSIS/Include'\ -I'$(STM32BASE)/../Project/$(CHIP)_StdPeriph_Templates'\ -I'$(STM32373CBASE)/Common'\ -I'$(STM32373CBASE)/$(subst -,_,$(BOARD))' # Программы, используемые при сборке проекта PREFIX = arm-none-eabi- AR = $(GCCDIRNAME)/bin/$(PREFIX)ar CC = $(GCCDIRNAME)/bin/$(PREFIX)gcc CXX = $(GCCDIRNAME)/bin/$(PREFIX)g++ AS = $(CC) LD = $(CC) OBJCOPY = $(GCCDIRNAME)/bin/$(PREFIX)objcopy OBJDUMP = $(GCCDIRNAME)/bin/$(PREFIX)objdump # Уровень оптимизации OPTIMIZE = -Os # Общие влаги компиляции FLAGS = -mcpu=$(MCU) -mthumb FLAGS += -MD FLAGS += $(INCLUDES) FLAGS += $(DEFS) # Скрипт линковщика, специфичный для контроллера # Возможно, придётся забрать его в каталог проекта, # и внести изменения (размер стека, объём внутренней # FLASH- и RAM-памяти) LD_SCRIPT = $(STM32BASE)/../Project/$(CHIP)_StdPeriph_Templates/TrueSTUDIO/$(BOARD)/STM32_FLASH.ld # Флаги, специфичные для компиляции ассемблерных файлов AFLAGS = $(FLAGS) AFLAGS += -x assembler-with-cpp -c # Флаги, специфичные для компиляции файлов C++ CXXFLAGS = $(FLAGS) CXXFLAGS += $(OPTIMIZE) CXXFLAGS += -g CXXFLAGS += -fno-exceptions -fno-rtti CXXFLAGS += -ffunction-sections -fdata-sections CXXFLAGS += -fno-threadsafe-statics CXXFLAGS += -funsigned-bitfields -fshort-enums CXXFLAGS += -Wall -Wextra CXXFLAGS += -Winline CXXFLAGS += -Wpointer-arith -Wredundant-decls CXXFLAGS += -Wshadow -Wcast-qual -Wcast-align -pedantic CXXFLAGS += -c -std=c++11 # Использовать библиотеку C-runtime, # оптимизированную для применения в микроконтроллерах USE_NANO = --specs=nano.specs # Использовать "заглушки" для некоторых # функций C-runtime, неиспользуемых в микроконтроллерах USE_SEMIHOST = --specs=rdimon.specs # Флаги линкера LD_FLAGS = -mcpu=$(MCU) LD_FLAGS += -mthumb LD_FLAGS += -Wl,-Map="$(MAP)",--cref LD_FLAGS += -Wl,--gc-sections LD_FLAGS += -T$(LD_SCRIPT) LD_FLAGS += $(USE_NANO) LD_FLAGS += $(USE_SEMIHOST) # Для использования в проекте функций, обращающихся к C- C++-runtime # после -lrdimon добавить -lc и/или -lstdc++ LD_FLAGS += -Wl,$(LINKPATH),--start-group -lrdimon -Wl,--end-group # Флаги для objcopy, создание бинарного файла прошивки CPFLAGS = --output-target=binary # Флаги для objdump, создание листинга программы (ассемблерный код). ODFLAGS = -h -S # Чтобы не разводить свалку объектных файлов в корневом каталоге проекта, будем складывать их в отдельный каталог OBJDIR = ./obj # Начальная инициализация микроконтроллера STM32STARTUPFILENAME = startup_$(CHIP) STM32SYSTEMFILENAME = system_$(CHIP) # Запуск микроконтроллера STM32STARTUP = $(STM32BASE)/CMSIS/Device/ST/$(CHIP)/Source/Templates/gcc_ride7/$(STM32STARTUPFILENAME).s STM32SYSTEM = $(STM32BASE)/CMSIS/Device/ST/$(CHIP)/Source/Templates/$(STM32SYSTEMFILENAME).c # Библиотека ввода-вывода (GPIO) GPIOSTDFILENAME = $(CHIP)_gpio GPIOSTD = $(STM32BASE)/$(CHIP)_StdPeriph_Driver/src/$(GPIOSTDFILENAME).c # Библиотека управления тактированием микроконтроллера (RCC) RCCSTDFILENAME = $(CHIP)_rcc # RCC stdlib code RCCSTD = $(STM32BASE)/$(CHIP)_StdPeriph_Driver/src/$(RCCSTDFILENAME).c # Определения и функции, специфичные для демонстрационной платы EVBOARDHARDWFILENAME = $(subst -,_,$(BOARD)) EVBOARDHARDW = $(STM32373CBASE)/$(subst -,_,$(BOARD))/$(EVBOARDHARDWFILENAME).c # Обработчики прерываний INTWORKFILENAME = interrupts INTWORK = ./$(INTWORKFILENAME).cpp # Создание map-файла MAP = $(TARGET).map # Пути к объектным файлам из корневого каталога проекта STM32STARTUPOBJ = $(OBJDIR)/$(STM32STARTUPFILENAME).o STM32SYSTEMOBJ = $(OBJDIR)/$(STM32SYSTEMFILENAME).o GPIOSTDOBJ = $(OBJDIR)/$(GPIOSTDFILENAME).o RCCSTDOBJ = $(OBJDIR)/$(RCCSTDFILENAME).o EVBOARDHARDWOBJ = $(OBJDIR)/$(EVBOARDHARDWFILENAME).o INTWORKOBJ = $(OBJDIR)/$(INTWORKFILENAME).o TARGETOBJ = $(OBJDIR)/$(TARGET).o # Объектные файлы, из которых будет собираться финальный образ OBJECTS =\ $(STM32STARTUPOBJ) $(STM32SYSTEMOBJ) $(GPIOSTDOBJ)\ $(RCCSTDOBJ) $(EVBOARDHARDWOBJ) $(INTWORKOBJ)\ $(TARGETOBJ) # Сборка финального образа программы, и её листинга all: $(TARGET)-$(MCU).axf @echo "....copying" $(OBJCOPY) $(CPFLAGS) $^ $(TARGET)-$(MCU)-$(BINFILESUFFIX).bin $(OBJDUMP) $(ODFLAGS) $^ > $(TARGET)-$(MCU).lst # Линковка промежуточного образа программы $(TARGET)-$(MCU).axf: $(OBJECTS) $(LDSCRIPT) @echo "...linking" $(LD) $^ $(LD_FLAGS) -o $@ $(STM32STARTUPOBJ): $(STM32STARTUP) @echo "..assembling of $^" $(AS) $(AFLAGS) $< -o $@ $(STM32SYSTEMOBJ): $(STM32SYSTEM) @echo ".compiling of $^" $(CXX) $(CXXFLAGS) $< -o $@ $(GPIOSTDOBJ): $(GPIOSTD) @echo ".compiling of $^" $(CXX) $(CXXFLAGS) $< -o $@ $(RCCSTDOBJ): $(RCCSTD) @echo ".compiling of $^" $(CXX) $(CXXFLAGS) $< -o $@ $(EVBOARDHARDWOBJ): $(EVBOARDHARDW) @echo ".compiling of $^" $(CXX) $(CXXFLAGS) $< -o $@ $(INTWORKOBJ): $(INTWORK) @echo ".compiling of $^" $(CXX) $(CXXFLAGS) $< -o $@ $(TARGETOBJ): $(TARGET).cpp @echo ".compiling of $^" $(CXX) $(CXXFLAGS) $< -o $@ clean: rm -f $(OBJECTS) $(TARGET)*.axf *.map *.lst $(OBJDIR)/*.d *.bin *.o # Создаём каталог для объектных файлов, если уже создан -- ошибки не будет -include $(shell mkdir obj 2> /dev/null) $(wildcard obj\*)
среда, 7 августа 2013 г.
Настройка среды сборки для контроллеров ARM (AT91SAM7Sxxx и STM32F3xx)
- 1. Конфигурация системы
- Развёртывание и конфигурирование среды сборки производилось в операционной системе Windows 7 x86-64. Использовались демонстрационная плата AT91SAM7S-EK с JTAG-отладчиком J-Link-ARM, шедшим с ней в комплекте, и плата STM32373C-EVAL.
- 2. Переключение Windows в тестовый режим
- Ранее на этом же компьютере был установлен драйвер ввода-вывода dlportio, что потребовало переключения Windows в тестовый режим, в котором отсутствует проверка цифровой подписи драйверов. Переключение между режимами описано в этой статье, там же приведена и ссылка на утилиту, с помощью которой производится переключение.
- 3. Компилятор gcc-arm-none-eabi
- На сайте кросскомпилятора GCC можно скачать требуемую версию GCC-ARM, в данный момент используется версия GCC ARM Embedded 4.7-2013-q1-update. Архив нужно распаковать в выбранный каталог, в переменную окружения Path операционной системы путь к каталогу disk:\path_to_directory\gcc-arm-none-eabi-4_7-2013q1-20130313-win32\bin добавлять нет необходимости, он явно задан в Makefile проекта, который описывается в следующей заметке.
- 4. Библиотека периферии для контроллеров AT91SAM7Sxx демонстрационной платы AT91SAM7S-EK
- Для доступа к регистрам контроллеров по их псевдонимам, а не по адресам, требуется скачать библиотеки периферии. На сайте Atmel найти их можно по ключевым словам 'demoboard-name Software Package for IAR 5.2, Keil and GNU'. Кроме того, архив содержит некоторые утилиты и драйверы, которые могут быть полезны в разработке (TWI, LCD, Ethernet и другие).
- 5. Библиотека периферии для контроллеров STM32F3XX
- Архив с библиотеками периферии. В архиве находятся следующие каталоги:Libraries/CMSIS (Cortex Microcontroller Software Interface Standard -- стандартные определения для контроллеров на ядре ARM Cortex); Libraries/STM32F37x_I2C_CPAL_Driver (исходные коды и заголовочные файлы библиотеки шины I2C); Libraries/STM32F37x_StdPeriph_Driver (исходные коды и заголовочные файлы библиотеки работы с периферией контроллера).Project/STM32F37x_StdPeriph_Examples (примеры использования библиотеки CMSIS); Project/STM32F37x_StdPeriph_Templates (шаблоны проектов для различных средств разработки).Utilities/STM32_EVAL/Common (шрифты для ЖКИ-дисплея отладочной платы STM32373C-EVAL и функции вывода); Utilities/STM32_EVAL/STM32373C_EVAL (базовые исходные коды и заголовочные файлы для периферии, размещённой на отладочной плате).
- 6. Отладчик OpenOCD
- Для программирования контроллера платы AT91SAM7S-EK использовался USB-JTAG адаптер J-Link-ARM, плата STM32373C-EVAL может программироваться как через JTAG, так и посредством размещённого на ней же USB-адаптера ST-LINK V2. Для программирования обеих плат использовалась программа OpenOCD.
- 7. Установка драйверов libUsb для адаптеров JLink и ST-LINK V2 с помощью утилиты zadig
- После подключения к компьютеру адаптеров они не распознаются системой автоматически. Для их корректной работы с OpenOCD нужно скачать утилиту zadig, с помощью которой производится установка драйверов USB для адаптеров. После её запуска в выпадающем списке будут показаны USB-устройства, для которых не установлены драйверы. В списке драйверов (Target Driver) следует выбрать драйвер libusb-win32 (v1.2.6.0), и нажать кнопку Install Driver.
четверг, 29 ноября 2012 г.
Boost Spirit::Qi, разбор выражений с числом элементов, большим десяти
При попытке разобрать парсером Spirit::Qi выражение, в котором более десяти элементов, компилятор сообщает об ошибках вида error: '_10' is not a member of 'qi'. Продолжительные и нерегулярные :-) раскопки исходников Qi, а так же связанных с ним Phoenix-а и fusion-а, в конце концов привели к следующим определениям, которые нужно изменить в нужную для себя сторону:
После их явного задания требуемые данные успешно распарсились в вектор кортежей:
#define PHOENIX_LIMIT 20 /* Или сколько там надо их парсить... */ #define FUSION_MAX_VECTOR_SIZE PHOENIX_LIMIT #define BOOST_RESULT_OF_NUM_ARGS PHOENIX_LIMIT
После их явного задания требуемые данные успешно распарсились в вектор кортежей:
namespace ph = boost::phoenix;
namespace qi = boost::spirit::qi;
using boost::spirit::ascii::space_type;
//--------------------------------------------------------------------------
typedef double ValueType;
typedef ValueType First; static const size_t FirstIndex = 0;
typedef ValueType Second; static const size_t SecondIndex = FirstIndex + 1;
typedef ValueType Third; static const size_t ThirdIndex = SecondIndex + 1;
typedef ValueType Fourth; static const size_t FourthIndex = ThirdIndex + 1;
typedef ValueType Fifth; static const size_t FifthIndex = FourthIndex + 1;
typedef ValueType Sixth; static const size_t SixthIndex = FifthIndex + 1;
typedef ValueType Seventh; static const size_t SeventhIndex = SixthIndex + 1;
typedef ValueType Eight; static const size_t EightIndex = SeventhIndex + 1;
typedef ValueType Ninth; static const size_t NinthIndex = EightIndex + 1;
typedef ValueType Tenth; static const size_t TenthIndex = NinthIndex + 1;
typedef ValueType Eleventh; static const size_t EleventhIndex = TenthIndex + 1;
typedef ValueType Twelfth; static const size_t TwelfthIndex = EleventhIndex + 1;
typedef bool Locked; static const size_t LockedIndex = TwelfthIndex + 1;
//--------------------------------------------------------------------------
typedef std::tuple<First,Second,Third,Fourth,Fifth,Sixth, \
Seventh,Eight,Ninth,Tenth,Eleventh,Twelfth, \
Locked> Data;
typedef std::vector<Data> DataContainer;
//--------------------------------------------------------------------------
struct phoenix_make_tuple_impl
{ /* Tuple create adapter */
template <typename... Args>
struct result
{
typedef std::tuple<Args...> type;
};
template <typename... Args>
typename result<Args...>::type operator () (Args... args) const
{
return std::make_tuple(args...);
}
};
ph::function<phoenix_make_tuple_impl> const phoenix_make_tuple = phoenix_make_tuple_impl();
//--------------------------------------------------------------------------
template <typename Iterator,typename Container> \
struct ParserGrammar : qi::grammar \
<Iterator,Container(),qi::blank_type> \
{
typedef typename Container::value_type Value;
ParserGrammar(Container& container) : \
ParserGrammar::base_type(start)
{
start = qi::lit("Data") >> qi::lit("=") >> \
containerData \
[ph::push_back(ph::ref(container),qi::_1)] % \
qi::eol;
containerData = \
(first >> second >> third >> fourth >> \
fifth >> sixth >> seventh >> eight >> \
ninth >> tenth >> eleventh >> twelfth >> \
locked) \
[qi::_val = phoenix_make_tuple \
(qi::_1,qi::_2,qi::_3,qi::_4,qi::_5,qi::_6, \
qi::_7,qi::_8,qi::_9,qi::_10,qi::_11,qi::_12, \
qi::_13)];
first = second = third = fourth = fifth = \
sixth = seventh = eight = ninth = tenth = \
eleventh = twelfth = qi::double_;
locked = qi::bool_;
return;
}
qi::rule<Iterator,Container(), qi::blank_type> start;
qi::rule<Iterator,Value(), qi::blank_type> containerData;
qi::rule<Iterator,double()> \
first,second,third,fourth,fifth,sixth, \
seventh,eight,ninth,tenth,eleventh,twelfth;
qi::rule<Iterator, bool()> locked;
};
//--------------------------------------------------------------------------
const std::string dataString = "Data = 1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8 9.9 10.10 11.11 12.12\n\
10.10 20.20 30.30 40.40 50.50 60.60 70.70 80.80 90.90 100.100 110.110 120.120\n";
вторник, 24 июля 2012 г.
Компиляция проектов Qt версии ниже 4.8.1 с использованием MinGW GCC 4.7.0
При компиляции проектов Qt версии ниже 4.8.1 компилятором MinGW GCC 4.7.0 с использованием флага -std=c++11 некоторые макросы распознаются как пользовательские литералы, что приводит к ошибкам компиляции. Для версии Qt 4.8.1 выпущен патч, а для предыдущих версий предлагается следующий заголовочный файл, корректно (с точки зрения C++11) определяющий нужные макросы:
Включение этого файла после подключенных заголовочных файлов Qt позволяет "малой кровью", без пересборки самой библиотеки Qt, решить проблему этой ошибки.
#ifndef CXX0XCOMPATIBILITY_HPP__20120723__1427
#define CXX0XCOMPATIBILITY_HPP__20120723__1427
/*
* For compatibility with C++-0x mode in GCC 4.7.x
*/
//-------------------------------------------------------------------------
# ifndef QT_NO_DEBUG
# ifdef QLOCATION
# undef QLOCATION
# define QLOCATION "\0" __FILE__ ":" QTOSTRING(__LINE__)
# ifndef QT_NO_KEYWORDS
# ifdef METHOD
# undef METHOD
# define METHOD(a) qFlagLocation("0" #a QLOCATION)
# endif
# endif
# endif
# ifdef SLOT
# undef SLOT
# define SLOT(a) qFlagLocation("1" #a QLOCATION)
# endif
# ifdef SIGNAL
# undef SIGNAL
# define SIGNAL(a) qFlagLocation("2" #a QLOCATION)
# endif
# else
# ifndef QT_NO_KEYWORDS
# ifdef METHOD
# undef METHOD
# define METHOD(a) "0" #a
# endif
# endif
# ifdef SLOT
# undef SLOT
# define SLOT(a) "1" #a
# endif
# ifdef SIGNAL
# undef SIGNAL
# define SIGNAL(a) "2" #a
# endif
# endif
#endif//
Включение этого файла после подключенных заголовочных файлов Qt позволяет "малой кровью", без пересборки самой библиотеки Qt, решить проблему этой ошибки.
воскресенье, 26 февраля 2012 г.
Прочистка форсунок стеклоомывателя
При езде в сырую погоду часто случается досадная неприятность: грязью из-под колёс забиваются форсунки стеклоомывателя. После чего на очистку лобового (а у кого и заднего) стекла приходится тратить гораздо больше времени. Разумеется, это очень снижает безопасность вождения. При попытке прочистить каналы форсунок простой проволокой, зачастую, грязь только проталкивается дальше, к трубке подачи жидкости. В худшем случае проволока может обломиться внутри форсунки, и тогда её остаётся только заменить на новую. А до автомагазина ещё надо доехать... Решение по прочистке было найдено неожиданно, и оказалось очень эффективным. Прочищать надо такой специальной стоматологической штуковиной, под названием эндодонтический файл. Можно выпросить его (с подходящим диаметром) в стоматологическом кабинете, а можно купить в магазине, торгующем медтехникой. Цена их крайне мала -- от 10 рублей за штуку, делаются они из прочной, гибкой стали, так что сломать его внутри форсунки почти невозможно. Так же он имеет конусообразную форму, и резьбу, что позволяет вкрутить его в скопление грязи/ржавчины/чем-там-ещё-может-забиться-форсунка, и вытащить всё это богатство наружу. В общем -- рекомендую. Очень полезная штука.
четверг, 29 декабря 2011 г.
Promote widget в Qt Creator: что это такое, и как его использовать
При создании формы графического интерфейса в Qt Creator-е зачастую возникает необходимость изменить поведение размещённых на форме визуальных компонентов. Для этого в нём (Creator-е) существует механизм promote-инга (корректный перевод не знаю). В качестве примера рассмотрим добавление объекту QLabel возможности реагирования на отпускание на нём левой кнопки мыши (ЛКМ).
Выделив необходимый компонент на форме, в меню ПКМ выбираем пункт Promote to.... Откроется меню задания имени класса-обёртки, и его заголовочного файла. Заголовочный файл может находиться и не в рабочем каталоге с файлом формы (*.ui), можно задать ему либо абсолютный путь (возможны проблемы при переносе проекта между платформами), либо относительный, от рабочего каталога. Дадим классу имя TestPromoter (Promoted class name:), его заголовочный файл -- ./TestPromoter.hpp (Header file:). Нажимаем кнопку Add, и QLabel оказывается "обёрнут" в созданный класс promoter-а.
Теперь нужно вручную создать заголовочный файл, и файл реализации нового класса:
Таким образом можно реализовать расширение функциональности визуальных объектов Qt Creator-а.
Выделив необходимый компонент на форме, в меню ПКМ выбираем пункт Promote to.... Откроется меню задания имени класса-обёртки, и его заголовочного файла. Заголовочный файл может находиться и не в рабочем каталоге с файлом формы (*.ui), можно задать ему либо абсолютный путь (возможны проблемы при переносе проекта между платформами), либо относительный, от рабочего каталога. Дадим классу имя TestPromoter (Promoted class name:), его заголовочный файл -- ./TestPromoter.hpp (Header file:). Нажимаем кнопку Add, и QLabel оказывается "обёрнут" в созданный класс promoter-а.
Теперь нужно вручную создать заголовочный файл, и файл реализации нового класса:
#include <QLabel>
#include <QMouseEvent>
//-------------------------------------------------------------------------
/*
TestPromoter.hpp
*/
//-------------------------------------------------------------------------
class TestPromoter : public QLabel
{
Q_OBJECT:
protected:
virtual void mouseReleaseEvent(QMouseEvent* ev);
public:
TestPromoter(QWidget* parent = 0,Qt::WindowFlags f = 0);
TestPromoter(const QString& text,QWidget* parent = 0,Qt::WindowFlags f = 0);
};
#include "./TestPromoter.hpp"
//-------------------------------------------------------------------------
/*
TestPromoter.cpp
*/
//-------------------------------------------------------------------------
TestPromoter::TestPromoter(QWidget* parent,Qt::WindowFlags f) : \
QLabel(parent,f) \
{
return;
}
TestPromoter::TestPromoter(const QString& text,QWidget* parent,Qt::WindowFlags f) : \
QLabel(text,parent,f) \
{
return;
}
void TestPromoter::mouseReleaseEvent(QMouseEvent* ev)
{
if(ev->button() == Qt::LeftButton)
{
//Код, который нужно выполнить по указанному событию
}
QLabel::mouseReleaseEvent(ev);
return;
}
Таким образом можно реализовать расширение функциональности визуальных объектов Qt Creator-а.
Подписаться на:
Сообщения (Atom)