Odwołanie się do elementu

Witam mam taki kłopot, Chciałbym się odwołać np. do pictureBox’a, który nosi nazwa box1 i mam dajmy na to 5 takich czyli:

box1, box2, box3 itd

i teraz cyfry pobieram z textbox’a(oznaczają do którego picturebox’a się odwołuje) i żeby nie pisać 10 razy to samo chciałbym dla jednego przycisku zaprogramować, że z textbox’a pobiera liczbę i następnie dodaje do box tworząc np. box1 innymi słowy box + textbox.text.

ale wtedy jest to string i c# wywala błąd, da się zrobić żeby nie traktował tego jako string a jako odwołanie do elemebtu(np. box1.location) w moim przypadku do pictureBox’a ? ale zamieszałem, mam nadzieje, że jednak zrozumiecie o co mi chodzi :slight_smile:

  1. Zawsze (najlepiej w nazwie tematu) wyraźnie zaznaczaj, w jakim języku/technologii piszesz.

  2. Jeżeli dobrze zrozumiałem, chcesz dynamicznie tworzyć nowe komponenty (czy jak to się w .NET zwie). W takim wypadku lepszym wyjściem będzie stworzenie kolekcji (np. listy) takich komponentów. Żaden nie będzie miał nazwy, ale będziesz się mógł do nich odwoływać (i dodawać, usuwać, czytać, zapisywać etc.) poprzez kolekcję i numer porządkowy.

Następnym razem będę pamiętał o tytule.

Mógłbyś dać jakiś przykład jak do tego mam się zabrać :)?

Może żeby lepiej zaobrazować chodzi o to, że tworze taką rozsypankę z 4 obrazków, każdy ma swoje położenie i przesuwam je za pomocą buttonów(góra, dól, prawo, lewo) a który przesuwam pobieram z textboxa, i teraz, żeby do każdego nie pisać tych samych instrukcji chciałbym żeby to wyglądało tak do każdego przycisku mam instrukcje(góra przesuwa o 10 jednostek w góre prawo przesuwa o 10 jednostek w prawo itd) i teraz zostało mi żeby pobrać tą liczbę z textbox’a i dodać przykład:

w textbocie 2 czyli przesuwamy 2 obrazek czyli:

"box"+"2".Location = new Point(box1.Location.X, box1.Location.Y - 10);

Takie rzeczy da się robić w językach dynamicznych. C# chyba robił jakieś podejścia w tym kierunku, ale nie wiem, jak w efekcie to działa.

Tak czy siak - to jak strzelanie z armaty do komara. Nie robię w .necie, ale opisane przeze mnie zachowanie jest raczej standardowe dla większości nowoczesnych języków programowania. Kod powinien wyglądać mniej więcej tak:

  1. Tworzysz listę pictureBoxów

    List pictures = new List();

  2. Dodajesz boxy

    pictures.add(new Picturebox());

    pictures.add(new Picturebox());

(albo w ten sam sposób dodajesz już wcześniej stworzone) 3. Czytasz z textBoxa numer obrazka, który chcesz przesunąć. Np. jest tam cyfra 2. Zapisujesz ją do zmiennej liczbowej np. “numer”. Potem odwołujesz się do listy - pozycji o jeden mniejszej (pamiętaj, że listy indeksuje się od 0 ).

pictures[numer - 1].Location =new Point(pictures[numer - 1].Location.X, pictures[numer - 1].Location.Y - 10);

Okey, dziękuje za odpowiedź zabiorę się za to i zobaczymy co mi wyjdzie :slight_smile:

Dodane 02.03.2013 (So) 13:08

Ehh już nie wiem, stworzyłem nawet taką listę i i tak mam 2 błedy, które towarzyszą mi cały czas tu lista:

ArrayList lista = new ArrayList();

lista.Add(1);

tu błedy:

Error	2 '_.Form1.lista' is a 'field' but is used like a 'type'

Error	1 Invalid token '(' in class, struct, or interface member declaration

Próbowałem wrzucić jakąś gotową listę, ale cały czas te błędy, przeglądałem na szybko jakieś kursy i posługiwanie się kolekcjami nie wydawało się trudne i robię je tak jak pokazywali, ale i tak mam cały czas te błedy ;/ pojawiają się one w 2 kroku czyli:

lista.Add(); // już nie wiem jak to ogarnąć ;/

Z tego co wyrzuca kompilator wygląda jakbyś dodawał te zmienne poza obszarem klasy. Wrzuć nieco więcej kodu na razie trudno coś wysnuć.

To co opisał kolega @ Frankfurterium , jest całkiem poprawne. Zakładając że robisz to WinForms to metodzie Initialize gdzie tworzysz te PictureBoxy powinieneś je dodać do listy. Dodatkowo powinieneś użyć Listy generycznej tak jak pokazał to @ Frankfurterium z nie ArrayList.

ArrayList użyłem jedynie do testów czy ogólnie jakakolwiek lista mi zadziała:

więcej kodu:

namespace _

{


    public partial class Form1 : Form

    {

        public Form1()

        {

            InitializeComponent();

        }

            string zm;

            string wchih;

            int num;


            public List ls = new List();

            ls.Add();



        private void toolStripMenuItem1_Click(object sender, EventArgs e)

        {


        }

Może nie w tym miejscu tworzę listę ?

Co bym nie wpisał w .add(); pojawiają się kolejne błędy ;/

P S

A gdy chce dodać do listy pixtureboxa, którego stworzyłem sobie do .add() wpisać jego name ? czyli .add(box1); ?

trzeba będzie kiedyś przysiąść nad tym językiem bo niby podstawy, które mam w szkole ogarniam(niedawno zaczeliśmy), ale to co sobie wymyślę i bez problemu zrobiłbym w PHP/JS tu już nie daje rady :smiley:

Wpisać obiekt czyli nazwę zmiennej

PictureBox box1 = new PictureBox();

ls.add(box1);

A z racji że te pictureBoxy tworzysz w metodzie InitializeComponent to tam najlepiej będzie wykonać operację uzupełnienia listy PictureBox’ów.

public partial class Form1 : Form

    {

        public Form1()

        {

            InitializeComponent();

        }

            string zm;

            string wchih;

            int num;


            public List ls = new List();

            PictureBox box1 = new PictureBox();

            ls.Add(box1);



        private void toolStripMenuItem1_Click(object sender, EventArgs e)

        {


        }


        private void nowyToolStripMenuItem_Click(object sender, EventArgs e)

        {


        }


        private void Form1_Load(object sender, EventArgs e)

        {


        }

error:

Error	4	'_.Form1.box1' is a 'field' but is used like a 'type'	C:\Users\Jacek\Desktop\+\+\Form1.cs	25	20	+

Error	3	'_.Form1.ls' is a 'field' but is used like a 'type'	C:\Users\Jacek\Desktop\+\+\Form1.cs	25	13	+

Error	2	Invalid token ')' in class, struct, or interface member declaration	C:\Users\Jacek\Desktop\+\+\Form1.cs	25	24	+

Error	1	Invalid token '(' in class, struct, or interface member declaration	C:\Users\Jacek\Desktop\+\+\Form1.cs	25	19	+

Nie wiem co jest nie tak z tym :d

Piszesz instrukcje wewnątrz klasy.

public partial class Form1 : Form

    {

        public Form1()

        {

            InitializeComponent();

            CreatePictureBoxes();

        }

            string zm;

            string wchih;

            int num;


            public List ls = new List();

public void CreatePictureBoxes(){

            PictureBox box1 = new PictureBox();

            ls.Add(box1);

}



        private void toolStripMenuItem1_Click(object sender, EventArgs e)

        {


        }


        private void nowyToolStripMenuItem_Click(object sender, EventArgs e)

        {


        }


        private void Form1_Load(object sender, EventArgs e)

        {


        }

Z palca ale powinno działać.

A wyjaśnisz mi jeszcze tylko dlaczego potrzeba jest do tego klasa :>

jacek21 , wstawiasz instrukcje kodu poza metodami, a tak robić nie wolno.

Tak czy siak, wszystkie kontrolki formularza znajdują się już w kolekcji o nazwie Controls (ta nazwa pewno dla zmyły), więc nie ma sensu robienie kolejnej. Kod jest banalny:

string boxNr = this.textBox1.Text;


var box = this.Controls.OfType() 

    .Single(pb => pb.Name == "pictureBox" + boxNr); 


box.Location = new Point(box.Location.X, box.Location.Y - 10);

Wersja z pętlą zamiast LINQ:

string boxNr = this.textBox1.Text;


foreach (var control in Controls)

{

    var box = control as PictureBox;

    if (box != null && box.Name == "pictureBox" + boxNr)

    {

        box.Location = new Point(box.Location.X, box.Location.Y - 10);

    }

}

o matko nie zauważyłem, że to funkcja xD

somekind twj sposób wygląda interesująco, ale za mało z niego rozumiem ;/

a poza tym włącza się debuger(z ciekawości sprawdziłem)

dobra, ale wróćmy, mam tą funkcję, wywoływana jest na starcie i teraz w instrukcji przycisku chce jej użyć a tu ■■■■ :d

ls[0].Location = new Point(ls[0].Location.X, ls[0].Location.Y - 10);

zero błędów, debugger też się nie odzywa, nic się nie dzieje po kliknięciu w buttona.

Ehh nawet nie wiem w jaki sposób w c# najlepiej sprawdzać sobie kod, co się dzieje :smiley:

Dodaj breakpointy do kodu i przechodzą krok po kroku (F10, F11) możesz patrzyć co się wykonuje. Również możesz skorzystać z IntelliTrace ale chyba za wcześnie dla Ciebie z tym tematem.

Jeśli dałeś taki kod jak ja Ci podałem to masz pictureBox jako obiekt ale nie masz go dodanego do kontrolek okna. Wrzuć kod jaki masz teraz plus kod metody InitializeComponent.

Zakładam że używasz Visual Studio, Jeśli nie to część informacji może nie być przydatna, więc uściślij z jakiego IDE korzystasz.

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;

namespace _

{


    public partial class Form1 : Form

    {

        public Form1()

        {

            InitializeComponent();

            box();

        }

            string zm;

            int which;

            public List ls = new List();


        private void toolStripMenuItem1_Click(object sender, EventArgs e)

        {


        }


        private void nowyToolStripMenuItem_Click(object sender, EventArgs e)

        {


        }


        private void Form1_Load(object sender, EventArgs e)

        {


        }


        private void openToolStripMenuItem_Click(object sender, EventArgs e)

        {

            text1.Text = "open";

        }


        private void wytnijToolStripMenuItem_Click(object sender, EventArgs e)

        {

            zm = text1.Text;

            text1.Text = "";

        }


        private void wklejToolStripMenuItem_Click(object sender, EventArgs e)

        {

            text2.Text = zm;

        }


        private void kopiujToolStripMenuItem_Click(object sender, EventArgs e)

        {

            zm = text1.Text;

        }


        private void exitToolStripMenuItem_Click(object sender, EventArgs e)

        {

            Application.Exit() ;

        }


        private void czyscFormularzToolStripMenuItem_Click(object sender, EventArgs e)

        {

            text1.Text = "";

            text2.Text = "";

        }


        private void pOMOCToolStripMenuItem_Click(object sender, EventArgs e)

        {

            MessageBox.Show(" http://google.pl");

        }


        private void pictureBox1_Click(object sender, EventArgs e)

        {


        }


        private void pictureBox6_Click(object sender, EventArgs e)

        {


        }


        private void textbox_TextChanged(object sender, EventArgs e)

        {

            which = Convert.ToInt16(textbox.Text);


        }

        public void box() {

            PictureBox box1 = new PictureBox();

            PictureBox box2 = new PictureBox();

            PictureBox box3 = new PictureBox();

            PictureBox box4 = new PictureBox();

            ls.Add(box1);

            ls.Add(box2);

            ls.Add(box3);

            ls.Add(box4);

        }


        private void button2_Click(object sender, EventArgs e)

        {

            ls[0].Location = new Point(ls[0].Location.X, ls[0].Location.Y - 10);


        }

    }

}

tak to jest Visual, cały kod… też ciekawi mnie jedno dlaczego po dodaniu listy i funkcji Box(), zginęło mi menu, skoro nie ingerowałem w kod odpowiedzialny za menu ?

To co podałeś jest częścią kodu. Klasa Form1 jest zawarta w więcej niż jednym pliku ponieważ masz tam słowo kluczowe partial. Zakładając że użyłeś designera do ustawienia elementów w oknie visual wygenerował metodę InitializeComponent(). Najprościej żeby zobaczyć jak ona wygląda kliknij kursorem w tą nazwę a następnie wciśnij F12. W tamtej metodzie masz utworzone wszystkie obiekty kontrolek i dodane do formatki.

Twoje pictureboxy są utworzone ale nie dodałeś ich do formatki ani nie podałeś żadnych konkretnych właściwości. Zobacz jak wygląda metoda InitializeComponent i jak wspomniałem jak chcesz użyć kolekcji pictureboxów to w tamtej metodzie powinieneś je wrzucić do listy.

Widać, że z c# spotykałeś się nie raz, ale ja jestem początkującym i nie za bardzo radze sobie z Twoimi radami, wszedłem do From1.Disagner i jedyne co zobaczyłem to to iż są tam zamieszczone wszystkie elementy, które dodawałem, ale nie jak mi to mówi jak mam sobie poradzić z PictureBox’ami oraz dlaczego nagle ni stąd ni zowąd znikło moje ubogie menu.

Chyba jednak zrobię to naokoło i dodam te 12 linii kodu więcej bo ja na razie stoję w miejscu.

Już mam dosyć tego języka, miałem pomysł na fajną klasę w php’ie a tu nawet edytora nie zdążyłem otworzyć a weekend mi się skończył…

Nie rozumiesz pętli, operatora as i ifa z drugiego kodu, czy tej magii z pierwszego?

A w swoim kodzie, nie dodajesz tworzonych przez siebie PictureBoxów do kolekcji Controls, więc nie wyświetlają się one na formularzu. Podobnie nie ustawiasz im wymiarów ani pozycji startowej…

Naprawdę, mój kod jest prostszy.

Do pliku designer nie masz po co zaglądać. A języka masz dość, bo go nie znasz, i nawet nie spróbowałeś się zacząć jego uczyć.

Na poważnie fakt nie zacząłem się go uczyć, już na początku odrzuciła mnie sama praca na typach ciągłe konwersje, nie jest to język, który przypadłby mi do gustu od pierwszej linii kodu, choć wiem jakie duże możliwości daje, lubię pracować z PHP/JS i chciałbym większość swojego czasu poświęcić tym językom.

A co do ogólnej nauki c# idąc tokiem szkolnym radzę sobie bardzo dobrze wbrew pozorom :stuck_out_tongue:

czego nie rozumiem hmm nie wiem czemu wskazujesz na Controls(this.Controls) co robi ten kawałek:(.Single(pb => pb.Name) tzn co robi to widać, ale do czego jest single.

Mimo wszystko dziękuje za pomoc, spróbuję jeszcze Twojego sposobu pomęczę się bo mam chwilkę :slight_smile:

@jacek21

Nie możesz zaczynać nauki języka od poukładania kontrolek na ekranie. To po prostu nie ma najmniejszego sensu. Od JavaScriptu do C# droga już krótka. Z tego też względu nie wypada Tobie chełpić się znajomością JS. [-X

Zacznij od podstaw, a efekty pojawią się same.