Консультация № 192443
23.01.2018, 12:08
0.00 руб.
0 17 1
Здравствуйте! У меня возникли сложности с таким вопросом: На форме лежат MainMenu, Chart. Как добавляя Series на Chart, автоматически создавать MenuItem в MainMenu с именами Series и возможностью установления галочки, при выборе в меню нужного пункта.

Обсуждение

давно
Старший Модератор
31795
6196
23.01.2018, 12:15
общий
Адресаты:
Покажите, что у Вас есть, посмотрим, что можно доделать.
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

давно
Посетитель
400264
21
23.01.2018, 12:33
общий
25.01.2018, 10:37
Серия строится по данным заключённым в текстовый файл, название файла и есть название серии, структура его следующая (x y Color)

[code lang=pascal] od := TOpenDialog.Create(self);
od.InitialDir := GetCurrentDir;
od.Options := [ofFileMustExist];
od.Filter := '*.txt';

if od.Execute then
begin
fn := od.FileName;
while pos('\', fn) > 0 do
delete(fn, 1, pos('\', fn));
sl := TStringList.Create;
sl.LoadFromFile(fn);

Chart.AddSeries(TLineSeries.Create(self));
j:= Chart.SeriesCount -1 ;
Chart.Series[j].Clear;

for i := 0 to sl.Count - 1 do
begin
fn := sl[i];
x := StrToFloat(copy(fn, 1, pos(' ', fn) - 1));
delete(fn, 1, pos(' ', fn));
// y := StrToFloat(w);
y := StrToFloat(copy(fn, 1, pos(' ', fn) - 1));
delete(fn, 1, pos(' ', fn));
Color:= StringToColor(fn);

Chart.Series[j].AddXY(x, y, '',Color);
end;
sl.Free;

end
else
ShowMessage('Ошибка открытия файла');
od.Free;[/code]
давно
Старший Модератор
31795
6196
25.01.2018, 10:36
общий
25.01.2018, 10:39
Адресаты:
Можно немного проще, не думаю, что у Вас будет не ограниченное количество серий, по этому можно создать, к примеру 20-ть меню второго уровня и спрятать их с помощью свойства visible:=false. При загрузке серий - открыть нужное количество подменю, одновременно с этим менять их Caption:='Show Series 1'- показать серию . Если было нажатие на пункт подменю, показать серию и поменять заголовок на Caption:='Hide Series 1'. Следующим кликом в нужной строке серия будет спрятана, также соответственно вернуть Caption:='Show Series 1'. Т.е CheckBox не обязательно использовать.

Если количество серий не ограниченно можно динамически добавлять подменю:
[code lang=pascal]procedure tform1.addsubitem(s: string; to : integer);
var
newitem, toitem: Tmenuitem;
begin
{to = верхний уровень меню для нового пункта}
toitem := mainmenu1.items[to ];
newitem := tmenuitem.create(toitem);
newitem.caption := s;
{если вы хотите определить событие onclick
newitem.onclick:=Dynamenuclick; }
toitem.onclick := nil;
toitem.insert(toitem.count, newitem);
removemenuitem1.enabled := true;
end;[/code]

И ещё, я бы использовал вместо OpenDialog (при неограниченном количестве, удобней, чем каждый раз открывать их все) - функции FindFirst | FindNext, они по маске найдут все файлы с сериями. Загрузить их в какой нибудь ListBox, и потом извлекать имя нужной серии и загружать её.
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

давно
Посетитель
400264
21
25.01.2018, 11:54
общий

procedure tform1.addsubitem(s: string; to : integer);
Ругается программа на "to"
давно
Посетитель
400264
21
25.01.2018, 11:59
общий
removemenuitem1.enabled := true;

И на "removemenuitem1" тоже, мне кстати тоже не совсем понятно что это. newitem, toitem и вдруг removemenuitem1
давно
Старший Модератор
31795
6196
25.01.2018, 12:08
общий
25.01.2018, 12:10
Адресаты:
Посмотрите этот Урок 16. Динамически меняем меню или Динамическое добавление пунктов меню
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

давно
Старший Модератор
31795
6196
26.01.2018, 14:28
общий
Адресаты:
получилось, что либо сделать?
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

давно
Старший Модератор
31795
6196
01.02.2018, 20:41
общий
это ответ
Здравствуйте, 08101967!

Смотрите приложение:
[code lang=pascal h=300]unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, TeEngine, Series, ExtCtrls, TeeProcs, Chart, Menus;
type
TForm1 = class(TForm)
MainMenu1: TMainMenu;
File1: TMenuItem;
LoadSeries1: TMenuItem;
Exit1: TMenuItem;
Chart1: TMenuItem;
FreeAllSeries1: TMenuItem;
s11: TMenuItem;
s21: TMenuItem;
s31: TMenuItem;
s41: TMenuItem;
s51: TMenuItem;
s61: TMenuItem;
Chart2: TChart;
Series1: TLineSeries;
procedure LoadSeries1Click(Sender: TObject);
procedure Exit1Click(Sender: TObject);
procedure FreeAllSeries1Click(Sender: TObject);
procedure s11Click(Sender: TObject);
procedure s21Click(Sender: TObject);
procedure s31Click(Sender: TObject);
procedure s41Click(Sender: TObject);
procedure s51Click(Sender: TObject);
procedure s61Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure MyMenuOnClick(a:string);
var
b,c:integer;
begin
b:=1;
c:=0;
while b < Form1.MainMenu1.Items[1].Count do
begin
if Form1.MainMenu1.Items[1].Items[b].Checked then inc(c);
inc(b);
end;
b:=1;
while(b < Form1.MainMenu1.Items[1].Count) and
(Form1.MainMenu1.Items[1].Items[b].Caption <> a) and
(pos('.',Form1.MainMenu1.Items[1].Items[b].Caption)>0) do inc(b);
if (c > 1) or (not Form1.MainMenu1.Items[1].Items[b].Checked) then
begin
if b < Form1.MainMenu1.Items[1].Count then
begin
Form1.Chart2.Series[b].Active:= not Form1.Chart2.Series[b].Active;
Form1.MainMenu1.Items[1].Items[b].Checked:=not Form1.MainMenu1.Items[1].Items[b].Checked;
end;
end
else ShowMessage('This last series, please turn on FreeAllSeries');
end;
procedure TForm1.s11Click(Sender: TObject);
begin
MyMenuOnClick((Sender as TMenuItem).Caption);
end;
procedure TForm1.s21Click(Sender: TObject);
begin
MyMenuOnClick((Sender as TMenuItem).Caption);
end;
procedure TForm1.s31Click(Sender: TObject);
begin
MyMenuOnClick((Sender as TMenuItem).Caption);
end;
procedure TForm1.s41Click(Sender: TObject);
begin
MyMenuOnClick((Sender as TMenuItem).Caption);
end;
procedure TForm1.s51Click(Sender: TObject);
begin
MyMenuOnClick((Sender as TMenuItem).Caption);
end;
procedure TForm1.s61Click(Sender: TObject);
begin
MyMenuOnClick((Sender as TMenuItem).Caption);
end;
procedure TForm1.LoadSeries1Click(Sender: TObject);
var
Find:TSearchRec;
Data:TStringList;
i,j:integer;
begin
if FindFirst('s*.dat',faAnyFile,Find)=0 then
begin
Chart2.FreeAllSeries;
j:=1;
repeat
MainMenu1.Items[1].Items[j].Visible:=true;
MainMenu1.Items[1].Items[j].Checked:=true;
MainMenu1.Items[1].Items[j].Caption:=Find.Name;
Data:=TStringList.Create;
Data.LoadFromFile(Find.Name);
Chart2.AddSeries(TLineSeries.Create(self));
for i:=0 to Data.Count-1 do
begin
Chart2.Series[Chart2.SeriesCount-1].AddXY(
StrToFloat(copy(Data[i],1,pos(' ',Data[i])-1)),
StrToFloat(copy(Data[i],pos(' ',Data[i])+1,length(Data[i]))),'');
end;
Data.Free;
inc(j);
until FindNext(Find)<>0;
Form1.MainMenu1.Items[0].Items[0].Enabled:=false;
Form1.MainMenu1.Items[1].Enabled:=true;
end
else
ShowMessage('File not found');
end;
procedure TForm1.Exit1Click(Sender: TObject);
begin
Form1.Chart2.FreeAllSeries;
Form1.Close;
end;
procedure TForm1.FreeAllSeries1Click(Sender: TObject);
var
a:integer;
begin
Form1.Chart2.FreeAllSeries;
a:=1;
While a < Form1.MainMenu1.Items[1].Count do
begin
MainMenu1.Items[1].Items[a].Visible:=false;
MainMenu1.Items[1].Items[a].Checked:=false;
MainMenu1.Items[1].Items[a].Caption:='s'+IntToStr(a);
inc(a);
end;
Form1.MainMenu1.Items[0].Items[0].Enabled:=true;
Form1.MainMenu1.Items[1].Enabled:=false;
end;
end.[/code]

На форме Вы должны создать следующую структуру:


Удачи!
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

давно
Старший Модератор
31795
6196
02.02.2018, 20:44
общий
Адресаты:
Вам такое решение подходит?
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

давно
Посетитель
400264
21
03.02.2018, 13:51
общий
Здравствуйте! Извините за молчание. Я сделал всё руководствуясь Динамическое добавление пунктов меню, ссылку на которую вы дали. Но вот
как галочку установить при выборе в меню нужного пункта, я так и не разобрался.
давно
Старший Модератор
31795
6196
03.02.2018, 15:37
общий
Адресаты:
Вы пробывали код который я дал.
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

давно
Старший Модератор
31795
6196
03.02.2018, 15:43
общий
Адресаты:
Покажите свой код.
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

давно
Старший Модератор
31795
6196
05.02.2018, 12:27
общий
Адресаты:
Код покажите? Что именно у Вас не получается.
Код который я дал в ответе, был написан 26-го. Если Вам нужен код именно с динамичным меню - проект, у меня дома на компе, сейчас могу подсказать, что можно сделать для этого.
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

давно
Посетитель
400264
21
05.02.2018, 12:45
общий
Здравствуйте! Код вечером покажу, он у меня на работе. У меня всё добавляется и всё удаляется. Дело в том, что у меня только форма и меню, всё остальное у меня загружается, отдельно настройки Chart и отдельно его series. Мне надо в меню отмечать серию, с которой я хочу что то сделать, так как других компонентов у меня нет, я хочу в меню напротив нужной мне серии ставить галочку. Вот в ней у меня и загвоздка.
давно
Старший Модератор
31795
6196
05.02.2018, 12:53
общий
Адресаты:
Вы на эти строки внимание обращали:
[code lang=asm] Form1.Chart2.Series[b].Active:= not Form1.Chart2.Series[b].Active;
Form1.MainMenu1.Items[1].Items[b].Checked:=not Form1.MainMenu1.Items[1].Items[b].Checked;[/code]
Первая прячет-показывает график на Чарте, а вторая прячет-ставит галочку.
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

давно
Посетитель
400264
21
05.02.2018, 18:08
общий
У Вас там почему то в :

Chart2.Series[Chart2.SeriesCount-1].AddXY(
StrToFloat(copy(Data[i],1,pos(' ',Data[i])-1)),
StrToFloat(copy(Data[i],pos(' ',Data[i])+1,length(Data[i]))),'');

ошибка вылетает, я не стал разбираться

Вставил свой кусок он рабочий:

fn := sl[i];
x := StrToFloat(copy(fn, 1, pos(' ', fn) - 1));
delete(fn, 1, pos(' ', fn));
y := StrToFloat(copy(fn, 1, pos(' ', fn) - 1));
delete(fn, 1, pos(' ', fn));
Color:= StringToColor(fn);
Chart.Series[j].AddXY(x, y, '',Color);

Вроде всё получилось. Галочка появляется, спасибо.
давно
Старший Модератор
31795
6196
06.02.2018, 13:23
общий
06.02.2018, 13:23
Адресаты:
Жаль Вы не показали Весь код.
В прикрепленном файле проект с динамикой.
Снова дома забыл флешку, написал сегодня по памяти.
Прикрепленные файлы:
4ddecbd024bb4fcb678f6cc0db8bc870.zip
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

Форма ответа