Delphi: проблемы с остановкой табуляции в TRadioButton

#delphi #focus #radio-button #selection

#delphi #фокус #переключатель #выбор

Вопрос:

Когда у TRadioButton TabStop= True, он ведет себя очень странно.

Если вы попытаетесь переключать фокус между множеством переключателей в форме с помощью клавиши Tab, вы будете делать это только 1 раз за сеанс приложения. Табулирование является односторонним, никогда не возвращаясь к первому переключателю. Также, когда фокус перемещается по переключателям, они автоматически становятся «проверенными».

Можно ли исправить это поведение без создания моего собственного компонента?

Я хочу, чтобы стандартные переключатели

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

Ответ №1:

Я понимаю, что вы работаете с существующим кодом, который является ограничением реального мира, которое слишком часто игнорируется на этих форумах.

Мне кажется, что флажки подошли бы вам больше. Вы можете обеспечить эксклюзивность, обычно ожидаемую от RadioButtons, в событии OnChecked. Это должно решить ваши проблемы с табуляцией / фокусом и выбором / отменой выбора.

Флажки не будут автоматически устанавливаться при получении фокуса, и ваши пользователи могут устанавливать / снимать их с помощью клавиши пробела.

Комментарии:

1. Я выбираю этот ответ, потому что использование флажков является наиболее простым решением проблемы, как я вижу. Однако мне нужны именно переключатели, и я создам компонент с измененным поведением для табуляции.

Ответ №2:

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

 var
  SelectedRadioButton: TRadioButton;

//event shared by all radiobuttons
procedure TForm1.RadioButton1Enter(Sender: TObject);
begin
  if Sender <> SelectedRadioButton then begin
    SelectedRadioButton.Checked:= true;
  end;
end;

procedure TFrameOrder.RadioButton1Click(Sender: TObject);
begin
  SelectedRadioButton:= (Sender as TRadioButton);
end;

procedure TFrameOrder.RadioButton1KeyPress(Sender: TObject; var Key: Char);
var
  MyRadioButton: TRadioButton;
begin
  MyRadioButton:= (Sender as TRadioButton);
  if Key in [#32,#13] then begin 
    MyRadioButton.Checked:= true;
    RadioButton1Click(MyRadioButton);
  end; {if}
end;
  

Вероятно, было бы разумнее создать новый компонент TMyRadioButton, хотя, потому что это загромоздит ваш обычный код.

Комментарии:

1. Спасибо, Йохан. Я пробовал это решение, но проблема глубже, чем кажется.

Ответ №3:

Я нашел интересную статью Крейга Штунца об этой проблеме. Как я вижу, мне нужно будет создать свой собственный элемент управления, чтобы решить это.

Комментарии:

1. Вам нужно сделать это, только если вы действительно хотите иметь возможность переключаться между всеми соответствующими переключателями. Хотя обычно переключатели работают не так. Вы переходите к группе переключателей, а затем с помощью клавиш со стрелками (или символов акселератора) выбираете, какой из них следует отметить. Только отмеченный должен быть остановкой табуляции.

2. @Rob, я понимаю стандартную ситуацию, но мне нужно решить немного необычную задачу, когда переключатели находятся не в одной группе, а в частях разных элементов управления. Итак, я хочу иметь полный контроль над выбором и проверкой.

Ответ №4:

По умолчанию только одна радиокнопка имеет свойство TabStop = True; Все радиокнопки обрабатываются как один элемент управления. Когда radiobutton находится в фокусе, вы можете переключаться между кнопками с помощью стрелок вверх и вниз.

Теперь, когда пользователь выбирает одну опцию, он может нажать tab, чтобы переключиться на другой элемент управления (без изменения параметров радио).