1st question: OnPaintIt is better to use TPaintBox.
When I click on a start buttion I show a mine field and fill it with squares. Then I click on the mine field and show a mine. But the mine field fully repaint and my squares is gone. Why?
It is better to use TPaintBox.Thanks! I'll try and be back later to say if it works for me.
It is better to use TPaintBox.No, if I simply replace TBevel with TPaintBox it's not working. Attached pics demonstrates three steps with TBevel (show mine) and PaintBox (show no mine).
In the OnPaint handler, assume that all the content is corrupted and incorrect. Based on this, build the logic of rendering.I found a simplistic clone of MS Paint (https://github.com/DreamVB/MePaint) on Github. It seems that author creates a bitmap in memory, in OnMouseUp/Down/Move draws something on top of this bitmap and then in OnPaint just put the whole bitmap on the PaintBox. But it's kinda wierd solution. Why are the things so complicated?!
It seems that author creates a bitmap in memory, in OnMouseUp/Down/Move draws something on top of this bitmap and then in OnPaint just put the whole bitmap on the PaintBox. But it's kinda wierd solution. Why are the things so complicated?!It just caches a lot of drawings on a separate bitmap. To speed up. But the principle remains the same - redraw each time.
But it's kinda wierd solution. Why are the things so complicated?!That is how graphics work.
It just caches a lot of drawings on a separate bitmap. To speed up. But the principle remains the same - redraw each time.So I have to do the same, right? Create a bitmap in memory, draw the mine field on this bitmap, place bitmap on PaintBox, trigger OnPaint by Repaint, Update or whatever, draw something (e.g. bomb) on top of mine field, place this new picture on PaintBox, trigger OnPaint again and so on. Not an elegant way. And passing signals like "I press a button" or "I click on mine field" from OnClick to OnPaint with global variables is not an elegant too. Well... I have to deal with it. :)
That is how graphics work.Ok, I get it. But why covering/uncovering my window with another window (e.g. browser) does not triiger repainting and minimizing — trigger? Althouth it's pretty the same for my app form — nothing changed on it.
Ok, I get it. But why covering/uncovering my window with another window (e.g. browser) does not triiger repainting and minimizing — trigger? Althouth it's pretty the same for my app form — nothing changed on it.The only difference with other controls is that the painting (refresh) happens automatically on/for certain events.
you could perhaps react on another event that signifies to redraw the window or panel at which the paintbox control is positioned and use that to update your paintbox. tbh, I never tried.You wanna say what I can prevent control repainting?
your message on how to do it makes it sound very complicatedNo, no, it's not a big deal. :) Dealing with painting, repainting and so on seems to me complicated and unclear.
{ offtop onAs a new user you are not allowed to edit your message until you have done a minimal amount of posts. This is done by the forum software as a protection to prevent trolls and spammers from posting and modifying their message. Unfortunately we have a lot of those.
How do you edit your messages? I dont' see any button or something like that.
offtop off}
As a new user you are not allowed to edit your message until you have done a minimal amount of posts.Ahh... Ok, I get it. Thanks for the clarification!
Have a bitmapMineSweeper is not Doom. There's no need to get as much fps as you can. :)
If your game doesn't flicker do as you wish, but there's a flicker in some cases because you're painting several times on the screen. Noticeable only in some old hardware (that I had in time and noticed it with Lazarus and Windows 7).This was exactly what I wanted to write as I remember minesweeper on win95 and when a lot of cells were being opened you could see the flickering of the cells when they were drawn. Ofc that has been a long time ago with different hardware but still it did not have to that and could be solved even back then.
PS: how is the weather over there ? (let's up that postcount of yours :D )Just got back from the outside. :)
Here is 35° C.Lucky you! :)
And yes I can also remember the flickering from the original minesweeper from Windows 95. :)I remember flickering in MS DOS on my monochrome display. :))
Just got back from the outside. :)Minus 15 ? darn that is not weather to show up in shorts. It's currently around 4°C here.
During the day it was +7°C but now there's a bliizzard out there and about –15°C.
Still not able to edit a message ?No. But that's not the most wanted feature for me. :)
You better tell me why my Button1 works only once. :)Oh, I'm sorry. I missed that you still have issues.
Logic is pefectly clear:I can't answer the why as your logic seems correct. However I suspect that the paintbox does not get a refresh on secondary press of your button. Why that does work for the first press and not (as you stated) consecutive ones I have no idea. Try adding a call to paintbox1.refresh at your buttonclick event after having set the necessary values and see if that helps.
• Button clicked? → ok, set global bool
• in OnPaint check global bool, if true do staff and unset global bool
Nothing special, it seems. But then Button stops reacting.
Why? WHY?!
Try adding a call to paintbox1.refresh at your buttonclick event after having set the necessary values and see if that helps.It works! Great! Thanks a lot!
But why it works?! What's the matter?See edit in my previous post. You can verify that by setting the paintbox dimensions on form create event and then try the buttonclick. If my clarification is correct then it should not paint on the first click either.
If my clarification is correct then it should not paint on the first click either.It works fine: paint from the first click, even wothout assigning onpaint in the fomcreate.
Sorry for typos I'm dying to sleep.By all means, then get some sleep please. There is always tomorrow. I see you are still logged in. I'll have a look at it later because I have other things on my plate right now as well. We'll figure it out :)
It works fine: paint from the first click, even wothout assigning onpaint in the fomcreate.Well, in that case there must be something off with your testing method or a difference in widgetset/platform.
Your guess is interesting but does not explain how paintbox.onpaint corupt button.onclick?
How one control can so unclearly ingluence another thougth I must send signals with the global vars, bot directly.
It blows my mind. I need to get some sleep. :)
Use a Timer and refresh the paintbox every 33ms (1000/30) to get something like 30fps.Thanks for advice! Somewhen I'll use it!
Is like real games works.
If the onpaint method is removed from the object inspector and set the dimensons of the paintbox at form create event and after that assign the onpaint event...That's definitly clear!
.. and have the buttonclick event read:
Then the paintbox onpaint event will not be called at that click and as a result the grid will not be painted and will stay empty.
Hence we have to trigger the event ourselves by either using .refresh, .update, .invalidate or invoke the paint method (whatever is applicable for the situation).Googling and reading this topic (https://forum.lazarus.freepascal.org/index.php/topic,40433.0.html) gives me understanding that
See also attached project.Thanks for you time! I've read it and here some things...
// actually we should calc the row and column of the cell that contains a bombNo, we shouldn't. If there are some other already opened cells drawing the complete grid will override it.
// and then draw the complete grid as above, making an exception for the cell
// that contains the bomb and draw the bomb instead of a 'normal' closed cell.
Googling and reading this topic gives me understanding thatAlthough you can use google, the help is a much better source. It is just a press to F1 away :)
refresh — refreshes the component internally without repainting it;TControl.Refresh (https://lazarus-ccr.sourceforge.io/docs/lcl/controls/tcontrol.refresh.html):
Calls the Repaint method to either draw the clipping rectangle for the control to the handle in the Parent, or invalidate the control area for the next paint operation that occurs when the Parent controls are Visible.
invalidate — tells the component that its visuals is outdated and then repaint only visible part of component (maybe some part off screen or cover by another window, whatever)Invalidate (https://lazarus-ccr.sourceforge.io/docs/lcl/controls/tcontrol.invalidate.html)
Calls the InvalidateControl method to invalidate the bounds rectangle for the control using the clipping rectangle for the Parent. The control is redrawn when there are no pending messages in the message queue.How exactly it is implemented depends on the used control. But yes in basics what you wrote applies.
update — refresh + repaint;
Update calls the Update method in the Parent control to refresh the window where the control is hosted. No actions are performed in the method when Parent has not been assigned.Thus, the parent gets notified. What the parent does (in relation to the component that was placed on it and notified it) depends on the parent.
// there is some unclearness: are refresh and update not telling the component that its visuals is outdated? What's the point?In case the former, yes. In case the latter it depends on the parent component. But it also depends on how the child-control handles 'instructions' from the parent. It can vary per control.
repaint — just repaintCorrect.
// and there is some unclearness too: what's the difference between calling Repaint and calling OnPaint method? For example, PaintBox1.Repaint or PaintBox1.OnPaintDoSomeStuff.You do not call the onpaint method. It is an event that is invoked by the control (when assigned) whenever it it deems necessary to do so while invoking paint or repaint is something that you are able to call whenever you feel the need to do so.
No, we shouldn't. If there are some other already opened cells drawing the complete grid will override it.Not if you keep track of the state, that is the whole point I was trying to make. The state determines how a cell should be drawn.
n my real program I'm doing exactly how you mentioned beneath — working with the dynamic array of cells and repainting (or not, if it's already opened) only one that clicked.As stated /if/ you keep using the path as in your example (nothing wrong with it, just making sure you get the idea) then get rid of the drawbomb check and the click check and draw the whole grid (e.g. every cell). Use a state for each cell to know exactly what you need to draw (cell open, cell closed, etc.). When you left click the mouse then change the state of the cell before drawing/updating/refreshing the grid.
Actually I was a fool and doing all my drawings in the onclick method. I thougth that component (in my case — bevel) holds its state unchanged until I'm draw something on it.
When I tried to rewrite it to draw in the onpaint method I'm stuck with the problem, reproduce it with the minimal code and came here for advice.
Although you can use google, the help is a much better source. It is just a press to F1 away :-)Thanks for your paitience!
Hopefully that was able to clarify a few things, if not then don't hesitate to point them out.Sure it was! Thanks again!
I was just on my way heading out so it might take me a while to reply. Post noted and I will have a look when I'm back. But perhaps someone else is able to address your concerns/question(s) as well.I'm not in a hurry! Good luck out there!
Thanks for your paitience!To show incentive is half the job :)
I'm not a newbie in programming itself but I'm total newbie in LCL so a couple of things can be unclear and challenging for me. :)I understand and that shouldn't be a problem.
And of course I'm not an expert, programming is just a hobby for me. Sort of. :)Did we not all started out that way ?
I redwrote my example to use bitmap as an intermediate layer and it works well.Yes, I can see. That is nice progress.
Only one thing seems to me not the best and elegant way to do it.Ok, let's try provide some pointers. Keep my previous remark in mind.
I personally treat every component that I am not familiar with as a Christmas present that requires careful unwrapping.That's a good idea!
I do have a couple of hintsAnd I'm here to get some!
The bitmap variable in the source is positioned between the components.You right! I just placed it right after form variables keeping in mind only one thing: it sholud have access to other form's vars and methods.
It is wiser to situate that into a separate section.
Speaking of which. All variables declared right under the form variable declaration are accessible outside your form units as well. It is custom to make these variables part of a private section in your form type declaration.You right. But what if I make another form (for example, Options form to change mine field sizes with sliders and see how the mine field is changing sizes in real time)? Option form will not have access to private section of Main form. So some vars should be global.
If you must place them outside your form type declaration it is custom to do that as part of the implementation section.Correct me if I'm wrong.
The bitmap can be resized and also be cleared.TBitmap.Clear! Damn it! So easy!
I rather wait for your epiphany moment regarding cell status.:D
You right! I just placed it right after form variables keeping in mind only one thing: it sholud have access to other form's vars and methods.You're probably right.
I moved it to private section now but I thibk it doesn't matter for such a small educational project like mine.
You right. But what if I make another form (for example, Options form to change mine field sizes with sliders and see how the mine field is changing sizes in real time)? Option form will not have access to private section of Main form. So some vars should be global.You are quite right about that. I assumed (yes, mother of all screw-ups :D ) it was a simple implementation contained in a single unit/form (perhaps using menu's and/or other components on the same form).
Correct me if I'm wrong.If you are talking about direct access then yes you are absolutely correct (see above remark about passing along)
All that is placed in the interface section are accessible from another units and forms.
All that is placed in the implementation section are not accessible from another units and forms.
This is how I can recall it from my Borland Pascal times.
Of cource I can use only one array of bytes to minimize using memory but it will cost more annoying calculations, bitmasks... I don't like that.Instead of bitmasks, have a look at a set (enums). If my calculations are correct then the maximum number of neighbouring bombs would be eight (nine if you count zero). Add to that whether or not a cell contains a bomb or a flag perhaps a question-mark and you would be well on your way.
E.g. aligning and anchoring... I just touched water but see a lot of underwater stones.Ah yes you mentioned having an issue with that. Note that there were quite a few changes/fixes with regards to anchors and alignments since the release you seem to be using so it might very well you encountered a bug (that might also have been fixed in the mean time). With the information provided (unless I missed something) it is quite impossible to reproduce/verify.
Like most people I do not like mixing IDE generated content with my ownMe too but it's not a big deal for a small educational projects like mine. And of course visual designer might be quite useful.
especially since it has the habit of being tossed around when adding and removing components.Right! So I decided to write messy code at first and refactor it only when I'm done.
In light of your other remark(s) it is quite possible to add a class visibility specifier multiple times in a class type definition, for instance the public specifier.Somthing like: private {bla-bla-bla} public {bla-bla-bla} private {bla-bla-bla} public {bla-bla-bla} ?
I assumed (yes, mother of all screw-ups :D ) it was a simple implementation contained in a single unit/form (perhaps using menu's and/or other components on the same form).For now it is. But I write a code keeping in mind that functionality of my program might extend. At the same time I don't want to make my code overcomplicated (like passing massages with manually handling). No doubt there's a different ways to passing vars and using globals is not the best practice. But for a small project that's enough. I assume (mother of all screw-ups :D ) that there are no penalties or issues with using globals for — again! — a small project.
Whatever works best for you would be the correct implementation ;DI hope so! :)
Instead of bitmasks, have a look at a set (enums). If my calculations are correct then the maximum number of neighbouring bombs would be eight (nine if you count zero). Add to that whether or not a cell contains a bomb or a flag perhaps a question-mark and you would be well on your way.Yes, It was my first attempt but lately I'll show you why I decided not to use it.
If you are able to explain what you are trying to achieve and what fails (e.g. what in your eyes is a (reproducable) bug) then we can have a look at it.Ok, I'll explain and attach some screenshots.
Also note that Lazarus 4.0RC2 also exist and that has even more fixes in comparison to 3.8 (though I am not sure how this relates wrt the few days ago released 3.8 fixes release).I prefer to use stable versions of products so betas or RCs is not an option. Only in special cases.
If you wish to focus on a particular issue and perhaps try attract more readers then it might be helpful to start another thread solelyI think later I'll start a new topic with subject something like "Stupid questions of a newbie making a sort of Mine Sweeper". :)
things always seem to have a tendency to work out differently as expected/intended.Story of my life :D
2. In the Form Designer place TPaintBox on an empty form;Steps 2 and 3 can be reversed and instead of TPaintBox it can be used another non-visual components. Not all.
3. Set AutoSize property of TForm to True by checking it in the Object Inspector.
Ok, I'll explain and attach some screenshots.Thank you. Nice and clear description.
try using a newer version of the IDE (either 3.8 or 4.0RC2)The question is how I update properly? Fully uninstall and install new version? But how can I save all settings of IDE?
The question is how I update properly? Fully uninstall and install new version? But how can I save all settings of IDE?That is a very good question because I am not familiar with the windows side of things (e.g. the installer).
In case you wish to preserve your configuration make sure to backup your Lazarus configuration directoryThanks! This is how I should do it!