Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: VB.NET: Objektien uudelleenpiirtämisestä

Sivun loppuun

sniiki [04.07.2008 09:03:14]

#

Projektissa on itse väsätty sulavasti skrollaava lista jossa paanelin sisään rakennetaan labeleita. Kun listaa skrollataa, liikkuu koko paneeli ja kun paneelin ylä- tai alareuna menee yli tietyn rajan heitetään koko paneelia tekstirivinverran alas ja labeleiden tekstit piirretään uudestaan (siirretään pykälä eteen- tai taaksepäin). Tuloksena siis vaikutelma loputtomasta ja sulavasti skrollaavasta listasta.

Homma pelaa muuten hyvin mutta tuo tekstien uudelleenpiirtäminen aiheuttaa ärsyttävää välkkymistä. Formilla on doublebufferi mutta se ei taida vaikuttaa paneelin sisältöön.

Olisiko jokin keino ajoittaa paneelin siirto ja tekstien piirto TÄSMÄLLEEN samanaikaiseksi, tai jotenkin muuten piirtää paneeli ja sen sisältö kokonaan uudelleen tietyssä vaiheessa ja tällä tavoin estää välkkyminen?

Tossa koodin pätkä jos se nyt mitään selventää.

'ylös
 If Panel1.Top < -2 * labelit(0).Height And nextUP >= 0 And nextUP < (50 - 13) Then
                nextUP += 1
                nextDOWN += 1
                Panel1.Top = -labelit(0).Height
                ' Panel1.Invalidate()

                curmousepos = Cursor.Position.Y
                curpanelpos = Panel1.Top
                For i As Integer = 0 To 13
                    labelit(i).Text = texts(nextUP + i)
                Next

                ' alas
            ElseIf Panel1.Top > -labelit(0).Height And nextUP > 0 And nextDOWN < 50 Then
                nextUP -= 1
                nextDOWN -= 1
                Panel1.Top = -2 * labelit(0).Height
                ' Panel1.Invalidate()

                curmousepos = Cursor.Position.Y
                curpanelpos = Panel1.Top
                For i As Integer = 0 To 13
                    labelit(i).Text = texts(nextUP + i)
                Next

            End If

sniiki [04.07.2008 23:24:45]

#

Tein listan erityylillä vaikeamman kautta; labeleita liikutetaan ja yli reunan mennyt heitetään listan toiseen päähän. Koodia tuli kaiken kaikkiaan 10x enemmän mutta eipähän vilku.

Olisi silti kiva tietää miten tuon alkuperäisen ongelman saisi kierrettyä.

Newb [05.07.2008 00:20:25]

#

Mulla oli samantapainen projekti just muutama päivä sitten, muutaman tunnin koitin sitä ongelmaa ratkasta, mut taitaa olla melko mahdotonta. :E

sniiki [05.07.2008 02:41:14]

#

Sain kyllä toimimaan ihan nätisti :)
18 labelin lista joka skrollailee muutaman tuhannen biisin mp3 listaa. Meni vaan tosiaan melkosen vaikeaksi biisien valinnat ja kappaletekstin piirto tällä tapaa mitä tein.

Tein koko roskan 4:llä eri tavalla kunnes sain toimimaan sulavasti ja suht keveästi.

Periaate siis että label(0) on "referenssipiste" ja siitä lasketaan muiden labelien paikat, heittäen niitä tarpeen tullen paneelin toiseen päähän. Tällä tavoin toi pinkka pysyy kasassa, meinaan jos jokaselle labelille laskee itsenäisesti uuden paikan niin nopeasti scrollatessa pinkka leviää käsiin, varsinkin kun oma listani on semmonen "Apple-tyylinen" eli voi heittää pyörimään.

User137 [05.07.2008 11:08:23]

#

Voit tietysti käyttää jotain kuva komponenttia niiden labeleiden ja paneelin sijaan ja piirtää see lista tekstiä itse. Pääsee ainakin koodissa ja päänsäryssä vähimmälle.

sniiki [05.07.2008 18:16:56]

#

mjoo mietin tuota mutta en sitten jaksanut edes koittaa kun ajattelin ettei ite piirtämällä miksikään muutu.

Tiedä sitten kumpi syö enemmän tehoa, labeleiden liikutus vai panelin liikutus + 18 tekstirivin piirtäminen 10ms välein.

sniiki [07.07.2008 10:43:53]

#

Tuntuu näitä kysymyksiä tulevan, muttakun kaikki sattuu olemaan sellaisia joihin ei vastausta löydy miltään saitilta ja vaikka miten kuuklettelee.

Eli toinen samaan aiheeseen liittyvä kyssäri:

Ohjelmani ulkoasun pitäisi toimia seuraavasti:
-Pääsivulla on ylä- ja alaosassa kontrolleja jotka tulee näkyä aina (alhaalla musasoittimen ohjausnapit ja ylhäällä informaatio-osa).
-Kaikkien painikkeiden tulee olla läpikuultavia ja näyttää siis alla oleva taustakuva läpi.
-Pääikkunaan avataan alasivuja joiden tulee näkyä siis pääsivun kontrollien väliin jäävässä osassa ja olla aina päällimmäisenä, mutta siis samalla pääsivun kontrolleja täytyy pystyä käyttämään.
-Pääsivun kontrolleista täytyy pystyä sulkemaan nämä avatut alasivut
-Pääsivulla näytetään oletuksena painikkeet joista avataan alasivuja

Tällä hetkellä oon toteuttanut homman tekemällä pääsivusta mdi containerin, jossa taustakuva piirretään koko ikkunan kokoiseen paneeliin ja paneelin päälle nämä aina näkyvät yleiskontrollit.
*Tämän koko ikkunan kokoisen paneelin päällä on pienempi paneeli, joka toimii avattavien alasivujen sisällön näyttäjänä.
*Myös kaikilla alasivuilla on koko alasivun kokoinen paneeli, jonka parentiksi asetetaan pääsivun pikkupaneeli.
*Alasivut siis avataan pääsivulle tyyliin

panel2.controls.clear
frmalasivu1.mdiparent = me
frmalasivu1.show
frmalasivu.panel1.parent = me.panel2

Tällä tavoin saan pääsivun taustakuvan (panel1) näkymään myös alasivujen taustakuvana ja läpikuultavuudet toimimaan myös alasivuilla oikein.
Ongelma on vain että kun alasivujen paneeleiden parentiksi asetetaan pääsivun pikkupaneeli, kopioidaan alasivujen objektit aina tähän parent paneeliin ja se aiheuttaa grafiikan hitaan rakentumisen. Eli objektit ilmestyvät hitaasti yksikerrallaan, eikä siis koko ikkuna avaudu kerralla siististi.

Paneelin asettaminen parentiksi vaikeuttaa toimintaa myös muutoin. frm.hide komento esimerkiksi ei siis hävitä avatun alasivun kontrolleja vaan panel2 täytyy aina putsata. Alasivujen sulkeminen niiden omasta koodista ei siis toimi tyyliin me.hide, vaan täytyy aina luoda instanssi pääsivusta ja sen kontrolleista mikä aiheuttaa sekaannusta.

Olisiko siis jollain hyvä esimerkki graafisen, moni-ikkunaisen sovelluksen rakentamiseen? Ongelma poistuisi jos mdi containerin taustakuvan saisi näkymään myös alasivujen kontrollien läpikuultavuuden yhteydessä, mutta ne ole saanut tätä toteutettua, vaan läpikuultavissa objekteissa tausta näkyy siis harmaana.

Toivottavasti selityksestä saa jotain selkoa.

EDIT:
Tässä pari kuvaa softasta, jos ne vaikka selkeyttäisivät asiaa.
http://www.mp3car.com/vbulletin/vbimghost.php?do­=displayimg&imgid=6677
http://www.mp3car.com/vbulletin/vbimghost.php?do­=displayimg&imgid=6678

User137 [07.07.2008 18:18:31]

#

frm.hide piilottaa frm:n. Yhden instanssin luominen kerran ohjelman alussa luulisi riittävän, muutoin ohjelmasta tulee hidas. Voit kontrolloida mitä vaan formia mistä vaan formista käsin, tosin tuollainen ohjelma näyttäisi olevan kätevin tehdä pelkillä paneeleilla ja yhdellä ainoalla formilla.

sniiki [07.07.2008 19:41:40]

#

Jos nuo paneelien parentit asettaa kuten tuossa niin ei, formia ei pysty ohjata mistä vain. Instanssit on luotu vain kerran moduulissa.

Koitin tehdä myös toisella tapaa;
Pääformi normaaliksi, ei mdi containeriksi, tällä tavoin pääsivun kontrollit saadaan läpinäkyviksi formin taustakuvaa vasten.
Alasivuilla tuo läpinäkyvyys ei ole kovin välttämätöntä, joten ne voi aukaista vaikka näin:

frmalasivu1.toplevel = false
Me.Controls.Add(frmMedia)
frmalasivu1.top = 80
frmalasivu1.left = 0
frmalasivu.show

Mutta tuosta ei sen enemää iloa ole sillä tajusin nyt vasta että taustakuvan asettaminen formiin aiheuttaa tuon kontrollien (ainakin pictureboxien joita nappini on) hitaan piirtymisen.
Sanoisinko että kohtuullisen hanurista vb.netin graafiset ominaisuudet.

PS. tuo paneeleilla tekeminen ei siis auta tässä tapauksessa mitenkään :|

sniiki [07.07.2008 21:48:42]

#

Taustakuvalla varustetun formin piirtoa saa reilusti nopeutettua seuraavalla pätkällä (taustakuva asetettu normaalisti formin ominaisuuksista):

Protected Overrides Sub OnPaintBackground(ByVal e As System.Windows.Forms.PaintEventArgs)
              e.Graphics.DrawImage(BackgroundImage, e.ClipRectangle, e.ClipRectangle, GraphicsUnit.Pixel)
  End Sub

Vieläkin kontrollien peräkkäinen piirto näkyy mutta on tämä 10 kertaa parempi kuin vakio taustakuvan piirto.

vehkis91 [07.07.2008 22:21:31]

#

Aika hienon näköinen sovellus tulossa... :D

sniiki [08.07.2008 07:58:53]

#

Heh, no kiitos :)

sniiki [08.07.2008 14:02:20]

#

User137:

En tiedä tarkoititko tätä, mutta koitin tuota alkuperäistä listatyyliä siten, että paneelit korvattiin pictureboxeilla ja niiden paint eventtiin tein drawstringillä tekstin piirron. Ei vaikuttanut tulokseen vaan välkkyy edelleen.

Tähän mennessä siis tuo labeleiden liikuttelu siis edelleen paras vaihtoehto.

sniiki [09.07.2008 23:12:59]

#

Äh, oon nyt muutaman illan tota listaa parannellu ja muunnellu ja se kelpaa nyt omaan käyttöön muutoin MUTTA jostain syystä kun listaa skrollaa alaspäin, sekoittaa se kappaleiden järjestystä satunnaisesti. Labelit pysyvät oikeassa järjestyksessä, mutta niihin piirtyvä teksti on väärä. Tätä tapahtuu tosiaan vain ja ainoastaan listan pyöriessä alaspäin joten bugi on varmaan joku erittäin pieni ja typerä, mutta alan ilmeisesti tulla sokeaksi ite tolle koodin pätkälle niin tässäpä autoskrollauksen pätkä jos joku jumal-olento siitä vian minulle löytäisi :/
Joo se on vähä rujoa kun testailumielessä muuttanu/lisänny jotain väliin ja kommentitkin on tullu jalkaterän asennon määrittämällä kielellä.

Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
       Dim z, w As Integer
       Dim up As Boolean
       'Get the speed (diff) to "throw" the list
       If Control.MouseButtons = MouseButtons.Left And AllowListScroll And AllowAccelerating And Not AutoScrlToItem Then
           diff = (Cursor.Position.Y - prevpos3)
           If diff > 40 Then diff = 40
           If diff < -40 Then diff = -40
           prevpos3 = Cursor.Position.Y
       ElseIf AutoScrlToItem Then
           If AutoScrlUp And AutoScrlDist > 0 Then
               diff = -40 'ylös
           ElseIf Not AutoScrlUp And AutoScrlDist < 0 Then
               diff = 40 'alas
           Else
               diff = diff / 16
               AutoScrlToItem = False
           End If
       End If

       If AllowListAutoScroll Then

           If diff < -0.2 Then  'lista scrollaa ylös
               up = True
               diff = diff + 0.1
           ElseIf diff > 0.2 Then  'lista scrollaa alas
               up = False
               diff = diff - 0.1
           Else
               diff = 0
               up = False
           End If

           For i As Integer = 0 To SonglistItemIndexCount
               If i = 0 Then
                   newPOS = SonglistItem(0).Top + diff
                   If newPOS < 0 Then 'Ylös
                       newPOS = (SonglistItemIndexCount + 1) * lblHeight
                   ElseIf newPOS > (SonglistItemIndexCount + 1) * lblHeight Then 'Alas
                       newPOS = 0
                   End If
               Else
                   newPOS = SonglistItem(0).Top + i * lblHeight
                   If newPOS > (SonglistItemIndexCount + 1) * lblHeight Then 'Alas
                       newPOS = newPOS - (SonglistItemIndexCount + 1) * lblHeight
                   End If
               End If

               SonglistItem(i).Top = newPOS

               'text change:

               'list rolls up
               If up And SonglistItem(i).Top - prevPOS(i) > 300 And _
               SonglistItem(i).Top - prevPOS(i) < 400 Then

                   AutoScrlDist -= 1
                   nextUP += 1
                   nextDOWN += 1
                   If nextUP > (SongTitles.Count - 1) Then nextUP = 0
                   If nextDOWN > (SongTitles.Count - 1) Then nextDOWN = 0
                   SonglistItem(i).Text = nextDOWN & ". " & SongTitles(nextDOWN)

                   'list rolls down
               ElseIf Not up And SonglistItem(i).Top - prevPOS(i) < -300 And _
               SonglistItem(i).Top - prevPOS(i) > -400 Then 'lista scrollaa alas

                   AutoScrlDist += 1
                   nextUP -= 1
                   nextDOWN -= 1
                   If nextUP < 0 Then nextUP = SongTitles.Count - 1
                   If nextDOWN < 0 Then nextDOWN = SongTitles.Count - 1
                   SonglistItem(i).Text = nextUP & ". " & SongTitles(nextUP)
               End If

               prevPOS(i) = SonglistItem(i).Top
               prevI = i

               'Colorize selected song
               z = Microsoft.VisualBasic.InStr(SonglistItem(i).Text, ".")
               w = Microsoft.VisualBasic.Left(SonglistItem(i).Text, z - 1)
               If w = WMP.currentMedia.getItemInfo("playlistindex") Then
                   SonglistItem(i).BackColor = Color.LightBlue
                   SonglistItem(i).ForeColor = Color.White
               Else
                   SonglistItem(i).BackColor = Color.White
                   SonglistItem(i).ForeColor = Color.Black
               End If
           Next
       End If
       TextBox1.Text = nextUP
       TextBox2.Text = nextDOWN
       TextBox4.Text = diff

   End Sub

User137 [10.07.2008 12:25:01]

#

Sanoisin että vika on tuolla:

'list rolls up ja 'list rolls down

käytät SongTitles(nextUP) riviä havainnollistamaan labeliesi tekstit, kun ne eivät edes mene numerojärjestyksessä ylhäältä alas. Sulla on SonglistItem(0).Top mikä liikkuu aluksi mihin kohtaan vain ja sen jälkeen skrollaat muut sen alle tai sen yläpuolelle jos eivät alas mahdu, kun taas nämä yläpuolelle joutuvat itemit voivat sisältää teksiä joka kuuluisi alas ruudun ulkopuolelle.

sniiki [10.07.2008 14:41:13]

#

Kiitti kun jaksoit vilkaista,

nextup ja nextdown siis osoittavat mikä biisi pitäisi seuraavaksi putkahtaa listaan ylhäältä ja alhaalta, ne kulkevat järjestyksessä.
(nimet siis haetaan stringitaulukosta SongTitles)

SonglistItem(0) voi liikkua yhdellä kierrolla korkeintaan diff muuttujan verran joka on aina alle listan pituus, eli se ei voi lentää montaa kertaa listan läpi yhdellä kierrolla ja sotkea asioita.

Ja koska tuo labelilista käydään järjestyksessä läpi, niin noiden muiden itemeiden pitäisi ihan nätisti siirtyä järjestyksessä listan alkuun ottaen ensin järjestyksessä seuraavan biisin nimen, eli yläpuolelle ei pitäisi joutua alapuolelle kuuluvia nimiä.

Labeleiden siirto ja nimien vaihtaminen ovat siis muutoin toisistaan riippumattomia operaatioita, mutta seuraava haettava nimi YRITETÄÄN päätellä siitä onko joku labeli lentänyt rajojen yli.

Mutta oikeassa olet, tuohon itemien 1-> siirtymiseen tuo ongelma liittyy ja koko tekeles on suhteellisen perseestä noiden nimien järjestyksessä pitämisen suhteen.

Ruokatunnilla testailin viä tuota ensimmäistä versiotani ja itseasiassa välkyntä tuntui katoavan kun laitoin doublebufferin kaikkiin paneeleihin ja labeleihin. Saattoi aiemmin puuttua paneelista joka sisältää tuon ylös alas nytkyvän pienemmän paneelin. Täytyy illalla testailla josko sen version saan toimimaan välkkymättä, olisi tuo nimilistan hallinta ja moni muu asia huomattavasti helpompaa sen kans.

User137 [10.07.2008 16:25:09]

#

User137 kirjoitti:

Voit tietysti käyttää jotain kuva komponenttia niiden labeleiden ja paneelin sijaan ja piirtää see lista tekstiä itse. Pääsee ainakin koodissa ja päänsäryssä vähimmälle.

Jos tämän idean selittäis tarkemmin niin...ensinnäkin en tiedä kuinka se tapahtuu VB:ssä, google tai joku muu voinee kertoa.

Pictureboxia ei siirretä ollenkaan vaan kuva sen sisällä liikkuu. Lista nimiä piirretään kaksoispuskuriin ja sen jälkeen kaksoispuskuri piirretään Pictureboxiin jolloin välkkymistä ei voi olla lainkaan. Kuinka kaksoispuskuri luodaan manuaalisesti, siihen piirretään tekstiä itse jne jää sitten selvitettäväksi.

sniiki [10.07.2008 17:12:17]

#

Tuossa ideassa vaikeaksi menee taas biisin valinta listasta. Pitäisi aina osua tekstin kirjaimiin, tai luoda joku toleranssialue sen ympärille klikkauksen rekisteröimiseksi joka menee taas turhan monimutkaiseksi.

sniiki [18.07.2008 16:37:12]

#

Rakensin roskan viä.. en muista enää monennellako tavalla, mutta nyt laitoin kaksi paneelia päällekkäin jotka kumpikin täytetään esim. 10 rivillä biisejä. Paneelit on yhtä korkeita kuin "isäntäpaneeli" jossa ne liikkuvat. Jos jompi kumpi paneeli menee kokonaan piiloon, piirretään siihen uudet labelit ja nakataan se toiseen päähän. Näin siis tekstien/labeleiden muuntovaiheessa paneeli on aina piilossa ja ongelma kierretty tällä tapaa.

Melkonen Erkki-ratkaisu tuo lienee, mutta sainpahan tehtyä.

Huonoa tuossa on jälleen vaikeus seurata mikä biisi-indexi on missäkin labelissa, joten teen tunnistuksen taas varmaan vain lukemalla kappaleen edessä olevan numeron.


Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta