Results 1 to 5 of 5

Thread: Adding lots of buttons

  1. #1

    Thread Starter
    Addicted Member
    Join Date
    Dec 2011
    Posts
    176

    Adding lots of buttons

    I have a re sizable panel which i am adding over 100 buttons to. to do it i have a timer which detects any change in the height or width. then clears the panel and re draws all 100 buttons on. however i am encountering issues with flashing (where the buttons are gone for a split second before being repainted)

    and also speed issues. it seems to be slowing down the users ability to re size the window.

    i was thinking by adding the buttons through its own thread it might combat the main (speed) issue.

    any suggestions?
    sorry if my problem is not clear!
    thanks Tim

  2. #2
    Frenzied Member
    Join Date
    Feb 2008
    Location
    Texas
    Posts
    1,288

    Re: Adding lots of buttons

    If you're using the sizeChanged event, why not just get the total y (from 0 to the sum of the heights of the existing buttons (with any spacing included)) and subtract that from the new size of the panel. Do a little arithmetic to see how many more buttons you can fit and just append them to the end of the panel.

    Justin
    You down with OOP? Yeah you know me!
    MCAD and MCMICKEYMOUSE (vb.net)

    ----

    If it even kinda helps... rate it : )

    Edit a Multi-page .tif file and save.

  3. #3
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    40,104

    Re: Adding lots of buttons

    I did something like this, though I was adding a custom control rather than a button. What I ended up doing was creating an array of controls sized to the largest size I would allow. All of the control creation and hooking up was done during the form load. Then, on the form, I would determine which ones were actually visible (the rest were off the visible part of the screen) and toggle the visible property. Toggling visibility is FAR faster than creating the control.

    The code doesn't really lend itself so much to being posted, but if you'd like to see some of it, I can post various pieces.

    EDIT: Also, don't use a timer to detect size changes. There are events for that, and that's where the code should be.
    My usual boring signature: Nothing

  4. #4

    Thread Starter
    Addicted Member
    Join Date
    Dec 2011
    Posts
    176

    Re: Adding lots of buttons

    Thanks for the help, i tried the my threading idea but im not too familiar with threading and so i got lots cross thread errors.

    i would love to see this code piece if you could show me.

    also thanks for the tip on detecting sizes!

  5. #5
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    40,104

    Re: Adding lots of buttons

    Don't bother with threading. Controls HAVE to be on the UI thread, and controls are all you are talking about. You'd end up doing more work and taking longer to use threading.

    Some code:

    Code:
    'I declared a 2D array of controls:
    Private mControls(,) As MortalityTB
    
    'This part is all in the Sub New for the form:
    
    'Calculate the maximum number of controls that will fit on the screen both wide and high.
    'This determines the number of controls to create.
    Dim wid = CInt(Math.Ceiling(Windows.Forms.Screen.PrimaryScreen.WorkingArea.Width / 113))
    Dim ht = CInt(Math.Ceiling(Windows.Forms.Screen.PrimaryScreen.WorkingArea.Height / 24)) - 6
    
    'Redim the array.
     ReDim mBulkTBControls(wid - 2, ht - 1)
            For x = 0 To wid - 2
                For y = 0 To ht - 1
                    Dim lMortTB = New MortalityTB
                    lMortTB.Left = (113 * (x + 1))
                    lMortTB.Top = 24 * (y + 1)
    
                    'Add a bunch of handlers
                    AddHandler lMortTB.MarkClicked, AddressOf HandleMarkClick
                    AddHandler lMortTB.CommentClicked, AddressOf HandleCommentClick
                    AddHandler lMortTB.KeyFailure, AddressOf HandleKeyFailure
                    AddHandler lMortTB.DataChanged, AddressOf HandleDataChanged
                    AddHandler lMortTB.TextAdditionFailed, AddressOf HandleTextAdditionFailure
                    mBulkTBControls(x, y) = lMortTB
                Next
            Next
    That part sets up the controls. While I am using the size of the primary screen to figure out the number of controls that can be in the array, you may note that I reduce the height by 6. This is because the area on the form that can have controls is less than the whole form (there is room for some buttons along the bottom).

    I was making this into a grid, so I had a list of labels for column headers, and another for row labels, but that's a different issue.

    'The code in the ReSize event
    Code:
             If SizeGrid() AndAlso Not mSuppressEvent Then
                ShowData()
            End If
    First I call SizeGrid to show the proper controls, then I call ShowData to load them. The latter may not be relevant. Since I was making a grid that was MUCH larger than the screen, there were horizontal and vertical scroll bars (the vertical bar only showed up, as needed, like a ListBox). The data that was loaded into the textboxes was based on the value of the two scroll bars. It doesn't sound like you are doing anything like that, but that's what ShowData was all about.

    SizeGrid did this:

    Code:
     Dim rowCount As Integer = CInt(Math.Ceiling((Me.pDisplaySurface.Height - 40) / 24)) 
    '(subtract the height of the column headers (24) plus the height of the horizontal scroll bar (16).
     Dim colCount As Integer = CInt(Math.Ceiling(Me.pDisplaySurface.Width / 113))
    
    Dim lControls(,) As MortalityTB
                'Only do anything if either count would necessitate a change.
                If rowCount <> mRows OrElse colCount <> mColumns Then
                    'Dim lControls(,) As MortalityTB
                    mSuppressEvent = True 'This is added because the value will change for the vertical scroll, but it shouldn't do anything at this time.
                    If mOrderedNames.Count > rowCount Then
                        vertScroll.Visible = True
                        vertScroll.Maximum = mOrderedNames.Count - (rowCount - 1)
                        rowOffset = 16
                    Else
                        vertScroll.Visible = False
                    End If
                    mSuppressEvent = False
    
                    'Now set up all the TB controls.
                    ReDim lControls(colCount - 2, rowCount - 1)
                    'This step will move over all existing TB, as well as add any new ones.
                    For y = 0 To rowCount - 1
                        For x = 0 To colCount - 2
                            lControls(x, y) = mBulkTBControls(x, y)
                            lControls(x, y).Left = (113 * (x + 1)) - rowOffset 'Might have changed the left.
                            If Not Me.pDisplaySurface.Controls.Contains(lControls(x, y)) Then
                                Me.pDisplaySurface.Controls.Add(lControls(x, y)) 'All controls are on a panel.
                            End If
                        Next
                    Next
    
                    'Now to remove all the TB that need to be removed. In case the thing was reduced in size.
                    'This removes the columns.
                    If colCount < mColumns Then
                        For x = mColumns - 2 To colCount - 1 Step -1
                            'Delete the textbox for all existing rows.
                            For y = 0 To mRows - 1
                                Me.pDisplaySurface.Controls.Remove(mControls(x, y))
                            Next
                        Next
                    End If
    
                    'This removes the rows.
                    If rowCount < mRows Then
                        For y = mRows - 1 To rowCount Step -1
                            'Delete the textbox for all existing columns.
                            For x = 0 To mColumns - 2
                                Me.pDisplaySurface.Controls.Remove(mControls(x, y))
                            Next
                        Next
                    End If
    It's a bit hard to tease out the parts that are relevant to the grid. There was a bit more code that dealt with putting the Row and Column headers in place. All controls are located on a panel rather than on the main form, so the positioning of the controls (top, and height) is based on panel coordinates.

    One thing I noticed when I looked at this is that I was creating the Bulk array, but then I was moving just the ones I wanted into a local array. This takes advantage of the fact that controls are reference types. I wasn't even toggling visibility, as I had said earlier. In fact, I was only showing the controls from the local array. 0,0 in the bulk array was 0,0 in the local array. The bulk array holds all the controls that could be shown if the form was at the maximum for the screen, and I copy the needed controls to the local array. Since controls are reference types, all that is copied is a single reference, which may be as little as four bytes. That's pretty fast.

    Hope it helps some.
    My usual boring signature: Nothing

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width