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
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ä.
Mulla oli samantapainen projekti just muutama päivä sitten, muutaman tunnin koitin sitä ongelmaa ratkasta, mut taitaa olla melko mahdotonta. :E
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.
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.
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.
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
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.
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 :|
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.
Aika hienon näköinen sovellus tulossa... :D
Heh, no kiitos :)
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.
Ä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
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.
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 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.
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.
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.
Aihe on jo aika vanha, joten et voi enää vastata siihen.