Здравствуйте :-)
Проблема в ComboBox в Delphi7.
Пишу курсовую, программа для расчета корней квадратного уравнения. Хочу чтоб в ней был выпадающий список с вариантами округления полученных результатов.
То есть если пользователь выбрал "Округлить до десятых", то корни уравнения должны написаться округленными до десятых.
Я только учусь. Целый день бьюсь - не получается.
не могу найти где и какие действия надо прописать этому комбобоксу... Может туда вообще другой элемент поставить? Но ComboBox так замечателдьно экономит место в интерфейсе...
Помогите, пожалуйста...
Если надо, могу выложить листинг программы или сами исходники...
Уважаемые авторы вопросов! Большая просьба сообщить о результатах решения проблемы на этой странице. Иначе, следящие за обсуждением, возможно имеющие аналогичные проблемы, не получают ясного представления об их решении. А авторы ответов не получают обратной связи. Что можно расценивать, как проявление неуважения к отвечающим от автора вопроса.
14-10-2008 00:26 | Сообщение от автора вопроса
Ну и Mikhal уже сказал вам, что подправить. Вы зачем-то сперва выводите неокруглённые результаты, а уж затем их округляете, но никуда не выводите. Ещё компилятор вам может указать на то, что после округления x1 и x2 нигде не используются.
Я увидела :-) Не знаю, зачем я его туда влепила, наверное зарапортовалась :-) Оно все вроде изначально там и стояло, просто пока я методом тыка экспериментировала, то видимо и перепутала места :-)
P.S. Кстати, если нет никаких "указаний свыше", то вместо Real, Single, Double лучше использовать Extended - это самый "толстый" вещественный тип из всех. Кроме того, он же является родным для машины.
"Свыше" или я не так объяснила, или меня не поняли, но вообще предложили не париться... Так что я перевыполнила задание по курсовику и теперь мне светят две пяторочки ;-)
А про Real, Single, Double,Extended мне надо теорию еще раз почитать, а то в голове что-то смутное мелькает .
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
//Кнопка "Решение" проводит вычисления
procedure TForm1.Button1Click(Sender: TObject);
var a,b,c,d,x1,x2:double;
z:integer;
begin
//если а=0 - прерываем процесс
if (edit1.text='0') or (edit1.text=emptystr)
then Memo1.Lines.Add('Коэффициент "а" не должен быть равен "0"');
if (edit1.text='0') or (edit1.text=emptystr) then abort;
//если данные не введены - ставим 0
if edit2.text=emptystr then edit2.text:='0';
if edit3.text=emptystr then edit3.text:='0';
//инициализируем переменные
a:=StrToFloat(Edit1.Text);
b:=StrToFloat(Edit2.Text);
c:=StrToFloat(Edit3.Text);
d:=b*b-4*a*c;
// если дискриминант больше 0, то провоим расчеты и выводим результат
if d>0 then
begin
x1:=(-b+sqrt(d))/(2*a);
x2:=(-b-sqrt(d))/(2*a);
case ComboBox1.ItemIndex of //задаем действие для ComboBox
0 : z := -15; //не округлять
1 : z := -1; //до десятых
2 : z := -2; //до сотых
3 : z := -3; //до тысячных
end;
x1:=RoundTo(x1,z); //округлить
x2:=RoundTo(x2,z); //округлить
Memo1.Lines.Add('D= '+FloatToStr(d));
Memo1.Lines.Add('D>0, уравнение имеет два корня');
Memo1.Lines.Add('x1= '+FloatToStr(x1));
Memo1.Lines.Add('x2= '+FloatToStr(x2));
end;
//Если дикриминант равен 0, то проводим расчеты и выводим результат
if d=0 then
begin
x1:=(-b)/(2*a);
case ComboBox1.ItemIndex of //задаем действие для ComboBox
0 : z := -15; //не округлять
1 : z := -1; //до десятых
2 : z := -2; //до сотых
3 : z := -3; //до тысячных
end;
x1:=RoundTo(x1,z); //округлить
Memo1.Lines.Add('D= '+FloatToStr(d));
Memo1.Lines.Add('x1= х2= '+FloatToStr(x1));
Memo1.Lines.Add('Уравнение имеет только один (два одинаковых корня)');
end;
//Если дискриминант меньше 0, то уравнение корней не имеет.
//Выводим сообщение об этом.
if d<0 then
begin
Memo1.Lines.Add('D= '+FloatToStr(d));
Memo1.Lines.Add('D<0. Уравнение не имеет корней');
end;
end;
>>> еще z вписала вот сюда
Если подумать, то станет очевидным, что значение "до какой цифры округлять" не может быть дробным числом ;) Значит z должно быть одним из целых типов.
Кроме того, вы всегда можете установить текстовый курсор на функцию (в нашем случае - на RoundTo) и нажать F1. Откроется справка по функции, в которой:
TRoundToEXRangeExtended = -20..20; // <- целый тип
function RoundTo(const AValue: Extended; const ADigit: TRoundToEXRangeExtended): Extended;
Ну и Mikhal уже сказал вам, что подправить. Вы зачем-то сперва выводите неокруглённые результаты, а уж затем их округляете, но никуда не выводите. Ещё компилятор вам может указать на то, что после округления x1 и x2 нигде не используются.
P.S. Кстати, если нет никаких "указаний свыше", то вместо Real, Single, Double лучше использовать Extended - это самый "толстый" вещественный тип из всех. Кроме того, он же является родным для машины.
Заменила "а" на "z", чтоб не путалась (хотя если не заменять, то тот же итог)
вот так:
if d>0 then
begin
x1:=(-b+sqrt(d))/(2*a);
x2:=(-b-sqrt(d))/(2*a);
case ComboBox1.ItemIndex of
0 : z := -15; //не округлять
1 : z := -1; //до десятых
2 : z := -2; //до сотых
3 : z := -3; //до тысячных
end;
Memo1.Lines.Add('D= '+FloatToStr(d));
Memo1.Lines.Add('D>0, уравнение имеет два корня');
Memo1.Lines.Add('x1= '+FloatToStr(x1));
Memo1.Lines.Add('x2= '+FloatToStr(x2));
x1:=RoundTo(x1,z);
x2:=RoundTo(x2,z);
end;
, еще z вписала вот сюда
procedure TForm1.Button1Click(Sender: TObject);
var a,b,c,d,x1,x2,z:real;
В общем теперь при компиляции на строчке x1:=RoundTo(x1,z);
пишется такая ошибка:
[Ошибка] Unit1.pas(78): Incompatible types: 'TRoundToRange' and 'Real'
[Ошибка] Unit1.pas(79): Incompatible types: 'TRoundToRange' and 'Real'
[Фатальная Ошибка] Project1.dpr(5): Could not compile used unit 'Unit1.pas'
И еще, если в
procedure TForm1.Button1Click(Sender: TObject);
var a,b,c,d,x1,x2,z:real;
вместо real вписать double - ошибка та же получается...
А никак на код не влияет то, что "а" у меня уже изначально задана как вводимая пользователем переменная?
Александр, все рправильно, я так и хочу сделать, как Вы поняли :-) Просто когда программа мне начала нули выкидывать, то я решила что может надо перед каждым выводом для каждого варианта округления "напоминать ей что от нее (программы) хотят...
>>> И еще надо ли для каждого варианта округления писать
Наверное это зависит от того, что вы хотите получить?
Я вот пока ещё не понял.
Например, в приведённом вами коде вы три раза выводите ответ. Зачем? Можете объяснить, что вы хотели увидеть? Типа, чтобы программа вывела ответ с тремя различными округлениями или что? В самом начале я решил, что вы хотите сделать так: пользователь вводит коэффициенты, выбирет из ComboBox режим округления и жмёт кнопку расчётов. Получает ответ в виде пары иксов с нужным округлением. Хочет другое округление или другое уравнение - вводит/выбирает новые значения и снова жмёт на кнопку рассчёта. Свои советы я писал, исходя из такой модели.
Далее, вроде бы мы с вами определились с планом, но вы зачем-то пишите x1:=RoundTo(x1,0); - т.е. сразу же округляете x1 до целых. Зачем? Кажется, у нас есть "a", которое мы на предыдущем шаге зачем-то выбирали.
>>> не округляем или какую цифру поставить, что он не производил никаких действий с округлением?
Оставьте пока как есть, давайте мы разберёмся с основным кодом, а потом посмотрим на этот особый случай.
Уважаемая N-Tali, Вы для того и вводите ComboBox, чтобы пользователь выбрал как округлять. В операторе case, в зависимости от выбора пользователя, переменной a присваивается число знаков после запятой, которое потом используется в функции RoundTo.
З.Ы. И повнимательней - в предыдущем посте я указал, где Вы допустили ошибку (x2 присваивали округленному x1)
Спасибо ОГРОМНОЕ всем, кто мне помогает и примите мои извинения за мою же тупость :-( Это моя САМАЯ ПЕРВАЯ программка, и я еще многого не знаю :-) Но обязательно выучу :-)
Вот что у меня получилось. Я добавила Math и для первого случая, когда дискримимнант больше 0 вписала:
// если дискриминант равен 0, проводим расчеты и выводим результат
if d>0 then
begin
x1:=(-b+sqrt(d))/(2*a);
x2:=(-b-sqrt(d))/(2*a);
case ComboBox1.ItemIndex of
0 : a := -15; //не округляем или какую цифру поставить, что он не производил никаких действий с округлением?
1 : a := -1; //до десятых
2 : a := -2; //до сотых
3 : a := -3; //до тысячных
end;
x1:=RoundTo(x1,0);
x2:=RoundTo(x1,0);
Memo1.Lines.Add('D= '+FloatToStr(d));
Memo1.Lines.Add('D>0, уравнение имеет два корня');
Memo1.Lines.Add('x1= '+FloatToStr(x1));
Memo1.Lines.Add('x2= '+FloatToStr(x2));
x1:=RoundTo(x1,1);
x2:=RoundTo(x1,1);
Memo1.Lines.Add('D= '+FloatToStr(d));
Memo1.Lines.Add('D>0, уравнение имеет два корня');
Memo1.Lines.Add('x1= '+FloatToStr(x1));
Memo1.Lines.Add('x2= '+FloatToStr(x2));
x1:=RoundTo(x1,2);
x2:=RoundTo(x1,2);
Memo1.Lines.Add('D= '+FloatToStr(d));
Memo1.Lines.Add('D>0, уравнение имеет два корня');
Memo1.Lines.Add('x1= '+FloatToStr(x1));
Memo1.Lines.Add('x2= '+FloatToStr(x2));
end;
Помоему я что-то лишнее намудрила, так как он теперь х1 и х2 всегда считает равным 0...
Поправьте меня, пожалуйста... :-)
И еще надо ли для каждого варианта округления писать:
x1:=RoundTo(x1,2);
x2:=RoundTo(x1,2);
Memo1.Lines.Add('D= '+FloatToStr(d));
Memo1.Lines.Add('D>0, уравнение имеет два корня');
Memo1.Lines.Add('x1= '+FloatToStr(x1));
Memo1.Lines.Add('x2= '+FloatToStr(x2));
Смотрите, в Button1Click у вас есть код, который показывает ответ, например:
Memo1.Lines.Add('D= '+FloatToStr(d));
Memo1.Lines.Add('D>0, уравнение имеет два корня');
Memo1.Lines.Add('x1= '+FloatToStr(x1));
Memo1.Lines.Add('x2= '+FloatToStr(x2));
Вы хотите, чтобы:
>>> если пользователь выбрал "Округлить до десятых", то корни уравнения должны написаться округленными до десятых.
Корни уравнения - это X1 и X2. Функцию округления вам уже подсказали - это RoundTo, Крокодил указал, как модключить модуль с ней. Как связать RoundTo с ComboBox-ом вам сказал Денис Молчанов во втором посте. Все куски на месте - вам осталось их только сложить.
План:
1. В ComboBox мы вводим какие-то строки ("не округлять"/"округлить до десятых" и т.п.), запоминая в каком они порядке.
2. Перед выводом результатов их нужно округлить, согласно выбранному режиму в ComboBox-е. Т.е. перед тем, как делать Memo1.Lines.Add('x1= '+FloatToStr(x1)); вам нужно округлить x1.
а). Сперва нужно выбрать до каких округлять. Делается это case-ом, что вам дал Денис Молчанов. Тут вам пригодятся номера строк, что вы запомнили в пункте 1. Не забудьте, что отсчёт идёт от нуля. Т.е. если вы добавили две строки ("не округлять" и "округлить до десятых"), то они будут иметь номера 0 и 1 соответственно.
б). Затем нужно произвести собственно округление: x1 := RoundTo(x1, a); где a - значение, выбранное в пункте 2а.
3). Вывести результат. Код останется без изменений: Memo1.Lines.Add('x1= '+FloatToStr(x1)); Здесь x1 - уже округлённое значение.
P.S. Самый первый ответ DragOn говорит просто о начальном заполнении ComboBox-а. Типа, чтобы самой ручками не писать. Больше он ничего не делает. Если вы руками заполнили ComboBox в режиме проектирования ("не округлять"/"округлить до десятых"), то вам это делать не нужно - про FormCreate можете (пока) забыть.
>>> Вы не поверите! Его там у меня нету :-(...
Наверное перед этим на форме надо щёлкнуть по форме, а не по комбобоксу? Инспектор показывает свойства и события выделенного объекта. Сейчас у вас выделен ComboBox, а не форма.
Крокодил сказал же:
>>> Давайте искать вместе. Кликаем мышкой на форме, затем смотрим налево и вниз.
Не прокатило.... Может всетаки в 7-й версии дельфи она как-то называется по-другому?
Вроде программа написана, работает, можно сдавать. И комбобокс этот не обязателен.. Но с ним-то круче! Интерфейс дружественней и функциональней и будущему пользователю с моей програмкой удобней будет :-)
Давайте искать вместе. Кликаем мышкой на форме, затем смотрим налево и вниз. Там находится так называемый Object Inspector. В нем есть две вкладки: Properties и Events. Нашли?
Крокодил
Вы не поверите! Его там у меня нету :-(... Я перед тем как обратиться сюда, искала информацию по книжкам, в сети... мне это OnCreate попадалось, но я его еще тогда не нашла и подумала, что может там для другой версии было написано...
В общем нет у меня такого...
Здесь в сообщение картинки не вставляются, поэтому напишу, какие у меня строчки есть в свойствах инспектора объектов: OnChange, OnClick, OnCloseUp, OnContextPopup, OnDblClick, OnDragDrop, OnDragOver, OnDrawItem, OnDropDown, OnEndDock, OnEndDrag, OnEnter, OnExit, OnKeyDown, OnKeyPress, OnKeyUp, OnMeasureltem, OnSelect, OnStartDock, OnStartDrag, PopupMenu... Уф! Переписала :-) Теперь я точно уверена что там нет такого пункта.
Может его надо где-то включить?
Или Вот когда нажимаю Два раза по OnClick, появляется
procedure TForm1.ComboBox1Click(Sender: TObject);
begin
end;
end.
в инспекторе объектов удалить ComboBox1Click, в код переписать так:
procedure TForm1.FormCreate(Sender: TObject);
begin
А вот эту TForm1.FormCreate...не нашла
Давайте искать вместе. Кликаем мышкой на форме, затем смотрим налево и вниз. Там находится так называемый Object Inspector. В нем есть две вкладки: Properties и Events. Нашли? Отлично! Щелкаем по вкладке Events. Находим слева в списке событий OnCreate. Не волнуйтесь, оно не тринадцатое, а двенадцатое по счету сверху. Кликаем мышкой слева на тексте "On Create". Справа от него должен активизироваться комбобокс (что это такое, Вы уже знаете). Писать в нем ничего не нужно, просто делаете двойной щелчок в поле его редактора. Получилось? Ну, если получилось, то дальше увидите все сами.
ЧТО НАДО ЗДЕСЬ НАПИСАТЬ, чтоб оно заработало?
Так это не сюда надо вписать, а в TForm1.FormCreate
Крокодил
С Math разобралась, точнее где она находится я увидела :-)
А вот эту TForm1.FormCreate...не нашла... Может у меня в проекте ее вообще нет? Или она как Math дополнительно указывается?
Не поняла что за модуль Math
В этом модуле содержится дополнительный набор математических функций и в частности функция RoundTo, которую Вам предложили использовать. Он автоматически не подключается к проекту и его нужно добавлять вручную.
с чем его едят
Его едят с помощью uses. Находите строчку uses в своем проекте и добавляете туда этот модуль:
uses
Windows, Messages, ... , ExtCtrls, Math;
В качестве альтернативного стола для еды можно использовать раздел implementation:
Спасибо за помощь!!!! Так хочу стать программистом, а вы мне помогаете в этом ;-)
Но у меня ничего не получилось... Поясняю:
В дизайнере задайте несколько строк в Items,поиграйте со Style -
посмотрите чему при разных стилях равны ItemIndex,Text.
XYZ
С этим я поигралась :-) Еще вчера. раза 4 пришлось после этих игр переписывать текст :-) т.к. ввидимо я что-то наигрывала такое, что она у меня то не компилировалась, то после компиляции не считала ничего или чушь всякую выдавала :-)
Text - это какая строчка будет видна по умолчанию в Комбобоксе, а значения ItemIndex тоже какая по счету строчка Комбобокса высвечивается... тоесть если в тексе написано "Ура", и при этом в Итемтексте стоит -1 - то никакого Ура в скомпилированной программе видно не будет....
Заносите в ComboBox Ваши варианты округления.
Затем, при вычислении используете выбранное значение ComboBox'a
b - результа расчетов до округления
....................
case ComboBox.ItemIndex of
0 : a := 0; //до целых
1 : a := -1; //до десятых
2 : a := -2; //до сотых
end;
result := RoundTo(b,a); //RoundTo в модуле Math
Денис Молчанов
Не поняла что за модуль Math и с чем его едят :-(.
В ComboBox-e в параментре Itams (TStrings) ввела "не округлять" и "округлить до десятых"... Пробовала туда добавить обозначения какие-нибудь - не то...
Наверное чтобы сработал Ваш вариант надо где-то задать этот "case ComboBox.ItemIndex of"...
11-10-2008 16:03
Var I:Integer;
Begin
ComboBox1.Items.Clear;//Очищаем
For I:=0 To 10 Do
ComboBox1.Items.Add('Округляем до '+IntToStr(I));
End;
DragOn
Вставила в текст программы Ваш текст. Результат: Вообще не выбирает. То есть мною введенные Itams (TStrings)"не округлять" и "округлить до десятых" пропали, появились "округляем до 1..2..3" и т.д. но при открытии программы первая строка поля комбобокс пустая, а из выпадающего списка ничего не выбирается.. и не округляется...
Что не так??? Наверное Clear здесь лишний....
Я выложу текст программы, посмотрите пожалуйста, что и куда вписать.
Может я просто не могу толком объяснить что мне надо...
Воть:
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
//Кнопка "Решение" проводит вычисления
procedure TForm1.Button1Click(Sender: TObject);
var a,b,c,d,x1,x2:double;
begin
//если а=0 - прерываем процесс
if (edit1.text='0') or (edit1.text=emptystr)
then Memo1.Lines.Add('Коэффициент "а" не должен быть равен "0"');
if (edit1.text='0') or (edit1.text=emptystr) then abort;
//если данные не введены - ставим 0
if edit2.text=emptystr then edit2.text:='0';
if edit3.text=emptystr then edit3.text:='0';
//инициализируем переменные
a:=StrToFloat(Edit1.Text);
b:=StrToFloat(Edit2.Text);
c:=StrToFloat(Edit3.Text);
d:=b*b-4*a*c;
// если дискриминант больше 0, то провоим расчеты и выводим результат
if d>0 then
begin
x1:=(-b+sqrt(d))/(2*a);
x2:=(-b-sqrt(d))/(2*a);
Memo1.Lines.Add('D= '+FloatToStr(d));
Memo1.Lines.Add('D>0, уравнение имеет два корня');
Memo1.Lines.Add('x1= '+FloatToStr(x1));
Memo1.Lines.Add('x2= '+FloatToStr(x2));
end;
//Если дикриминант равен 0, то проводим расчеты и выводим результат
if d=0 then
begin
x1:=(-b)/(2*a);
Memo1.Lines.Add('D= '+FloatToStr(d));
Memo1.Lines.Add('x1= х2= '+FloatToStr(x1));
Memo1.Lines.Add('Уравнение имеет только один (два одинаковых корня)');
end;
//Если дискриминант меньше 0, то уравнение корней не имеет.
//Выводим сообщение об этом.
if d<0 then
begin
Memo1.Lines.Add('D= '+FloatToStr(d));
Memo1.Lines.Add('D<0. Уравнение не имеет корней');
end;
end;
//Кнопка "Очистить результат" Очищает поле с результатами
procedure TForm1.Button3Click(Sender: TObject);
begin
Memo1.Clear;
end;
//Кнопка "Выход" завершает работу и закрывает приложение
procedure TForm1.Button4Click(Sender: TObject);
begin
form1.Close;
end;
procedure TForm1.ComboBox1Change(Sender: TObject);
Begin
//ЧТО НАДО ЗДЕСЬ НАПИСАТЬ, чтоб оно заработало? И Может где-нить еще надо что-то вписывать?
End;
У него есть свойства Style,Text,Items,ItemIndex(ну и другие:).
В дизайнере задайте несколько строк в Items,поиграйте со Style -
посмотрите чему при разных стилях равны ItemIndex,Text.
Затем, при вычислении используете выбранное значение ComboBox'a
b - результа расчетов до округления
....................
case ComboBox.ItemIndex of
0 : a := 0; //до целых
1 : a := -1; //до десятых
2 : a := -2; //до сотых
end;
result := RoundTo(b,a); //RoundTo в модуле Math
Если вы заметили орфографическую ошибку на этой странице, просто выделите ошибку мышью и нажмите Ctrl+Enter. Функция может не работать в некоторых версиях броузеров.