Użycie Lablea przez klasę w WinForms

Użycie Lablea przez klasę w WinForms
RA
  • Rejestracja:ponad 9 lat
  • Ostatnio:2 miesiące
  • Lokalizacja:Poznań
  • Postów:48
0

Cześć

Mam podstawowy projekt w Windows Forms

Kopiuj
public partial class MainForm : Form
{
...
}

MainForm zawiera jakieś tam Labele. Wszystkie są ustawione jako public.
Do tego mam klasę - dajmy na to T1 - w osobnym pliku i chciałbym, aby ona korzystała z tych Labeli.
Zauważytłem, że jeżeli tworzę obiekt klasy T1 bezpośrednio w:

Kopiuj
MainForm : Form

to ona tych Labeli nie widzi, widzi je, gdy utworzę obiekt w:

Kopiuj
public MainForm()

ale wtedy, aby metoda klasy T1 korzystała z Labela musi go mieć przekazanego jako argument (a to nie będzie jeden Label tylko więcej). I to każda metoda osobno, nawet przekazanie jako argument konstruktora nie pomaga.
Jest jakiś sposób na to czy może powinienem tworzyć obiekty w

Kopiuj
public MainForm()

?
Klasa T1 nie jest pochodną MainForm.

Sorry za formatowanie, ale nie ogarniam tego i proszę mi nie tłumaczyć, że T1 i MainForm to są osobne klasy, bo tyle to wiem.


Samouk. Początkujący. C++, C#.NET.
RA
  • Rejestracja:ponad 9 lat
  • Ostatnio:2 miesiące
  • Lokalizacja:Poznań
  • Postów:48
0

Kurde, chyba sam ogarnąłem 😄
KLasa T1 była zadeklarowana jako partial class T1. Dodałem public i chyba działa.


Samouk. Początkujący. C++, C#.NET.
RA
  • Rejestracja:ponad 9 lat
  • Ostatnio:2 miesiące
  • Lokalizacja:Poznań
  • Postów:48
0

Albo może i nie?


Samouk. Początkujący. C++, C#.NET.
AdamWox
  • Rejestracja:ponad 7 lat
  • Ostatnio:około godziny
  • Lokalizacja:Jastrzębie-Zdrój
  • Postów:2161
1

Przekaż całe MainForm do T1, będziesz miał dostęp do wszystkich publicznych pól i zmiennych

Kopiuj
public class T1
{
  Form _frm;
  public T1(Form frm)
  {
    _frm = frm;
  }
}

a w MainForm

Kopiuj
T1 t1 = new T1(this);
RA
OK, dzięki. Zaraz sprawdzam.
RA
  • Rejestracja:ponad 9 lat
  • Ostatnio:2 miesiące
  • Lokalizacja:Poznań
  • Postów:48
0

Działa, ale musiałem dać:

Kopiuj
MainForm _frm i
public T1(MainForm frm)

I przy okazji rozwiązała się druga kwestia. Muszę tworzyć obiekt T1 w public MainForm(), bo inaczej się nie kompiluje.


Samouk. Początkujący. C++, C#.NET.
edytowany 4x, ostatnio: Radziu
AdamWox
  • Rejestracja:ponad 7 lat
  • Ostatnio:około godziny
  • Lokalizacja:Jastrzębie-Zdrój
  • Postów:2161
0

Nie musisz tworzyć obiektu T1 w MainForm(). Tworzysz obiekt T1 tam gdzie jest ci on potrzebny. Pokaż, gdzie stworzyłeś obiekt T1? I dlaczego "nie działa" Form frm skoro MainForm dziedziczy po Form?

PS.
Mam wrażenie, że nie rozumiesz co robisz, a już tym bardziej nie znasz struktury projektu WinForms. Nie wiem jaki jest cel przekazywania całego okna do innej klasy, nie wiem jaki jest cel mieć dostęp do labelek z głownego okna. Dobrze by było opisać problem, bo może (a nawet na pewno) podchodzisz to swojego problemu źle 🤔

somekind
Moderator
  • Rejestracja:około 17 lat
  • Ostatnio:około 8 godzin
  • Lokalizacja:Wrocław
1

Zgaduję, że chodzi o przeniesienie jakiejś logiki z klasy formularza na zewnątrz, co jest słuszną ideą. Niemniej jednak, zamiast wiązać na sztywno te klasy ze sobą, lepiej zastosować wzorzec MVP (Model-View-Presenter), który w skrócie działa tak, że Presenter operuje (wysyła i odbiera dane) do View, który jest implementowany przez Form.
Dzięki temu mamy kod, który: oddziela logikę od zarządzania GUI, jest testowalny i pomijamy dziwne problemy typu konstruktor formularza zaczyna się nam łączyć z bazą, i designer się wywala.

AdamWox
I ty serio myślisz, że OP zrozumie co do niego napisałeś? 😅
somekind
Nie wiem, ale zawsze może wybingować słowa kluczowe, albo tutaj dopytać.
RA
Takiego czegoś jak Model-View-Presenter to ja jeszcze nie ogarniam. Oczywiście zrozumiałe jest, że odzdzielenie logiki od GUI to jest to o co nam chodzi, ale ja do tej pory większość pisałem w konsoli i programować coś tam umiem, ale w GUI to dopiero raczkuję, więc takie rzeczy na razie nie dla mnie.
RA
  • Rejestracja:ponad 9 lat
  • Ostatnio:2 miesiące
  • Lokalizacja:Poznań
  • Postów:48
0
AdamWox napisał(a):

Nie musisz tworzyć obiektu T1 w MainForm(). Tworzysz obiekt T1 tam gdzie jest ci on potrzebny. Pokaż, gdzie stworzyłeś obiekt T1? I dlaczego "nie działa" Form frm skoro MainForm dziedziczy po Form?

PS.
Mam wrażenie, że nie rozumiesz co robisz, a już tym bardziej nie znasz struktury projektu WinForms. Nie wiem jaki jest cel przekazywania całego okna do innej klasy, nie wiem jaki jest cel mieć dostęp do labelek z głownego okna. Dobrze by było opisać problem, bo może (a nawet na pewno) podchodzisz to swojego problemu źle 🤔

Rozumiem co robię, ale rzeczywiście - struktury projektu WinForms nie znam. Dopiero poznaję.
Jak wpisałem jak podałeś Form _frm to mam 'Form' does not contain a definition for 'lbl1' and no accessible extension method 'lbl1' accepting a first argument of type 'Form' could be found (are you missing a using directive or an assembly reference?) i też mnie to zastanawia czemu, skoro MainForm dziedziczy po Form. W tej chwili wpisanie MainForm załatwiło sprawę i mnie to zadowala.
I teraz mam klasy T1 i P1 w osobnych plikach (nie dziedziczą po MainForm) i coś takiego:

Kopiuj
   {
       List<int> STable = new List<int>();
       List<P1> P1s = new List<P1>();
...
}

W konstruktorze T1 mam te dwie listy oraz Form a właściwie MainForm przekazane przez this jak podałeś (wcześniej nie miałem).
Teraz jeżeli piszę:

Kopiuj
public partial class MainForm : Form
{
  P1 p1 = new P1();
  P1 p2 = new P1();
  List<int> STable = new List<int>();
  List<P1> P1s = new List<P1>();

  //T1 t1 = new T1(ref P1s, ref STable, this);

  public MainForm()
        {
            InitializeComponent();
            GoFullscreen(false);
 
            T1 t2 = new T1(ref P1s, ref STable, this);
      }
}

to działa, mogę też dodać kolejny obiekt T1 t3 w MainForm_Load(object sender, EventArgs e), ale jak odkumentuję T1 t1 to mam:
A field initializer cannot reference the non-static field, method or property 'MainForm.P1s' , to samo dla STable a chcę mieć referencje, bo nie będę za każdym razem kopii robił. T1 ma modyfikować pola obiektów P1 w P1s (są zawarte odpowiednie metody) i cyferki w STable oraz Keyword 'this' is not available in the current context. A jeszcze dodam, że ja przerabiam projekt, który jakiś czas temu napisałem w C++ w konsoli i tam działał, tylko, że to wszystko mało przejrzyste było, wszystko w linijkach na czarnym ekranie wypisywać. Teraz próbuję to przerobić na fajny projekt z GUI, ale bezboleśnie to póki co nie przechodzi :)


Samouk. Początkujący. C++, C#.NET.
edytowany 5x, ostatnio: Radziu
RA
Dodam jeszcze, że to nie jest mój pierwszy projekt w WinForms. Zrobiłem parę małych pier***ek, nawet grę w Black Jacka, możesz wierzyć albo nie, ale działa, z tym, że tylko na 1 playera. I nie ma jeszcze wszystkich opcji z prawdziwej gry.
Azarien
  • Rejestracja:ponad 21 lat
  • Ostatnio:3 minuty
2

Do tego mam klasę - dajmy na to T1 - w osobnym pliku i chciałbym, aby ona korzystała z tych Labeli.

Nie idź tą drogą. Zdefiniuj metodę w MainForm która robi na labelach to co powinna. Z drugiej klasy wywołuj tę metodę.

RA
Próbowałem czegoś takiego, ale coś źle robiłe, bo mi kompilator wywalał, że klasa T1 nie zna takiej metody. No o zasięg widoczności chodziło. Nie widzi żadnych metod z MainForm, mimo tego, że są public, nie ma ich na liście IntelliSense :/
Azarien
pewnie się odwołujesz do klasy a nie do obiektu (instancji klasy)
RA
No widzisz proste odpowiedzi są najprostsze :) próbowałem się odwoływać bezpośrednio do metody (pewnie dlatego, że w c++ to działało). Dodanie przed kropką _frm (czyli instancji klasy) rozwiązało problem :) :) . Teraz jak wiem jak to zrobić będę to lubił o wiele bardziej.
RA
Ale w projekcie konsolowym c++ taka globalna funkcja nie należała do żadnej klasy a tu należy do MainForm :O i logiczne, że trzeba się do niej odnieść poprzez obiekt typu MainForm. U mnie teraz pole _frm w klasie T1 i obiekt klasy T1 może sobie wywoływać _frm.metoda()
RA
  • Rejestracja:ponad 9 lat
  • Ostatnio:2 miesiące
  • Lokalizacja:Poznań
  • Postów:48
0

No i co, wszyscy ucichli?


Samouk. Początkujący. C++, C#.NET.
somekind
Ale co tu jeszcze dodać? Jest jakieś nowe pytanie?
RA
No jest. AdamWox napisał: "Nie musisz tworzyć obiektu T1 w MainForm(). Tworzysz obiekt T1 tam gdzie jest ci on potrzebny." i ja mu dwa posty niżej odpisałem, dlaczego nie wszędzie mogę i dlaczego nie działa Form _frm, ale MainForm _frm działa.
somekind
Moderator
  • Rejestracja:około 17 lat
  • Ostatnio:około 8 godzin
  • Lokalizacja:Wrocław
2
Radziu napisał(a):

Jak wpisałem jak podałeś Form _frm to mam 'Form' does not contain a definition for 'lbl1' and no accessible extension method 'lbl1' accepting a first argument of type 'Form' could be found (are you missing a using directive or an assembly reference?) i też mnie to zastanawia czemu, skoro MainForm dziedziczy po Form. W tej chwili wpisanie MainForm załatwiło sprawę i mnie to zadowala.

Oczywistym jest, że pole jest zdefiniowane w tej klasie, w której jest, a nie w bazowej. Rodzic nie ma skąd (ani po co) wiedzieć o polach swoich dzieci. MainForm dziedziczy z Form i dodaje swoje pola, więc taki np. lbl1 jest w MainForm, a nie w Form.
Obstawiam, że @AdamWox po prostu skrót myślowy zastosował pisząc o Form.

jak odkumentuję T1 t1 to mam:
A field initializer cannot reference the non-static field, method or property 'MainForm.P1s'

No tak, to prawda. Nie możesz inicjalizując pole odwoływać się do innych niestatycznych pól.
Możesz sobie zadeklarować pole w klasie, i zainicjalizować je w konstruktorze, o tak:

Kopiuj
public partial class MainForm : Form
{
    P1 p1 = new P1();
    P1 p2 = new P1();
    List<int> STable = new List<int>();
    List<P1> P1s = new List<P1>();

    T1 t1;

    public MainForm()
    {
        InitializeComponent();
        GoFullscreen(false);

        this.t1 = new T1(P1s, STable, this);
    }
}

Bez ref, bo są zbędne.

edytowany 1x, ostatnio: somekind
RA
  • Rejestracja:ponad 9 lat
  • Ostatnio:2 miesiące
  • Lokalizacja:Poznań
  • Postów:48
0

No właśnie. I dlatego ja sobie wpisywałem MainForm _frm i mi to w niczym nie przeszkadzało. Jeśli chodzi o refy to gdzieś w książce wyczytałem, że obiekty klas tworzonych przez użytkownika i tak są zawsze typu referencyjnego a to, że mam je w wielu miejscach wynika z tego, że przepisuję ten projekt z c++ i ref pojawił się tam gdzie był &, ale rozumiem, że mogę tego się spokojnie pozbyć.
Co się tyczy pól niestatycznych - póki co tworzę obiekty zawsze w jakiejś metodzie i jest dobrze. Takiego czegoś jak tu podałeś z odwołaniem poprzez this nie znałem. Będzie okazja wypróbować. Dzięki za pomoc.


Samouk. Początkujący. C++, C#.NET.
obscurity
tak możesz się spokojnie pozbyć. ref jest odpowiednikiem wskaźnika na wskaźnik i pozwala na podmienienie referencji z wewnątrz funkcji
Azarien
  • Rejestracja:ponad 21 lat
  • Ostatnio:3 minuty
1

obiekty klas tworzonych przez użytkownika i tak są zawsze typu referencyjnego

Nie ma takiej zasady. W C# są "reference types" i są "value types". Do pierwszych należą klasy (typy zdefiniowane za pomocą słowa class), do drugich struktury (zdefiniowane słowem struct).

obscurity
mi się zdaje czy napisałeś to samo z czym się nie zgodziłeś innymi słowami "obiekty klas są zawsze typu referencyjnego" vs "Do reference types należą klasy"
RA
No właśnie. Ja w zasadzie nie korzytsam ze struktrur, zawsze tworzę klasę a te są zawsze typu referencyjnego, right?
Azarien
@obscurity: chodzi o to że nie ma znaczenia czy klasa jest "tworzona przez użytkownika". ma znaczenie czy jest to typ class czy struct.
somekind
struct nie jest klasą.
somekind
Moderator
  • Rejestracja:około 17 lat
  • Ostatnio:około 8 godzin
  • Lokalizacja:Wrocław
1
Radziu napisał(a):

No właśnie. I dlatego ja sobie wpisywałem MainForm _frm i mi to w niczym nie przeszkadzało. Jeśli chodzi o refy to gdzieś w książce wyczytałem, że obiekty klas tworzonych przez użytkownika i tak są zawsze typu referencyjnego a to, że mam je w wielu miejscach wynika z tego, że przepisuję ten projekt z c++ i ref pojawił się tam gdzie był &, ale rozumiem, że mogę tego się spokojnie pozbyć.

Jak najbardziej.

Co się tyczy pól niestatycznych - póki co tworzę obiekty zawsze w jakiejś metodzie i jest dobrze. Takiego czegoś jak tu podałeś z odwołaniem poprzez this nie znałem. Będzie okazja wypróbować. Dzięki za pomoc.

this podkreśla, że odwołujesz się do elementu klasy. Równie dobrze możesz to słówko pominąć, bo w tym kontekście jasne jest, o które t1 chodzi. (Bo jest tylko jedno. ;))

RA
  • Rejestracja:ponad 9 lat
  • Ostatnio:2 miesiące
  • Lokalizacja:Poznań
  • Postów:48
0

@somekind po Twoim poście i napisałem coś takiego:

Kopiuj
public partial class MainForm : Form
{
    P1 p1 = new P1();
    P1 p2 = new P1();
    List<int> STable = new List<int>();
    List<P1> P1s = new List<P1>();

    T1 t1;

    public MainForm()
    {
        InitializeComponent();
        GoFullscreen(false);

        this.t1 = new T1(P1s, STable, this);
        T1 t2 = new T1(P1s, STable, this);
        
    }
}

Teraz dowolna metoda należąca do MainForm widzi t1, ale nie widzi t2. Tak się zastanawiam dlaczego, przecież t2 zostało utworzone w konstruktorze, czy to nie jest konstruktor?


Samouk. Początkujący. C++, C#.NET.
edytowany 1x, ostatnio: Radziu
AD
  • Rejestracja:ponad rok
  • Ostatnio:6 dni
  • Postów:50
2
Radziu napisał(a):

@somekind po Twoim poście i napisałem coś takiego:

Kopiuj
public partial class MainForm : Form
{
    P1 p1 = new P1();
    P1 p2 = new P1();
    List<int> STable = new List<int>();
    List<P1> P1s = new List<P1>();

    T1 t1;

    public MainForm()
    {
        InitializeComponent();
        GoFullscreen(false);

        this.t1 = new T1(P1s, STable, this);
        T1 t2 = new T1(P1s, STable, this);
        
    }
}

Teraz dowolna metoda należąca do MainForm widzi t1, ale nie widzi t2. Tak się zastanawiam dlaczego, przecież t2 zostało utworzone w konstruktorze, czy to nie jest konstruktor?

Nie widzi bo t2 jest zdefiniowane w konstruktorze, a nie w klasie. W momencie zakończenia kodu konstruktora zmienna t2 znika.

RA
Jasna sprawa, myślałem, że zostaje.
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)