У меня есть много пользовательских событий C#, которые связаны с объектами, выбираемыми в дереве и затем контекстном меню, используемом для инициирования некоторого действия с выбранными пунктами. Я начал создавать отдельный находящийся в EventArgs класс для каждого пользовательского события, упаковывать необходимые данные для события.
В непредусмотрительности, хотя, я понимаю, что большинство (возможно, все) моих пользовательских событий должно будет передать, по крайней мере, список основных объектов, представленных древовидным выбором. Некоторым событиям, вероятно, будут нужны дополнительные данные также.
Имея это в виду, интересно, является ли любое из следующего приемлемой практикой?
Используйте тот же пользовательский находящийся в EventArgs класс для нескольких событий (те, которым просто нужен список объектов, который будет передан). Очевидно, это должно работать, но, кажется, покончило с некоторыми рекомендуемыми соглашениями о присвоении имен, используемыми для проводного соединения оборудования события.
Создайте базовый класс, который оборачивает мой часто необходимый список объектов, и затем получите дополнительные классы из него, поскольку дополнительные данные необходимы.
Возможно, что-то еще полностью?
В настоящее время я только имею горстку пользовательских событий, но должен добавить больше. Так как я вижу, что шаблон появляется относительно данных, необходимых каждому событию, я хотел бы иметь лучший план перед продолжением.
Спасибо за любой совет.
Ниже приведен полный пример отображения данных с линейной оси на окружность.
Я показываю два способа достижения цели:
Основная идея: если у вас есть ряд D
, то сопоставьте точки с окружностью, где радиус равен значениям данных, используя:
theta = linspace(0, 2*pi, N); %# divide circle by N points (length of data)
r = data; %# radius
x = r.*cos(theta); %# x-coordinate
y = r.*sin(theta); %# y-coordinate
plot(x, y, '-');
%# some random data
K = 3;
N = 30;
data = zeros(K,N);
data(1,:) = 0.2*randn(1,N) + 1;
data(2,:) = 0.2*randn(1,N) + 2;
data(3,:) = 0.2*randn(1,N) + 3;
center = [0 0]; %# center (shift)
radius = [data data(:,1)]; %# added first to last to create closed loop
radius = normalize(radius',1)'+1; %# normalize data to [0,1] range
figure, hold on
%# draw outer circle
theta = linspace(5*pi/2, pi/2, 500)'; %# 'angles
r = max(radius(:)); %# radius
x = r*cos(theta)+center(1);
y = r*sin(theta)+center(2);
plot(x, y, 'k:');
%# draw mid-circles
theta = linspace(5*pi/2, pi/2, 500)'; %# 'angles
num = 5; %# number of circles
rr = linspace(0,2,num+2); %# radiuses
for k=1:num
r = rr(k+1);
x = r*cos(theta)+center(1);
y = r*sin(theta)+center(2);
plot(x, y, 'k:');
end
%# draw labels
theta = linspace(5*pi/2, pi/2, N+1)'; %# 'angles
theta(end) = [];
r = max(radius(:));
r = r + r*0.2; %# shift to outside a bit
x = r*cos(theta)+center(1);
y = r*sin(theta)+center(2);
str = strcat(num2str((1:N)','%d'),{}); %# 'labels
text(x, y, str, 'FontWeight','Bold');
%# draw the actual series
theta = linspace(5*pi/2, pi/2, N+1);
x = bsxfun(@times, radius, cos(theta)+center(1))';
y = bsxfun(@times, radius, sin(theta)+center(2))';
h = zeros(1,K);
clr = hsv(K);
for k=1:K
h(k) = plot(x(:,k), y(:,k), '.-', 'Color', clr(k,:), 'LineWidth', 2);
end
%# legend and fix axes
legend(h, {'M1' 'M2' 'M3'}, 'location', 'SouthOutside', 'orientation','horizontal')
hold off
axis equal, axis([-1 1 -1 1] * r), axis off
%# some random data
K = 3;
N = 30;
data = zeros(K,N);
data(1,:) = 0.2*randn(1,N) + 1;
data(2,:) = 0.2*randn(1,N) + 2;
data(3,:) = 0.2*randn(1,N) + 3;
center = [0 0]; %# center (shift)
radius = [data data(:,1)]; %# added first to last to create closed loop
radius = normalize(radius',1)'; %# normalize data to [0,1] range
radius = bsxfun( @plus, radius, (1:2:2*K)' ); %# 'make serieson seperate ranges by addition
figure, hold on
%# draw outer circle
theta = linspace(5*pi/2, pi/2, 500)'; %# 'angles
r = max(radius(:))+1; %# radius
x = r*cos(theta)+center(1);
y = r*sin(theta)+center(2);
plot(x, y, 'k:');
%# draw mid-circles
theta = linspace(5*pi/2, pi/2, 500)'; %# 'angles
r = 1.5; %# radius
for k=1:K
x = r*cos(theta)+center(1);
y = r*sin(theta)+center(2);
plot(x, y, 'k:');
r=r+2; %# increment radius for next circle
end
%# draw labels
theta = linspace(5*pi/2, pi/2, N+1)'; %# 'angles
theta(end) = [];
r = max(radius(:))+1;
r = r + r*0.2; %# shift to outside a bit
x = r*cos(theta)+center(1);
y = r*sin(theta)+center(2);
str = strcat(num2str((1:N)','%d'),{}); %# 'labels
text(x, y, str, 'FontWeight','Bold');
%# draw the actual series
theta = linspace(5*pi/2, pi/2, N+1);
x = bsxfun(@times, radius, cos(theta)+center(1))';
y = bsxfun(@times, radius, sin(theta)+center(2))';
h = zeros(1,K);
clr = hsv(K);
for k=1:K
h(k) = plot(x(:,k), y(:,k), '.-', 'Color', clr(k,:), 'LineWidth', 2);
end
%# legend and fix axes
legend(h, {'M1' 'M2' 'M3'}, 'location', 'SouthOutside', 'orientation','horizontal')
hold off
axis equal, axis([-1 1 -1 1] * r), axis off
Следует отметить, что normalize ()
является пользовательской функцией, она просто выполняет нормализацию minmax ( (x-min )/( max-min)
), определяемую как:
function newData = normalize(data, type)
[numInst numDim] = size(data);
e = ones(numInst, 1);
minimum = min(data);
maximum = max(data);
range = (maximum - minimum);
if type == 1
%# minmax normalization: (x-min)/(max-min) => x in [0,1]
newData = (data - e*minimum) ./ ( e*(range+(range==0)) );
end
%# (...)
end
-121--4617230- Из связанного вопроса, который конкретно просил решение быть pythonic, вы должны попробовать в библиотеке motmot's camiface от Эндрю Стро. Он также работает с камерами firewire, но он также работает с виджетом, который вы ищете.
Из учебного пособия:
import motmot.cam_iface.cam_iface_ctypes as cam_iface
import numpy as np
mode_num = 0
device_num = 0
num_buffers = 32
cam = cam_iface.Camera(device_num,num_buffers,mode_num)
cam.start_camera()
frame = np.asarray(cam.grab_next_frame_blocking())
print 'grabbed frame with shape %s'%(frame.shape,)
-121--3855367- Я уже делал этот путь. Я пошел с вашей второй идеей иметь базовый класс событий, который оборачивает общие данные. Если ни одно событие не будет использовать его напрямую, сделайте базовый класс внутренним, чтобы не предоставлять ненужные объекты пользователям. Наличие базового класса также позволяет добавлять дополнительные данные о событиях позже. Поскольку класс является внутренним, пользователи его внешне не подвержены изменениям.
Вы имеете в виду что-то вроде
public class EventArgs<TValue> : EventArgs
{
public TValue Value { get; }
/* ... */
}
?
Где я могу использовать в качестве значения
все, что мне нравится?
Да, Я с удовольствием пользуюсь такой штукой. Не думаю, что это проблема.
Я бы выбрал и один, и два. Создайте базовый класс, который вы можете использовать для большинства ваших событий, а затем наследовать от этого класса для событий, которым нужно что-то еще. Если вы посмотрите на библиотеки .NET, именно так они были созданы.
Просто убедитесь, что вы используете соответствующее соглашение об именах. Базовый класс не должен включать имя определенного события, только класс, который используется только в одном событии, должен ссылаться на имя события. Базовый класс, вероятно, будет включать имя вашего элемента управления.
Существует много примеров этого в рамке.NET. Это было бы довольно последовательно, чтобы сделать что-то в том же направлении. Вот пара:
я мог бы использовать класс как это ( не краткий обзор).
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
public class CollectionEventArgs<T> : EventArgs
{
public static readonly CollectionEventArgs<T> Empty = new CollectionEventArgs<T>();
public CollectionEventArgs(params T[] items)
{
this.Items = new ReadOnlyCollection<T>(items);
}
public CollectionEventArgs(IEnumerable<T> items)
{
this.Items = new ReadOnlyCollection<T>(items.ToArray());
}
public ReadOnlyCollection<T> Items
{
get;
private set;
}
}