Pořadí v Listu podle polohy   zodpovězená otázka

VB.NET, Komponenty, Grafika

Zdravím,

je možné při každé změně pozice komponent přes WndProc, setřídit pořadí komponenty v Listu podle pozice Y?

Díky.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Proč proboha přes WndProc? Jak přesně ty komponenty pozicujete?

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Proč přes WndProc: Četl jsem to v návodu pana Liharta.

Jak je pozicuji: Kamkoliv chce uživatel, pokud to myslíte takto.

Jde mi o to, pokud uživatel komponenty zamíchá, nebudou se data nahrávat postupně, tedy ano, ale ne "uživatelsky".

nahlásit spamnahlásit spam -1 / 1 odpovědětodpovědět

To by mě zajímalo ve kterém...

nahlásit spamnahlásit spam 0 odpovědětodpovědět

http://www.vbnet.cz/snippet--51-vlastni_...

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

To je pouze demonstrace toho, jak lze přesouvat formulář bez použití titulkového pruhu, nikoliv návod na to, jak přesouvat komponenty uvnitř něj. Nepochopil jste smysl článku a snažíte se používat něco takovým způsobem, na který to nebylo navrženo.

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Hmm, ale s DirectCast to funguje naprosto správně... Ale zpět k problému, prosím...

nahlásit spamnahlásit spam -1 / 1 odpovědětodpovědět

Tak znovu: Nepoužívejte věci k něčemu, k čemu nejsou navrženy.

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

A že byste mě třeba nakopl, co použít, nebo odkázal na návod, aby to řešilo tento, i můj hlavní problém?

nahlásit spamnahlásit spam -1 / 1 odpovědětodpovědět

Použít událost LocationChanged k detekci změny souřadnice Y...

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

A čím mám nahradit WndProc?

nahlásit spamnahlásit spam -1 / 1 odpovědětodpovědět

WndProc proboha nepoužívejte, to se dělá jen ve velmi specifických případech.

Radši si pohrajte s událostmi MouseDown, MouseMove a MouseUp na těch komponentách, které chcete umožnit přesouvat. Podle e.Button si zjistěte, kterým tlačítkem myši uživatel akci udělal, a podle toho kompomenty přesouvejte.

Doporučuji události navázat na komponenty dynamicky pomocí příkazu AddHandler ve VB.NET či operátoru += v C# a ne natvrdo, to by se velmi špatně spravovalo při přidávání nových komponent na formulář.

ListBox má tuším nějakou metodu Sort, která položky setřídí. Implementuje na objekty, které v listboxu máte, rozhraní IComparable podle souřadnice Y, aby Sort věděl, podle čeho má objekty třídit.

Pokud chcete nějaký z těch kroků rozepsat podrobněji, napište.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Vyřešeno přesouvání:

        If Clicked = True Then
            DirectCast(sender, Object).Top = DirectCast(sender, Object).Top + (MousePosition.Y - Y)
            DirectCast(sender, Object).Left = DirectCast(sender, Object).Left + (MousePosition.X - X)
            X = MousePosition.X
            Y = MousePosition.Y
        End If

nahlásit spamnahlásit spam -1 / 1 odpovědětodpovědět

Nechápete, k čemu slouží DirectCast. Proměnná sender označuje komponentu, která událost vyvolala, a je typu Object, kdežto vy používáte vlastnosti Top, Left atd., které definuje až typ Control.

DirectCast slouží k tomu, abyste sender přetypoval na Control (přetypovat jde jen když cílová třída Control dědí ze třídy reprezentované typem proměnné, tedy Object, a skutečný objekt, který v proměnné je, musí být samozřejmě cílového typu nebo z něj dědit; vše v .NETu dědí z Object a z logiky věci sender bude komponenta, která událost vyvolala, tedy Control; takže v tom není problém), ale vy ho přetypováváte znovu na Object, což je zbytečné. Funguje to jen díky prasárně VB, který umožňuje na Objectu zavolat cokoliv a pokud to objekt neumí, pak vznikne výjimka až za běhu. Je to pomalé a navíc potenciální příčina chyb a pádů aplikace za běhu.

Změňte DirectCast(sender, Object) na DirectCast(sender, Control), ať se tím problém spraví.

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Ještě mám poslední dotaz - Jak pomocí té metody Sort v Listu (Ne ListBoxu) ty komponenty setřídit pomocí té pozice Y? Se Sort neumím.

nahlásit spamnahlásit spam -1 / 1 odpovědětodpovědět

Pokud nechápete takové základní a triviální věci jako DirectCast, nemá cenu vám vysvětlovat implementaci a použití ICompareru. Začínejte vždy jednoduchými věcmi, které jste schopen zvládnout sám.

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

DirectCast chápu, jen jsem nevěděl, že mám Object nahradit Control, dosud jsem používal typ komponenty... Nevím, proč byste mi neměl vysvětlit IComparer...

nahlásit spamnahlásit spam -1 / 1 odpovědětodpovědět

Žádný typ komponenty jste nepoužíval, přetypovával jste Object na Object a to ještě zbytečně 2x což svědčí leda o tom, že absolutně nevíte která bije. Pokud si tak věříte, prostudujte si IComparer na MSDN (kde jsou i příklady) a vsadím se, že nepochopíte ani 1/100.

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Nemyslíte, že už to trochu přeháníte? Pokud sem chcete psát tyhle blitky, tak raději neodpovídejte vůbec.

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

To nejsou blitky ale bohužel reálné věci. Napíšu-li použijte metodu Compare tak, že implementujete rozhraní IComparable na vlastní třídící třídu a předejte její instanci této metodě, další idiotský dotaz bude jak implementovat IComparable a jak použít metodu Sort u Listu? Zkuste to. Takto to dopadá když se snaží programovat děti, které v životě nenapsali ani řádku.

nahlásit spamnahlásit spam 0 / 2 odpovědětodpovědět

Škoda s vámi mluvit...

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Ano, ale tím, že budete začátečníkům nadávat, se to nespraví. Fórum je o tom, že dokola a dokola vysvětlujete pro nás jasné věci a odkazujete na existující články. Pokud to chcete dělat jinak (nadávat), tak ne prosím tady.

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Myslete si co chcete, ale tohle téma není na hádky a flame. TAKŽE MĚ ZDE NEKRITIZUJTE!!

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Jak plníte ten ListBox?

nahlásit spamnahlásit spam 0 odpovědětodpovědět

ListBox neplním, plním list, ve kterém mám různé komponenty, jako labely atd. Přidávám je kódem:

muj_list.Add(nazev_komponenty)
Me.Controls.Add(nazev_komponenty)

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Seznam List má metodu Sort, která jako parametr bere objekt implementující rozhraní IComparer, což je nástroj, který definuje, jakým způsobem se bude porovnávat.

Takže vytvořte třídu třeba ControlsComparer, která bude vypadat zhruba takto:

Public Class ControlsComparer 
    Implements IComparer(Of Control)

    Public Function Compare(ByVal x As Control, ByVal y As Control) As Integer _
        Implements IComparer(Of Control).Compare
        Return x.Top.CompareTo(y.Top)
    End Function

End Class

Pro setřídění stačí zavolat

muj_list.Sort(new ControlsComparer())

Komparátor obsahuje metodu Compare, která vrátí 1, 0 nebo -1 podle toho, jestli je první objekt větší, roven či menší než druhý objekt. Protože porovnáváme komponenty, ale x a y jsou typu Object, přetypujeme si oba parametry na Control, abychom na nich viděli vlastnost Top.

To, jestli je komponenta větší než druhá zjistíme zavoláním metody CompareTo na typu Integer, která dělá to samé - vrací -1, 0 nebo 1.

Sort pak tenhle komparátor použije pro určení, která komponenta má být v seznamu před kterou.

Stačí to takhle?

nahlásit spamnahlásit spam 0 odpovědětodpovědět

VB mi hlásí 2 chyby v Implements:

Class 'ControlsComparer' must implement 'Function Compare(x As Object, y As Object) As Integer' for interface 'System.Collections.IComparer'.

'Compare' cannot implement 'Compare' because there is no matching function on interface 'System.Collections.IComparer'.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Jo pardon, psal jsem to z hlavy. Proměnné x a y v hlavičce funkce jsou typu Control, mají být typu Object.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

A teď při spuštění aplikace vyhodí hlášku u vyvolání přes Sort

Unable to cast object of type 'WindowsApplication1.ControlsComparer' to type 'System.Collections.Generic.IComparer`1[System.Windows.Forms.Control]'.

:(

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Opravil jsem to v kódu v předchozím příspěvku, List evidentně vyžaduje generický komparátor a ne obecný.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Ach jo, to je záludnost... Opět 2 errory...

'System.Collections.IComparer' has no type parameters and so cannot have type arguments.

Class 'ControlsComparer' must implement 'Function Compare(x As Windows.Forms.Control, y As Windows.Forms.Control) As Integer' for interface 'System.Collections.Generic.IComparer(Of System.Windows.Forms.Control)'.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Tak trochu zkoušejte, zkuste si tu chybovou hlášku třeba přeložit a vyčíst, o co jde. Já to píšu z hlavy, nechce se mi pouštět nové Visual Studio a zkoušet to.

Stačí v řádku Implements správný název třídy a metody, ten IComparer(Of Control) je v jiném namespace.

Opravil jsem to v ukázce, ale zkuste se taky trochu snažit sám.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Díky mnohokrát :)

nahlásit spamnahlásit spam 0 odpovědětodpovědět
                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.
  • Administrátoři si vyhrazují právo komentáře upravovat či mazat bez udání důvodu.
    Mazány budou zejména komentáře obsahující vulgarity nebo porušující pravidla publikování.
  • Pokud nejste zaregistrováni, Vaše IP adresa bude zveřejněna. Pokud s tímto nesouhlasíte, příspěvek neodesílejte.

přihlásit pomocí externího účtu

přihlásit pomocí jména a hesla

Uživatel:
Heslo:

zapomenuté heslo

 

založit nový uživatelský účet

zaregistrujte se

 
zavřít

Nahlásit spam

Opravdu chcete tento příspěvek nahlásit pro porušování pravidel fóra?

Nahlásit Zrušit

Chyba

zavřít

feedback