Помощь - Поиск - Пользователи - Календарь
Полная версия: Помогите с подгрузкой изображения в БД. С++
Форум «Всё о Паскале» > Современный Паскаль и другие языки > Ада и другие языки
alecsandr
У меня есть программа, АРМ администратора компьютерного магазина, вроде когда я беру изображения из БД все нормально картинка отображается в DBImagе, но когда жму кнопку "ДОБАВИТЬ" (Добавиьт данные в таблицу) он выбивает ошибку поэтому даже проверить не могу работоспособность добавления. Помогите пожалуйто с добавлением буду очень благодарен. В архиве прикрепленном снизу вся прога с БД. ВСЕ РАЗАРХИВИРУЙТЕ В ОДНУ ПАПКУ
IUnknown
Цитата
В архиве прикрепленном снизу вся прога с БД
Ну, и где? Архив, говорю, снизу чего прикреплен? Под монитором посмотрел - нету...
alecsandr
Цитата(IUnknown @ 5.06.2011 12:46) *

Ну, и где? Архив, говорю, снизу чего прикреплен? Под монитором посмотрел - нету...

иЗВИНИ ОН НЕ ОТПРАВИЛСЯ))
IUnknown
Ну, во-первых, вот это:
if (Form2->DataSource1->DataSet->FieldByName("Photo")==NULL)
- неправильно. У тебя никогда не поймается таким образом пустая строка. Ловить пустоту надо вот так:
if ((Form2->DataSource1->DataSet->FieldByName("Photo")->AsString).IsEmpty())


А во-вторых: не надо при добавлении новой записи в базу записывать полный путь к файлу. Достаточно только имени. Иначе сам подумай, что будет пытаться открыть LoadFromFile вот тут: LoadFromFile("photo\\" + strphoto), если в strphoto УЖЕ записан полный путь? Нехорошо, вылет программы обеспечен.

Вот так попробуй:
  if ((Form2->DataSource1->DataSet->FieldByName("Photo")->AsString).IsEmpty()) // Изменения здесь
{
Form2->ADOQuery1->Edit();
Form2->DataSource1->DataSet->FieldValues["Photo"]= "none.jpg"; // и здесь
}
strphoto = Form2->DataSource1->DataSet->FieldValues["Photo"];
Form2->DataSource1->DataSet->Post();
Form2->DBImage1->Stretch=true;
Form2->DBImage1->Picture->LoadFromFile("photo\\" + strphoto);

alecsandr
Цитата(IUnknown @ 5.06.2011 14:19) *

Ну, во-первых, вот это:
if (Form2->DataSource1->DataSet->FieldByName("Photo")==NULL)
- неправильно. У тебя никогда не поймается таким образом пустая строка. Ловить пустоту надо вот так:
if ((Form2->DataSource1->DataSet->FieldByName("Photo")->AsString).IsEmpty())


А во-вторых: не надо при добавлении новой записи в базу записывать полный путь к файлу. Достаточно только имени. Иначе сам подумай, что будет пытаться открыть LoadFromFile вот тут: LoadFromFile("photo\\" + strphoto), если в strphoto УЖЕ записан полный путь? Нехорошо, вылет программы обеспечен.

Вот так попробуй:
  if ((Form2->DataSource1->DataSet->FieldByName("Photo")->AsString).IsEmpty()) // Изменения здесь
{
Form2->ADOQuery1->Edit();
Form2->DataSource1->DataSet->FieldValues["Photo"]= "none.jpg"; // и здесь
}
strphoto = Form2->DataSource1->DataSet->FieldValues["Photo"];
Form2->DataSource1->DataSet->Post();
Form2->DBImage1->Stretch=true;
Form2->DBImage1->Picture->LoadFromFile("photo\\" + strphoto);



Блин он все ровно не пашет, пишет что не найден none.jpg
и останавливается на этой строчке
 Form2->DBImage1->Picture->LoadFromFile("photo\\" + strphoto);
IUnknown
Цитата
Блин он все ровно не пашет, пишет что не найден none.jpg
и останавливается на этой строчке
Да что ж такое?

Нажмите для просмотра прикрепленного файла
Опять у меня все не так, как нужно? Не останавливается, грузит форму с пустыми полями, чтоб их можно было обновить. Что ж я все-время не так делаю, а? Сколько раз повторять, я ПРОВЕРЯЮ код, который выкладываю. Если не работает - кода просто НЕТ. Так что ищи ошибку у себя...
alecsandr
Цитата(IUnknown @ 5.06.2011 16:30) *

Да что ж такое?

Нажмите для просмотра прикрепленного файла
Опять у меня все не так, как нужно? Не останавливается, грузит форму с пустыми полями, чтоб их можно было обновить. Что ж я все-время не так делаю, а? Сколько раз повторять, я ПРОВЕРЯЮ код, который выкладываю. Если не работает - кода просто НЕТ. Так что ищи ошибку у себя...



Он форму открывает, и у меня но когда я жму применить выбивает ошибку((


Добавлено через 8 мин.
У меня вот так вылаживаю фотки пошагово
IUnknown
Так... Ну, у тебя весь бардак - из-за того, что при нажатии на кнопку "Обзор" ты выбираешь файл, это меняет рабочую папку, и, соответственно, при дальнейших попытках открыть файл у тебя ничего не получается: папка изменилась, абсолютный путь - другой, программа аварийно завершается. После того, как бала нажата кнопка "Обзор", восстанавливай текущую папку (через SetCurrentDir), причем не только тогда, когда Execute завершилась удачно, а в любом случае. А fname присваивай не полное имя файла, а только ExtractFileName(Form3->OpenDialog1->FileName)... Тогда у тебя в любое время
а) будет правильная текущая папка;
б) будет правильное короткое имя файла изображения.

Разумеется, если ты хочешь подгружать изображения и из других папок - то это все надо делать по-другому, тогда надо вычислять относительный путь к файлу JPG от текущей папки (той, где лежит EXE-шник)
alecsandr
Цитата(IUnknown @ 5.06.2011 19:53) *

Так... Ну, у тебя весь бардак - из-за того, что при нажатии на кнопку "Обзор" ты выбираешь файл, это меняет рабочую папку, и, соответственно, при дальнейших попытках открыть файл у тебя ничего не получается: папка изменилась, абсолютный путь - другой, программа аварийно завершается. После того, как бала нажата кнопка "Обзор", восстанавливай текущую папку (через SetCurrentDir), причем не только тогда, когда Execute завершилась удачно, а в любом случае. А fname присваивай не полное имя файла, а только ExtractFileName(Form3->OpenDialog1->FileName)... Тогда у тебя в любое время
а) будет правильная текущая папка;
б) будет правильное короткое имя файла изображения.

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

Извини что надоедаю, ном ог бы не много подробнее)), а то просто не понял(((( особенно про setcurrentdir, просто такого даже не учили((
IUnknown
Прежде, чем с этим заморачиваться - ты сделай, чтобы у тебя к моменту открытия Form3 набор данных был уже открыт, те DBEdit-ы, которые лежат на форме, чтоб хоть как-то функционировали. А то смысл такой формы в чем? Не назначено DBEdit-ам ни RecordSet-а, ни имени поля в базе. Открылась форма, пытаешься ввести что-то - "а фиг тебе, я ни на что не реагирую". В топку такую форму, зачем она нужна, если не связана с базой, и не позволяет менять данные на лету? Или что, я должен в открытой форме выбрать название изображения, вслепую ее закрыть (а кнопочка Отмена не работает, закрывать приходится крестиком), а потом прямо в DBGrid-е изменять данные? Меня такое приложение мало интересует, я им заниматься не буду.

Второе: ты сравни свой скриншот с моим. Почему у тебя форма выглядит как положено, а у меня - нет? Это что, из серии "на мониторах больше 17 инч - не запускать, и только для Windows 7"? Приложение идет тем же лесом, что и из-за неадекватной формы. Исправляй работоспособность Form3, и внешний вид, и присоединяй проект. Только я тебя прошу: не надо мне твои obj-файлы и файлы истории. Убери все лишнее, зачем мегабайтные tds-файлы туда сюда перекачивать? Они мне на фиг не сдались, у меня все равно Builder 2009. Только MDB, CPP, H и BPR, все остальное любой откомпилирует сам...
alecsandr
Цитата(IUnknown @ 5.06.2011 20:55) *

Прежде, чем с этим заморачиваться - ты сделай, чтобы у тебя к моменту открытия Form3 набор данных был уже открыт, те DBEdit-ы, которые лежат на форме, чтоб хоть как-то функционировали. А то смысл такой формы в чем? Не назначено DBEdit-ам ни RecordSet-а, ни имени поля в базе. Открылась форма, пытаешься ввести что-то - "а фиг тебе, я ни на что не реагирую". В топку такую форму, зачем она нужна, если не связана с базой, и не позволяет менять данные на лету? Или что, я должен в открытой форме выбрать название изображения, вслепую ее закрыть (а кнопочка Отмена не работает, закрывать приходится крестиком), а потом прямо в DBGrid-е изменять данные? Меня такое приложение мало интересует, я им заниматься не буду.

Второе: ты сравни свой скриншот с моим. Почему у тебя форма выглядит как положено, а у меня - нет? Это что, из серии "на мониторах больше 17 инч - не запускать, и только для Windows 7"? Приложение идет тем же лесом, что и из-за неадекватной формы. Исправляй работоспособность Form3, и внешний вид, и присоединяй проект. Только я тебя прошу: не надо мне твои obj-файлы и файлы истории. Убери все лишнее, зачем мегабайтные tds-файлы туда сюда перекачивать? Они мне на фиг не сдались, у меня все равно Builder 2009. Только MDB, CPP, H и BPR, все остальное любой откомпилирует сам...


Вот сдесь можно изменять DBEDIt, они уже связаны с базой, клавиша отмена работает
IUnknown
DFM - файлы добавь в проект, а то восстанавливать форму не очень хочется вручную.
alecsandr
Цитата(IUnknown @ 6.06.2011 9:01) *

DFM - файлы добавь в проект, а то восстанавливать форму не очень хочется вручную.


нУ вроде скинул
IUnknown
Значит, смотри, что я сделал:

1) на Form3 вместо Edit1 добавил DBEdit4, связал его с полем Photo набора данных. Естественно, что в обработчике кнопки "Обзор" я заношу имя файла не в Edit1, а в DBEdit4.
2) с обработкой "Применить" у тебя - полный бардак. Я сделал так:
void __fastcall TForm3::Button2Click(TObject *Sender)
{
// Ничего заносить в поле Photo уже не надо, это делается автоматически
//Form2->DataSource1->DataSet->FieldValues["Photo"];// присваиваем имя фотографии товара

Form2->ADOQuery1->Edit(); // Тебе не нужно ДОБАВЛЯТЬ запись, достаточно ее ОБНОВИТЬ
Form2->DataSource1->DataSet->Post();
Form2->DBImage1->Stretch=true;
// Вот так я добиваюсь того, чтобы изображение читалось из текущей папки + /photo ВСЕГДА
Form2->DBImage1->Picture->LoadFromFile(ExtractFilePath(Application->ExeName) + "photo\\" + fname);

// Вот этого тоже делать не надо, не оставляй набор данных в открытом состоянии,
// не ты один можешь работать с базой, это будет мешать остальным...
// при выделении товара показывать информацию о нем
// Form2->ADOQuery1->Edit();
Form3->Close();
}


Точно так же, как и тут, я переделал строку в LoadPhoto() :
 Form2->DBImage1->Picture->LoadFromFile(ExtractFilePath(Application->ExeName) + "photo\\" + strphoto);
// при выделении товара показывать информацию о нем
, теперь все прекрасно добавляется и ничего никуда не вылетает.

Теперь еще кое-что:
1) у тебя программа не завершается корректно, остается висеть в процессах. При отладке работе из Билдера это видно, просто снимаешь ее с выполнения через Ctrl+F2 и все. А вот если запустить программу из проводника - то потом ее приходится снимать из диспетчера задач. Ищи причину.
2) утечка памяти. Ты выделяешь
void __fastcall TForm1::Button1Click(TObject *Sender)
{
int i;
char *k=new char[5]; // <--- Вот тут
память?
Где освобождение? CodeGuard тут же поднимает тревогу. Кстати, то, что ты делаешь - вообще неправильно. Как минимум потому, что выделять память надо на один символ больше, чем будешь использовать, для завершающего нуля. Ты этого не сделал. Исправляй эти недочеты тоже...

Добавлено через 12 мин.
Да, кстати, еще одно... Весь вот этот ужас:

Цитата
if (Form2->ComboBox1->ItemIndex==0)
{
Form2->ADOQuery1->SQL->Add("Select * FROM Акустика");
Form2->ADOQuery1->SQL->Add("WHERE (Наименование LIKE'%"+Edit1->Text+"%') ORDER by Наименование ASC");
Form2->ADOQuery1->Open();
Form2->DataSource1->DataSet=Form2->ADOQuery1;
// LoadPhoto();
}
else
if (Form2->ComboBox1->ItemIndex==1)
{
Form2->ADOQuery1->SQL->Add("Select * FROM Материнки");
Form2->ADOQuery1->SQL->Add("WHERE (Наименование LIKE'%"+Edit1->Text+"%') ORDER by Наименование ASC");
Form2->ADOQuery1->Open();
Form2->DataSource1->DataSet=Form2->ADOQuery1;
//LoadPhoto();
}
else ...
(и так далее еще 8 раз) - очень просто укладывается в 4 строки, независимо от количества таблиц в базе:
	Form2->ADOQuery1->SQL->Add("Select * FROM " + ComboBox1->Text);
Form2->ADOQuery1->SQL->Add("WHERE (Наименование LIKE'%"+Edit1->Text+"%') ORDER by Наименование ASC");
Form2->ADOQuery1->Open();
Form2->DataSource1->DataSet=Form2->ADOQuery1;
Угу? Главное, чтобы текст в комбобоксе совпадал с названием таблицы.

То же самое касается и десяти кнопок для выбора показываемой таблицы. Достаточно сделать один обработчик, работающий с Caption-ом Sender-а, и назначить его всем кнопкам. Не нужен тут Copy+Paste...
alecsandr
Цитата(IUnknown @ 6.06.2011 9:51) *

Значит, смотри, что я сделал:

1) на Form3 вместо Edit1 добавил DBEdit4, связал его с полем Photo набора данных. Естественно, что в обработчике кнопки "Обзор" я заношу имя файла не в Edit1, а в DBEdit4.
2) с обработкой "Применить" у тебя - полный бардак. Я сделал так:
void __fastcall TForm3::Button2Click(TObject *Sender)
{
// Ничего заносить в поле Photo уже не надо, это делается автоматически
//Form2->DataSource1->DataSet->FieldValues["Photo"];// присваиваем имя фотографии товара

Form2->ADOQuery1->Edit(); // Тебе не нужно ДОБАВЛЯТЬ запись, достаточно ее ОБНОВИТЬ
Form2->DataSource1->DataSet->Post();
Form2->DBImage1->Stretch=true;
// Вот так я добиваюсь того, чтобы изображение читалось из текущей папки + /photo ВСЕГДА
Form2->DBImage1->Picture->LoadFromFile(ExtractFilePath(Application->ExeName) + "photo\\" + fname);

// Вот этого тоже делать не надо, не оставляй набор данных в открытом состоянии,
// не ты один можешь работать с базой, это будет мешать остальным...
// при выделении товара показывать информацию о нем
// Form2->ADOQuery1->Edit();
Form3->Close();
}


Точно так же, как и тут, я переделал строку в LoadPhoto() :
 Form2->DBImage1->Picture->LoadFromFile(ExtractFilePath(Application->ExeName) + "photo\\" + strphoto);
// при выделении товара показывать информацию о нем
, теперь все прекрасно добавляется и ничего никуда не вылетает.

Теперь еще кое-что:
1) у тебя программа не завершается корректно, остается висеть в процессах. При отладке работе из Билдера это видно, просто снимаешь ее с выполнения через Ctrl+F2 и все. А вот если запустить программу из проводника - то потом ее приходится снимать из диспетчера задач. Ищи причину.
2) утечка памяти. Ты выделяешь
void __fastcall TForm1::Button1Click(TObject *Sender)
{
int i;
char *k=new char[5]; // <--- Вот тут
память?
Где освобождение? CodeGuard тут же поднимает тревогу. Кстати, то, что ты делаешь - вообще неправильно. Как минимум потому, что выделять память надо на один символ больше, чем будешь использовать, для завершающего нуля. Ты этого не сделал. Исправляй эти недочеты тоже...

Добавлено через 12 мин.
Да, кстати, еще одно... Весь вот этот ужас:

(и так далее еще 8 раз) - очень просто укладывается в 4 строки, независимо от количества таблиц в базе:
	Form2->ADOQuery1->SQL->Add("Select * FROM " + ComboBox1->Text);
Form2->ADOQuery1->SQL->Add("WHERE (Наименование LIKE'%"+Edit1->Text+"%') ORDER by Наименование ASC");
Form2->ADOQuery1->Open();
Form2->DataSource1->DataSet=Form2->ADOQuery1;
Угу? Главное, чтобы текст в комбобоксе совпадал с названием таблицы.

То же самое касается и десяти кнопок для выбора показываемой таблицы. Достаточно сделать один обработчик, работающий с Caption-ом Sender-а, и назначить его всем кнопкам. Не нужен тут Copy+Paste...



Спасибо огромное очень сильно помог)) Премного благодарен тебе!
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.