Форум: "Основная";
Текущий архив: 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 экономим электроэнергию
Пойдем дальше - когда моргаем, выключаем монитор :)
Страницы: 1 2 вся ветка
Форум: "Основная";
Текущий архив: 2009.10.18;
Скачать: [xml.tar.bz2];
Память: 0.55 MB
Время: 0.005 c