Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2009.10.18;
Скачать: [xml.tar.bz2];

Вниз

При переключении между чекбоксами - ошибка Stack overflow.   Найти похожие ветки 

 
Dr.Andrew   (2008-08-26 20:22) [0]

Добрый вечер!

Тестировано на Delphi 2007 win32 и Windows Vista Home Basic.
Проблемы с компонентом TCheckBox.
Вот два варианта кода:

procedure TForm1.CheckBox1Click(Sender: TObject);
// var i : Integer;
begin
{ for i := 0 to GroupBox1.ControlCount-1 do
begin
if TComponent(Sender).Tag = i then
(GroupBox1.Controls[i] as TCheckBox).Checked := True
else
(GroupBox1.Controls[i] as TCheckBox).Checked := False;
end; }

if Sender = CheckBox1 then
begin
CheckBox1.Checked := True;
CheckBox2.Checked := False;
CheckBox3.Checked := False;
CheckBox4.Checked := False;
end
else
if Sender = CheckBox2 then
begin
CheckBox1.Checked := False;
CheckBox2.Checked := True;
CheckBox3.Checked := False;
CheckBox4.Checked := False;
end
else
if Sender = CheckBox3 then
begin
CheckBox1.Checked := False;
CheckBox2.Checked := False;
CheckBox3.Checked := True;
CheckBox4.Checked := False;
end
else
if Sender = CheckBox4 then
begin
CheckBox1.Checked := False;
CheckBox2.Checked := False;
CheckBox3.Checked := False;
CheckBox4.Checked := True;
end;
end;


Финал один при переключении между чекбоксами выдает компиллятор следующую ошибку:

---------------------------
Debugger Exception Notification
---------------------------
Project Project1.exe raised exception class EStackOverflow with message "Stack overflow".
---------------------------
Break Continue Help
---------------------------

В чем проблема?

Спасибо.


 
TStas ©   (2008-08-26 20:44) [1]

В том, что Вы в обработчике щелчка меняете состояние ЧекБокса, что вызывает этот же обработчик.


 
Dr.Andrew   (2008-08-26 20:53) [2]

Да, но на делфи 7 все было нормально, а в делфи 2007 вот такая проблема. Это связано с делфи 2007 и ее спецификой. Можно подробнее объяснить. Спасибо.


 
Юрий Зотов ©   (2008-08-26 20:56) [3]

Судя по коду, тут больше подходит TRadioGroup, а не набор TCheckBox.


 
Dr.Andrew   (2008-08-26 21:03) [4]

Хотелось бы все же ответ на мой предыдущий вопрос по форуму. Спасибо.


 
{RASkov} ©   (2008-08-26 21:08) [5]

> [2] Dr.Andrew   (26.08.08 20:53)
> Да, но на делфи 7 все было нормально

Врешь.... переполнение везде будет с данным кодом.... Подробно в [1])


 
TStas ©   (2008-08-26 21:14) [6]

>Врешь.... переполнение везде будет с данным кодом.... Подробно в [1]
Нет! Не всегда программное переключение CheckBox"а вызывает OnClick! Я сам до сих пор не понял, почему. А вот у RadioGroup, о котором Зотов верное очень сказал, что именно его функциональность используется, ИМХО, всегда.
Мне кажется, что это связано с тем, что CheckBox - это лишь обёрка к аналогичному объекту Виндов, а они, как известно, сильно различаются друг от друга.


 
{RASkov} ©   (2008-08-26 21:22) [7]

> [6] TStas ©   (26.08.08 21:14)
> Нет! Не всегда программное переключение CheckBox"а вызывает
> OnClick!

Эт как это? :)
Да, может быть с экшенами что-то связано, но если без них то всегда.
Не сработает в том случае, если мы программно выставляем CheckBox.Checked := True; а в нем до этого была установлена галка - тогда - да, не сработает.... но в "нашем" случае это явно не так.... Хотя пока не известно с акциями там как дела, но.... пока все именно так как в [1] :)


 
Dr.Andrew   (2008-08-26 21:30) [8]

Спасибо. Только не стоит употреблять такую лексику как "Врешь". Нет не вру - может ккие-то другие процессы этому мешали, но проект компилированный в делфи 7 работал с подобной формой процедуры прогона чекбоксов работал нормально. Спасибо.


 
{RASkov} ©   (2008-08-26 21:33) [9]

Т.е. в [7] я хотел сказать, что не сработает в том случае, когда мы выставляем чекед который текущий в данный момент в контроле...
Т.е. Вот так
в чеке установлена галка, тогда
Checked := True;  //НЕ вызовет OnClick
Checked := False; // Вызовет OnClick
в чеке НЕ установлена галка, тогда
Checked := True;  //Вызовет OnClick
Checked := False; //НЕ вызовет OnClick


 
{RASkov} ©   (2008-08-26 21:35) [10]

> [8] Dr.Andrew   (26.08.08 21:30)
> Только не стоит употреблять такую лексику как "Врешь".

:) Ну сорри.... я вот такой вот вредный) Могу вообще не отвечать в твоих ветках :)


 
{RASkov} ©   (2008-08-26 21:40) [11]

> [8] Dr.Andrew   (26.08.08 21:30)
> Нет не вру - может ккие-то другие процессы этому мешали,
> но проект компилированный в делфи 7 работал с подобной
> формой процедуры прогона чекбоксов работал нормально

Ну не может он нормально работать... логически подумать даже с акциями должно быть переполнение стека...
Вот если предварительно отключать OnClick затем вся эта манипуляция и затем назад онклик вернуть, тогда - да. А так - ну не может :)


 
Dr.Andrew   (2008-08-26 21:41) [12]

Спасибо. Я только за взаимную вежливость.


 
student   (2008-08-26 21:45) [13]

procedure TForm1.CheckBox1Click(Sender: TObject);
// var i : Integer;
begin
if Sender = CheckBox1 then
begin
 CheckBox1.OnClick := nil;
CheckBox1.Checked := True;
CheckBox2.Checked := False;
 // ...
end;
 CheckBox1.OnClick := CheckBox1Click
end;


 
{RASkov} ©   (2008-08-26 21:46) [14]

> [12] Dr.Andrew   (26.08.08 21:41)

Тогда пожалуйста, приходите ещё.
:о)


 
Dr.Andrew   (2008-08-26 22:02) [15]

Спасибо


 
Dr.Andrew   (2008-08-26 22:10) [16]

student

Кстати, так не работает.


 
{RASkov} ©   (2008-08-26 22:16) [17]

> Кстати, так не работает.

Именно так не будет, но направление есть, нужно только всем "отключить", а затем всем "включить" данный обработчик...
 CheckBox1.OnClick:=nil;
 CheckBox2.OnClick:=nil;
 CheckBox3.OnClick:=nil;
 CheckBox4.OnClick:=nil;
тут код из [0]
 CheckBox1.OnClick:=CheckBox1Click;
 CheckBox2.OnClick:=CheckBox1Click;
 CheckBox3.OnClick:=CheckBox1Click;
 CheckBox4.OnClick:=CheckBox1Click;


 
Loginov Dmitry ©   (2008-08-26 22:29) [18]

> В чем проблема?


Сообщение "Stack overflow" совершенно однозначно описывает причину проблемы.

> Да, но на делфи 7 все было нормально, а в делфи 2007 вот
> такая проблема.


В D7 тоже самое.


 
{RASkov} ©   (2008-08-26 22:30) [19]

> [16] Dr.Andrew   (26.08.08 22:10)

Попробуй вот такой вариант:
 CheckBox1.OnClick:=nil;
 CheckBox2.OnClick:=nil;
 CheckBox3.OnClick:=nil;
 CheckBox4.OnClick:=nil;
 CheckBox1.Checked := False;
 CheckBox2.Checked := False;
 CheckBox3.Checked := False;
 CheckBox4.Checked := False;
 TCheckBox(Sender).Checked:=True;
 CheckBox1.OnClick:=CheckBox1Click;
 CheckBox2.OnClick:=CheckBox1Click;
 CheckBox3.OnClick:=CheckBox1Click;
 CheckBox4.OnClick:=CheckBox1Click;

Или вот такой если все чеки на одном паренте и у них один обработчик OnClick:
procedure SetChecks(APar: TWinControl; Check: TCheckBox; AllOnClick: TNotifyEvent);
var N: Integer;
begin
 for N:=0 to APar.ControlCount-1 do
  if APar.Controls[N] is TCheckBox then begin
   TCheckBox(APar.Controls[N]).OnClick:=nil;
   TCheckBox(APar.Controls[N]).Checked:=False;
  end;
 Check.Checked:=True;
 for N:=0 to APar.ControlCount-1 do
  if APar.Controls[N] is TCheckBox then
   TCheckBox(APar.Controls[N]).OnClick:=AllOnClick;
end;

procedure TForm1.CheckBox1Click(Sender: TObject);
begin
 SetChecks(Self, TCheckBox(Sender), CheckBox1Click);
end;

Можно еще много разных вариантов придумать, но может стоит присмотреться к [3]?


 
Dr.Andrew   (2008-08-26 23:49) [20]

Спасибо. полный разбор вопроса. Спасибо!


 
Dr.Andrew   (2008-08-27 00:20) [21]

Проверил второй вариант ([19]), но он не работает, ошибки тоже нет, просто чекбоксы отмечаются, но не отключаются другие. В чем ошибка?


 
Dr.Andrew   (2008-08-27 00:24) [22]

Все работает! Спасибо {RASkov}. Второй вариант супер!


 
Германн ©   (2008-08-27 01:06) [23]


> Сообщение "Stack overflow" совершенно однозначно описывает
> причину проблемы.
>
> > Да, но на делфи 7 все было нормально, а в делфи 2007 вот
> > такая проблема.
>
>
> В D7 тоже самое.

По-моему я как-то приводил тут пример подобной бесконечной рекурсии, но там даже "Stack overflow" было не дождаться. Слишком много времени занимала перерисовка грида.


 
Dr.Andrew   (2008-08-27 04:51) [24]

Спасибо


 
MsGuns ©   (2008-08-27 11:31) [25]

ИМХО, для выбора варианта из списка альтернативных все же лучше использовать радиогруппу или комбобокс. Чекбоксы принято использовать для неальтернативных опций


 
Dr.Andrew   (2008-08-27 15:14) [26]

Спасибо за помощь


 
Vlad Oshin ©   (2008-08-27 17:52) [27]

type
 TForm1 = class(TForm)
   CheckBox1: TCheckBox;
   CheckBox2: TCheckBox;
   CheckBox3: TCheckBox;
   CheckBox4: TCheckBox;
   procedure CheckBox1Click(Sender: TObject);
 private
   { Private declarations }
 public
   { Public declarations }
 end;

 tb=class(TButtonControl);

var
 Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.CheckBox1Click(Sender: TObject);
begin
 tb(sender).ClicksDisabled:=true;
 CheckBox1.Checked := False;
 CheckBox2.Checked := False;
 CheckBox3.Checked := False;
 CheckBox4.Checked := False;
 tCheckBox(sender).Checked:=true;
end;


 
MsGuns ©   (2008-08-27 20:45) [28]

>Vlad Oshin ©   (27.08.08 17:52) [27]

Ежики надели бронежилеты и продолжали лезть на кактус
;)


 
{RASkov} ©   (2008-08-27 20:54) [29]

> [28] MsGuns ©   (27.08.08 20:45)

Ну и что :) Кстати, хороший вариант...)
Итого у нас получилось:
type tb=class(TButtonControl);
procedure SetChecks(APar: TWinControl; Check: TCheckBox);
var N: Integer;
begin
 tb(Check).ClicksDisabled:=True;
 for N:=0 to APar.ControlCount-1 do
  if APar.Controls[N] is TCheckBox then
   TCheckBox(APar.Controls[N]).Checked:=False;
 Check.Checked:=True;
end;

procedure TForm1.CheckBox1Click(Sender: TObject);
begin
 SetChecks(Panel1, TCheckBox(Sender));
end;

:)


 
Dr.Andrew   (2008-08-27 21:48) [30]

{RASkov}
Если один из чекбоксов был включен предварительно, то последний пример работает с запаздыванием.
Спасибо за помощь.


 
{RASkov} ©   (2008-08-27 22:02) [31]

> [30] Dr.Andrew   (27.08.08 21:48)
> Если один из чекбоксов был включен предварительно, то последний
> пример работает с запаздыванием

Этому в принципе есть объяснение.
Так как OnClick вызовется для всех изначально включенных, помимо того который включаем - чекбоксов...
Из-за того что мы снимаем состояние чекед, вследствии чего снова вызывается данный обработчик онклик и дисаблим онклик вызвавшего чека....
Лучше в коде это отследить, чем понять что я тут понаписал :)
Так же себя поведет и код Влада....


 
Германн ©   (2008-08-28 01:11) [32]


> {RASkov} ©   (27.08.08 20:54) [29]
>
> > [28] MsGuns ©   (27.08.08 20:45)
>
> Ну и что :) Кстати, хороший вариант...)
>

У меня тоже был вариант. Вот только найти его в архивах на скорую руку не смог. (((


 
Vlad Oshin ©   (2008-08-28 09:31) [33]


> Если один из чекбоксов был включен предварительно, то последний
> пример работает с запаздыванием

тогда вот, полная иммитация radioбулочек :)

type
TForm1 = class(TForm)
  CheckBox1: TCheckBox;
  CheckBox2: TCheckBox;
  CheckBox3: TCheckBox;
  CheckBox4: TCheckBox;
  procedure CheckBox1Click(Sender: TObject);
private
   procedure ExtractedMethod;
  { Private declarations }
public
  { Public declarations }
end;

tb=class(TButtonControl);

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.ExtractedMethod;
begin
 CheckBox1.Checked := 1=2;
 CheckBox2.Checked := 1=2;
 CheckBox3.Checked := 1=2;
 CheckBox4.Checked := 1=2;
end;

procedure TForm1.CheckBox1Click(Sender: TObject);
begin
 ExtractedMethod;
 tb(sender).ClicksDisabled := 1=1;
 ExtractedMethod;
 tCheckBox(sender).Checked := 1=1;
end;


 
Dr.Andrew   (2008-08-28 21:41) [34]

Спасибо. тоже очень интересное решение.


 
evvcom ©   (2008-09-01 12:05) [35]

CheckBox1.Checked := 1=2;

:-) а True / False уже отменили?


 
Vlad Oshin ©   (2008-09-01 12:25) [36]


> evvcom ©   (01.09.08 12:05) [35]

1. писать короче на 1 символ ->  экономим место на диске :)
2. тут проскакивала темка про константы булевы, точно не помню, но так, (1=1), точно будет true.
Во, блин, вообще не помню..
Короче что-то там от версии к версии, еще про связанное с внутренним их представлением,
вот так как-то.. что-то ..
:)


 
Anatoly Podgoretsky ©   (2008-09-01 13:03) [37]

> Vlad Oshin  (01.09.2008 12:25:36)  [36]

И выключаем Num Lock экономим электроэнергию


 
evvcom ©   (2008-09-01 13:06) [38]


> 1. писать короче на 1 символ ->  экономим место на диске :)

Да... Это серьезная экономия :))

> но так, (1=1), точно будет true

True тоже точно будет true :)

> еще про связанное с внутренним их представлением

Ну если такое написать Boolean(2), то можешь наступить на грабли :)


 
{RASkov} ©   (2008-09-01 13:12) [39]

> точно не помню, но так, (1=1), точно будет true

А разве True (т.е. Checked := True) может быть False? :)
Это  ORD(True) могут быть разными...)
То что писать короче, да, но а компилятору теперь лишняя работа, хотя оптимизатор один фик заменит на булевые константы... имхо.


 
Vlad Oshin ©   (2008-09-01 13:20) [40]

>Это  ORD(True) могут быть разнымиясно.

PS
я ж прикольнулся

pss

> И выключаем Num Lock экономим электроэнергию


Пойдем дальше - когда моргаем, выключаем монитор :)


 
{RASkov} ©   (2008-09-01 15:29) [41]

> [40] Vlad Oshin ©   (01.09.08 13:20)
> я ж прикольнулся

> когда моргаем, выключаем монитор :)

Класс :)))


 
Anatoly Podgoretsky ©   (2008-09-01 16:11) [42]

> Vlad Oshin  (01.09.2008 13:20:40)  [40]

Зато я серьезно, можешь сам посчитать
потнебляемая мощность 0,1 вт
В сутках 24 часа, в году 365 дней.

Это только на глаз кажется ничего, а если посчитать, то ого-го


 
Anatoly Podgoretsky ©   (2008-09-01 16:12) [43]

> {RASkov}  (01.09.2008 15:29:41)  [41]

Не надежно, если не моргаем, то экономии нет, а когда моргаем перерасход на включение - токовый удар.



Страницы: 1 2 вся ветка

Форум: "Основная";
Текущий архив: 2009.10.18;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.56 MB
Время: 0.007 c
2-1250322712
Ulugbek
2009-08-15 11:51
2009.10.18
Помогите как вставить кнопка в ячейке Dbgrid?


15-1250571823
Вопрощающий
2009-08-18 09:03
2009.10.18
GLScene и Delphi2006 (for Win32)


2-1250151996
Дмитрий Л.
2009-08-13 12:26
2009.10.18
Система контроля ошибок


2-1250692255
Б
2009-08-19 18:30
2009.10.18
Перемещение курсора.


3-1228464946
Ламот
2008-12-05 11:15
2009.10.18
Выгрузить таблицу в table.dbf.





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский