Καλώς ορίσατε στο dotNETZone.gr - Σύνδεση | Εγγραφή | Βοήθεια
σε

 

Αρχική σελίδα Ιστολόγια Συζητήσεις Εκθέσεις Φωτογραφιών Αρχειοθήκες

ΣΧΕΔΙΑΣΗ ΜΕ C#

Îåêßíçóå áðü ôï ìÝëïò vtops. Τελευταία δημοσίευση από το μέλος KelMan στις 29-10-2011, 17:04. Υπάρχουν 4 απαντήσεις.
Ταξινόμηση Δημοσιεύσεων: Προηγούμενο Επόμενο
  •  27-10-2011, 22:24 67939

    ΣΧΕΔΙΑΣΗ ΜΕ C#

    Καλησπέρα σε όλους,

    Γενικά με την σχεδίαση δεν έχω ασχοληθεί καθόλου και μου έχει ανατεθεί το εξής project:

    Πάνω σε μια φόρμα να απεικονίζω τελείες (όπου το μέγεθος το χρώμα και οι συντεταγμένεςυπάρχουν μέσα σε ένα αρχείο), και στην συνέχεια ο χρήστης με το ποντίκι θα ενώνει τις τελείες με κάποιο μολύβι  με όποια σειρά θέλει. Το πρόγραμμα θα ελέγχει αν τις έχει ενώσει με την σωστή σειρά και αν όχι θα τις ενώνει με την σειρά που πρέπει. (Η σειρά που θα ενωθούν οι τελείες είναι καταχωρημένη στο ίδιο αρχείο)

    Απλό μου ακούγεται , αλλά δεν ξέρω καν από που να ξεκινήσω, γιατί δεν έχω ασχοληθεί καθόλου με τέτοιου είδους κλάσεις.

    Καμιά ιδέα;

    Ευχαριστώ!

    Best Regards
  •  28-10-2011, 09:38 67953 σε απάντηση της 67939

    Απ: ΣΧΕΔΙΑΣΗ ΜΕ C#

    Μπορείς να ψάξεις για GDI+. Δεν είναι και ότι πιο γρήγορο, αλλά από ότι περιγράφεις μου ακούγεται το καταλληλότερο. Περί ζωγραφικής τουλάχιστον.
    "When the darkness rises up from inside - that is normal.
    It's when you reach down to pull it up - that the noxious warnings sound."
    Tuzak, Farscape
  •  28-10-2011, 21:23 67954 σε απάντηση της 67953

    Απ: ΣΧΕΔΙΑΣΗ ΜΕ C#

    Σίγουρα μπορεί να γίνει με διάφορες τεχνολογίες όπως GDI+ και DirectX (Managed DirectX για την περίπτωσή σου) αλλά θα σου πρότεινα να ανέβεις ένα σκαλί στο abstraction και να πας σε WPF ή σε Silverlight. Με αυτόν τον τρόπο θα μπορείς να δουλέψεις με τα objects κανονικά, με τα properties και τα events τους και τα όλα τους. Για παράδειγμα, θα μπορεί η "τελεία" να κάνει raise event ότι έγινε κλικ πάνω της και να μην ασχολείσαι συνεχώς με το σε τι συντεταγμένες έχει γίνει το κλικ και τι έχει από κάτω. Από εκεί και πέρα το να ζωγραφίσεις μια ευθεία από τις συντεταγμένες (Χ1,Υ1) στις (Χ2,Υ2), ας πούμε με WPF ή Silverlight, είναι γελοίο, είτε με XAML:

      <Line X1="10" Y1="10"
        X2="50" Y2="50"
        Stroke="Black"
        StrokeThickness="4" />

    είτε με κώδικα

    var myLine = new Line();
    myLine.Stroke = System.Windows.Media.Brushes.LightSteelBlue;
    myLine.X1 = 1;
    myLine.X2 = 50;
    myLine.Y1 = 1;
    myLine.Y2 = 50;
    myLine.HorizontalAlignment = HorizontalAlignment.Left;
    myLine.VerticalAlignment = VerticalAlignment.Center;
    myLine.StrokeThickness = 2;
    ...

     


    Vir prudens non contra ventum mingit
  •  29-10-2011, 14:07 67961 σε απάντηση της 67939

    Απ: ΣΧΕΔΙΑΣΗ ΜΕ C#

    Graph δηλαδή πέπει να φτιάξεις, με τελείες (Nodes) και γραμμές. Δεν γνωρίζω καμία κλάση γιά graphs αλλά όσον αφορά τον σχεδιασμό κύκλων και γραμμών το System.drawing namespace έχει ότι χρειάζεσαι και πολλά άλλα. Αυτό έιναι ένα Game στην ουσία με rules και levels. Δες αν θέλεις τον παρακάτω κώδικα που Δημιουργεί και μετακινεί nodes με δεξί click και τους ενώνει με αριστερό. Ο παρακάτω κώδικας δεν είναι optimized αλλά μπορείς να πάρεις μία ιδέα.

     

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
     
    using System ;
    using System.Collections.Generic ;
    using System.ComponentModel ;
    using System.Data ;
    using System.Drawing ;
    using System.Linq ;
    using System.Text ;
    using System.Windows.Forms ;
    using System.Drawing.Drawing2D ;
    
    namespace Graph // To όλο "σκηνικό" λέγεται και Graph.
    {
        // Θα πρέπει να βάλεις τον κώδικα αυτόν σε custom control και όχι σε φόρμα κατ' ευθείαν.
        public partial class frmMain : Form
        {
    
            public frmMain()
            {
                InitializeComponent() ;
    
                // Double Buffering
                // Flickering reduction. Τεχνική που βοηθάει να βγει το "τρεμούλιασμα"
                this.SetStyle(ControlStyles.UserPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true) ;
            }
    
            private List<Node> _Nodes = new List<Node>() ; // Οι Τελείες λέγονται και Nodes.
            private Line _TempLine ; // Η προσωρινή γραμμή που εμφανίζεται όταν ξεκινάμε να ενώσουμε 2 τελείες ( Nodes ).
            private Node _SelectedNode ; // Το node που επιλέξαμε ή μόλις δημιουργήσαμε ( με δεξί click ).
    
            protected override void OnPaint(PaintEventArgs e)
            {
                Pen pen = new Pen(Color.DarkOrange, 3.0f) ;
    
                if (_TempLine != null) 
                    _TempLine.Draw(e.Graphics) ;
    
                foreach (Node node in _Nodes) 
                {
                    foreach (Node NeighborNode in node.Neighbors)
                    {
                        e.Graphics.DrawLine(pen, node.Centre, NeighborNode.Centre) ;
                        // Optimize
                        // 1. Δεν πρέπει ένα neighbor Node να ξαναζωγραφίζει μία γραμμή που έχει ήδη ζωγραφιστεί.
                        // 2. Parallel ΟΛΑ.
                        NeighborNode.Draw(e.Graphics) ;
                    }
    
                    node.Draw(e.Graphics) ;
                }
    
                pen.Dispose() ;
    
                base.OnPaint(e) ;
            }
    
            protected override void OnMouseDown(MouseEventArgs e)
            {
                if (e.Button == MouseButtons.Right)
                {
                    _SelectedNode = this.GetNode(e.X, e.Y) ;
    
                    if (_SelectedNode == null)
                    {
                        Node node = new Node() ;
    
                        node.Location = new Point(e.X - node.Radius, e.Y - node.Radius) ;
                        _Nodes.Add(node) ;
                        _SelectedNode = node ;
    
                        this.Invalidate(false) ;
                    }
                }
                else if (e.Button == MouseButtons.Left)
                {
                    _SelectedNode = this.GetNode(e.X, e.Y) ;
    
                    if (_SelectedNode !=null )
                    {
                        Line line = new Line() ;
    
                        line.StartLocation = new Point(_SelectedNode.Location.X + _SelectedNode.Radius,
                                                       _SelectedNode.Location.Y + _SelectedNode.Radius) ;
    
                        _TempLine = line ;
                    }
                }
    
                base.OnMouseDown(e) ;
            }
    
            protected override void OnMouseMove(MouseEventArgs e)
            {
                if (e.Button == System.Windows.Forms.MouseButtons.Right)
                {
                    _SelectedNode.Location = new Point(e.X - _SelectedNode.Radius, e.Y - _SelectedNode.Radius) ;
    
                    // (Invalidate) Ανανέωση των αλλαγών. Αν έχεις πολλά nodes πρέπει να κάνεις invalidate με region και όχι όλο το control, 
                    // κάνωντας Draw μόνο τα γειτονικά nodes και !!! τις γραμμές που περνάνε από τον ίδιο χώρο !!!.
                    // Γιά αυτόν τον λόγο φλικάρει αρκετά χωρίς DBuffer.
                    this.Invalidate(false) ;
                }
                else if (e.Button == System.Windows.Forms.MouseButtons.Left && _TempLine != null) 
                {
                    _TempLine.EndLocation = new Point(e.X, e.Y) ;
                    this.Invalidate(false) ; 
                }
    
                base.OnMouseMove(e) ;
            }
    
            protected override void OnMouseUp(MouseEventArgs e)
            {
                if (e.Button == System.Windows.Forms.MouseButtons.Left)
                {
                    if (_TempLine != null)
                    {
                        Node targetNode = this.GetNode(e.X, e.Y) ;
    
                        if (targetNode != null && targetNode != _SelectedNode && !_SelectedNode.Neighbors.Contains(targetNode))
                        {
                            _SelectedNode.Neighbors.Add(targetNode) ;
    
                            if (!targetNode.Neighbors.Contains(_SelectedNode))
                                targetNode.Neighbors.Add(_SelectedNode) ;
                        }
                        else
                        {
                            System.Media.SystemSounds.Hand.Play() ;
                            System.Diagnostics.Debug.WriteLine("Invalid Join.") ;
                        }
    
                        _TempLine = null ;
                        this.Invalidate(false) ;
                    }
                }
    
                base.OnMouseUp(e) ;
            }
    
            private Node GetNode(int x, int y)
            {
                foreach (Node node in _Nodes)
                    // Picking
                    // Πολύ χρήσιμο method (IsVisible). Τσεκάρει αν κάποιο σημείο είναι μέσα στο path.
                    // Στην δική μας περίπτωση ελέγχει αν το ποντίκι είναι πάνω από ένα node.
                    if (node.Path.IsVisible(x, y)) 
                        return node ; 
                
                return null ;
            }
    
        }
    
        // ---------------------------------------------------------------------------------------
    
        // Σε αυτό το Class πρέπει να κάνεις implement Τo IDisposable γιατί 
        // Το Path Field κάνει expose ένα Disposable class (το GraphicsPath).
        internal class Node
        {
            internal List<Node> Neighbors = new List<Node>() ;
            internal readonly GraphicsPath Path = new GraphicsPath() ;
            internal Point Location ;
            internal int Radius = 8 ;
            internal Point Centre
            {
                get
                {
                    return new Point(this.Location.X + Radius, this.Location.Y + Radius) ;
                }
            }
    
            internal void Draw(Graphics graphics)
            {
                Pen pen = new Pen(Color.DarkOrange, 3.0f) ;
            
                Path.Reset() ;
                
                graphics.SmoothingMode = SmoothingMode.HighSpeed ; 
                Path.AddEllipse(Location.X, Location.Y, Radius * 2, Radius * 2) ;
                graphics.FillPath(Brushes.White, Path) ;
    
                // Antialiasing
                // Η γνωστή τεχνική και από τα παιγνίδια.
                // Χοντρικά Κάνει τις διαγώνιες γραμμές πιό ομαλές αλλά τρώει performance.
                graphics.SmoothingMode = SmoothingMode.AntiAlias ;
                graphics.DrawPath(pen, Path) ; 
    
                pen.Dispose() ;
            }
        }
    
        internal class Line
        {
            internal Point StartLocation ;
            internal Point EndLocation ;
    
            internal void Draw(Graphics graphics) 
            { 
                Pen pen = new Pen(Color.OrangeRed, 3.0f) ;
    
                graphics.SmoothingMode = SmoothingMode.AntiAlias ;
                graphics.DrawLine(pen, StartLocation.X, StartLocation.Y, EndLocation.X, EndLocation.Y) ;
    
                pen.Dispose() ;
            }
        }
    } // καλή επιτυχία

     

     

     

  •  29-10-2011, 17:04 67962 σε απάντηση της 67954

    Απ: ΣΧΕΔΙΑΣΗ ΜΕ C#

    Χωρίς να θέλω να μειώσω σε τίποτα την απάντηση του Libra Storm και θέλοντας απλά να υπογραμίσω αυτά που γλυτώνεις με το Silverlight και το WPF, ορίστε μια απλοϊκή υλοποίηση σε WPF:

     

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
     
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;
    
    namespace WpfApplication2
    {
        /// <summary>
        /// Interaction logic for MainWindow.xaml
        /// </summary>
        public partial class MainWindow : Window
        {
            private Ellipse selectedDot;
            private Random rnd = new Random(System.Environment.TickCount);
    
            public MainWindow()
            {
                InitializeComponent();
            }
    
            private void Button1_Click(object sender, RoutedEventArgs e)
            {
                for (var i = 1; i <= 10; i++)
                {
                    var dot = new Ellipse
                    {
                        Height = 10,
                        Width = 10,
                        StrokeThickness = 2,
                        Fill = Brushes.Yellow,
                        Stroke = Brushes.Black,
                        Tag = i
                    };
    
                    var randomPoint = new Point(rnd.Next(5, (int)MainGrid.ActualWidth - 5), rnd.Next(5, (int)MainGrid.ActualHeight - 5));
                    dot.SetValue(Canvas.LeftProperty, randomPoint.X);
                    dot.SetValue(Canvas.TopProperty, randomPoint.Y);
    
                    MainGrid.Children.Add(dot);
    
                    dot.MouseUp += dot_MouseUp;
                }
            }
    
            private void dot_MouseUp(object sender, MouseButtonEventArgs e)
            {
                var dot = (Ellipse)sender;
    
                if (selectedDot != null)
                {
                    selectedDot.Fill = Brushes.Yellow;
                }
    
                dot.Fill = Brushes.Blue;
    
                if (selectedDot != null && dot != null)
                {
                    if (Math.Abs((int)selectedDot.Tag - (int)dot.Tag) == 1)
                    {
                        AddNewLine((double)selectedDot.GetValue(Canvas.LeftProperty),
                                   (double)dot.GetValue(Canvas.LeftProperty),
                                   (double)selectedDot.GetValue(Canvas.TopProperty),
                                   (double)dot.GetValue(Canvas.TopProperty));
                    }
                }
    
                selectedDot = dot;
            }
    
            private void AddNewLine(double x1, double x2, double y1, double y2)
            {
                var myLine = new Line();
                myLine.Stroke = Brushes.LightSteelBlue;
                myLine.X1 = x1;
                myLine.X2 = x2;
                myLine.Y1 = y1;
                myLine.Y2 = y2;
                myLine.StrokeThickness = 2;
                MainGrid.Children.Add(myLine);
            }
    
        }
    }

    Έχουμε 10 Ellipse objects που τοποθετούνται τυχαία πάνω στη φόρμα σε ένα Canvas (θα χρειαστεί να προσθέσεις ένα button και να κάνεις wire up το click event για να εμφανιστούν τα dots) και ο χρήστης μπορεί να ενώσει μόνο αυτά που σχετίζονται (μέσω του Tag property). Το θέμα δεν είναι τόσο σε αυτό το κομμάτι της λογικής, όσο τα πλεονεκτήματα αυτής της λύσης:

    • Δεν χρειάζεται να ασχοληθείς με το rendering (antializing, double buffers, smoothing modes, κλπ)
    • Δεν χρειάζεται να ασχοληθείς με το dispose των γραφικών στοιχείων
    • Δεν χρειάζεται να ζωγραφίζεις τα πάντα κάθε φορά, μόνο τη γραμμή που σου χρειάζεται
    • Το κάθε Ellipse κάνει raise event στο mouse up και έχεις απευθείας τις συντεταγμένες που του αντιστοιχούν χωρίς να ψάχνεις τίποτα

     

     

     

     


    Vir prudens non contra ventum mingit
Προβολή Τροφοδοσίας RSS με μορφή XML
Με χρήση του Community Server (Commercial Edition), από την Telligent Systems