у меня проблема с AutoScroll и рисованием (суть вопроса после кода). Я вот по такому коду рисую AVL- дерево:
namespace AVL
{
public partial class Form1 : Form
{
RandomFill rand;
List<int> list;
const int SIZE = 25;
const int WIDTH = 30;
const int HEIGHT = 30;
Font dataFont = new Font(FontFamily.GenericSerif, HEIGHT / 2, FontStyle.Bold);
AVL tr = new AVL();
List<Point> pointList = new List<Point>(0);
List<int> dataList = new List<int>(0);
public Form1()
{
rand = new RandomFill(SIZE);
list = rand.GetRandomFilledList();
InitializeComponent();
for (int i=0; i<SIZE; i++)
{
tr.Add(list[i]);
}
}
public void DisplayTree(AVL.Node root, Graphics graph, Pen pen, List<Point> pointList, List<int> dataList)
{
DrawConnectingines(root, graph, pen);
for (int i = 0; i < pointList.Count; i++)
{
graph.DrawEllipse(pen, pointList[i].X, pointList[i].Y, WIDTH, HEIGHT);
graph.FillEllipse(Brushes.White, pointList[i].X, pointList[i].Y, WIDTH, HEIGHT);
graph.DrawString(dataList[i].ToString(), dataFont, Brushes.Black, pointList[i].X, pointList[i].Y);
}
}
private void DrawConnectingines(AVL.Node root, Graphics graph, Pen pen)
{
if (root.left != null)
{
graph.DrawLine(pen, root.point.X + WIDTH/2, root.point.Y + HEIGHT/2, root.left.point.X + WIDTH / 2, root.left.point.Y + HEIGHT / 2);
DrawConnectingines(root.left, graph, pen);
}
if (root.right != null)
{
graph.DrawLine(pen, root.point.X + WIDTH / 2, root.point.Y + HEIGHT / 2, root.right.point.X + WIDTH / 2, root.right.point.Y + HEIGHT / 2);
DrawConnectingines(root.right, graph, pen);
}
}
private void PushNodesInList(AVL.Node root, List<Point> pointList, List<int> dataList)
{
if (root.left != null)
{
PushNodesInList(root.left, pointList, dataList);
}
root.point.X = (WIDTH + WIDTH) * pointList.Count;
root.point.Y = (HEIGHT + HEIGHT) * root.level;
pointList.Add(root.point);
dataList.Add(root.data);
if (root.right != null)
{
PushNodesInList(root.right, pointList, dataList);
}
}
private void treePanel_Paint(object sender, PaintEventArgs e)
{
Graphics graph = e.Graphics;
Pen pen = new Pen(Color.Black, 1);
//рисование
tr.RecountDepth();
DisplayTree(tr.GetRoot(), graph, pen, pointList, dataList);
}
private void button1_Click(object sender, EventArgs e)
{
pointList.Clear();
dataList.Clear();
PushNodesInList(tr.GetRoot(), pointList, dataList);
treePanel.Refresh();
}
}
}
Проблема в том, что если дерево не влезает в treePanel, то нужен Scroll рисунка, но как его реализовать, я не знаю. Свойство AutoScroll у treePanel работает только если я вместо рисования кругов рисую Label-метки, но даже в этом случае рисунок как-то странно съезжает, т.е. проблему это не решает (наверное)
Помогите, пожалуйста кодом или советом!)
1-изображение - это нужно устранить 2-изображение - А вот так пока получается, но нужно , чтобы можно было скроллить После ответа ниже - понял, что делал неправильно, код будет примерно следующий (линии я пока не нарисовал, но скроллящееся дерево без соединительных линий - уже есть) Вот обновлённый код:
namespace AVL
{
public partial class Form1 : Form
{
//GraphicsPath
System.Drawing.Drawing2D.GraphicsPath myPath;
//
RandomFill rand;
List<int> list;
const int SIZE = 25;
const int WIDTH = 30;
const int HEIGHT = 30;
Font dataFont = new Font(FontFamily.GenericSerif, HEIGHT / 2, FontStyle.Bold);
AVL tree = new AVL();
List<Point> pointList = new List<Point>(0);
List<int> dataList = new List<int>(0);
public Form1()
{
//на замену предыдущему способу - GraphicsPath!
myPath = new System.Drawing.Drawing2D.GraphicsPath();
//
rand = new RandomFill(SIZE);
list = rand.GetRandomFilledList();
InitializeComponent();
for (int i = 0; i < SIZE; i++)
{
tree.Add(list[i]);
}
}
private void treePanel_Paint(object sender, PaintEventArgs e)
{
pointList.Clear();
dataList.Clear();
tree.RecountDepth();
PushNodesInList(tree.GetRoot(), pointList, dataList);
}
public void DisplayTree(AVL.Node root, Graphics graph, Pen pen, List<Point> pointList, List<int> dataList)
{
for (int i = 0; i < pointList.Count; i++)
{
myPath.AddEllipse(pointList[i].X, pointList[i].Y, WIDTH, HEIGHT);
}
}
private void PushNodesInList(AVL.Node root, List<Point> pointList, List<int> dataList)
{
if (root.left != null)
{
PushNodesInList(root.left, pointList, dataList);
}
root.point.X = (WIDTH + WIDTH) * pointList.Count + delta * WIDTH;
root.point.Y = (HEIGHT + HEIGHT) * root.level;
pointList.Add(root.point);
dataList.Add(root.data);
if (root.right != null)
{
PushNodesInList(root.right, pointList, dataList);
}
}
private void CheckForScroll(AVL.Node root)
{ //Нужна для расширения panel1, которая есть наше дерево. Если не помещается дерево - panel1 расширится и на panel2 должен появиться скроллбар.
int treePanelCurrentWidth = panel1.Width;
if (root.right != null)
{
CheckForScroll(root.right);
}
if (root.right == null && root.point.X > treePanelCurrentWidth)
{
panel1.Width = root.point.X + WIDTH;
}
}
private void button1_Click(object sender, EventArgs e)
{
CheckForScroll(tree.GetRoot());
panel1.BackColor = Color.Yellow;
panel1.Region = new Region(myPath);
}
}
}
Для начала проясним ошибочное предположение: нарисованное изображение не является контентом, с точки зрения ScrolableControl
, от которого наследуются все контролы, которые поддерживают скроллинг. Таким образом, свойство AutoScroll
не может вам помочь, так как учитывает только вложенные контролы. Даже принудительная ручная активация скролла вам в данном случае не поможет.
Какие есть варианты? Основных три. Остальные - производные.
Так как скролл учитывает только контролы, то строить изображение с помощью кастомных контролов. Через свойство Control.Region
можно придать контролу любую форму (вершина, ребро, да хоть весь граф).
Использовать двухслойную модель контрола, т.е. за скролл отвечает один, а рисуем на другом, вложенном в первый. При этом во время рисования не забываем изменять размер контрола на котором рисуем так, чтобы изображение умещалось полностью, тогда, как только вложенный контрол перестанет умещаться в родительском, активируется автоскролл и появится возможность прокрутки.
Берем скрол полностью в свои руки, исключив все автоматические рюшечки. Фактически, мы просто добавляем полосы скролла и с их помощью управляем положением изображения вручную. Для этого изображение целиком должно быть представлено объектом GraphicsPath
, для которого можно задать позиционирование при отрисовке.
Если нужна только картинка, я бы предпочел последний вариант. Для интерактива - без вариантов первый. Второй - как переходный от вашего решения к любому более специализированному.
Пока как-то так.
Оборудование для ресторана: новинки профессиональной кухонной техники
Частный дом престарелых в Киеве: комфорт, забота и профессиональный уход
При нажатие на [GameObject] в моём случае им является [Button], нужно удалить это [GameObject] и заспавнить новый [GameObject] с чем мой скрипт успешно справляется,...
Необходимо выполнить очень много POST запросов на сайт, получить ответ (типо "1,2,3" добавить в массив и отправить запросы на другой URL
Есть свой User ControlКак вложить в него например TextBlock как ето сделано в ScrollViewer?
Есть ссылка на сайтНеобходимо получить selector или xpath для всех доступных элементов