Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Drawing gradients question #1460

Closed
kdschlosser opened this issue Dec 12, 2019 · 22 comments
Closed

Drawing gradients question #1460

kdschlosser opened this issue Dec 12, 2019 · 22 comments

Comments

@kdschlosser
Copy link
Contributor

kdschlosser commented Dec 12, 2019

OK I am trying to draw a rounded rectangle that has a gradient inside of it. the rectangle to 300x150 and the gradient is going to go from red to transparent. I have attached an image that shows what I am looking to do.
For the life of me I cannot figure out ho to go about making the gradient. I tried DC.GradientFillConcentric and this only drew a gradient circle in the middle. The name of this function is misleading. It should be GradientCircleConcentric not fill. fill leads you to believe that it fills the whole rect not just making a circle. I would have thought there would be a simple method that can be used maybe a blending mode and making a really wide line. IDK I can't find an easy way, I also tried googling for an example and came up with a single mailing list entry for someone asking the exact same thing. they were given a link to wxWidgets API docs specifically the wxGraphicsContext portion of it. and the user only said "It works!" and didn't provide any kind of an example. So I am going to make the assumption that what I need is in there I am not sure how to go about writing the code.

If someone can shed some light on this for me it would be appreciated.
Thank you for any assistance you can offer.
Kevin.

example_rectangle

@RobinD42
Copy link
Member

One approach I've seen for things like this is to draw a series of concentric rounded rectangles. First the black one, then a series of rectangles with a progressively more opaque border pen, and a transparent brush. The last one will use a fully opaque brush for the fill. It won't be exactly like your sample, but you can probably get pretty close by playing around with border thicknesses, corner radii, etc.

Another possibility is in wxPython 4.1, where there is support for applying a gradient brush to a stroked wx.GraphicsPath. So to do something like your image you could draw the black rectangle, and then draw the red rectangle using a fat gradient pen with the gradient centered at the center of the rectangle.

Yet another option, if wx.GraphicsContext and related classes are not cutting it, then you can probably do it with Cairo, which can be used with wxPython on all platforms, (although it might take a little extra setup.) See wx.lib.wxcairo.

Finally, if your graphics don't need to be super dynamic, then you can use SVG files in wxPython using the wx.svg package, which was added for version 4.1. You could edit SVG files (or create the appropriate XML at runtime) and either render directly element by element onto a wx.GraphicsContext or rasterize them onto a wx.Bitmap of whatever size you need.

@Metallicow
Copy link
Contributor

@RobinD42 Just checked the demo, and a bit off subject but I'm guessing you at least tested the wx.svg render demo on mac... it doesn't appear to be completely working on windows, tho the svg bitmap demo is working. ...maybe something needs tweaked to get the render demo working on windows...

@RobinD42
Copy link
Member

Oops. Yes, that demo is slightly unfinished. On windows the default GraphicsRenderer used is the GDIPlusRenderer, but the GDI+ API does not have the capability to correctly render all SVG features. So we need to force the use of the new Direct2DRenderer instead. I'll get that updated, thanks.

@kdschlosser
Copy link
Contributor Author

@RobinD42

I had thought about doing a recursive rectangle getting smaller each loop and adjusting the alpha each loop to a higher number. the problem with this method is you end up with a visual anomaly in the rendering called Moiré

Almost everyone has seen Moiré and never put much thought to it. so for those of you that want to put a name to that anomaly you have seen and never thought twice about. here is an image that will help you out.

image

I have tried on many occasions to do a manual gradient using wxPython and 100% of the time i have gotten this anomaly

I find it to be a particularly unattractive thing to look at.
and not to mention the cost of rendering like that is extremely high,

@RobinD42
Copy link
Member

RobinD42 commented Dec 17, 2019

So we need to force the use of the new Direct2DRenderer instead. I'll get that updated, thanks.

I went to look at the demo code for the SVImage_Render sample today and saw that it's already using the Direct2D renderer on Windows. So the glitches you were seeing are probably some off-by-one or floating point truncation issues in the the C++ code for the Direct2D renderer. When I was working on the SVG stuff I noticed that there were some cases there where a floating point calculation was being assigned to an integer that probably shouldn't have been.

It's also possible to use the Cairo GraphicsRenderer on Windows, and it does an excellent job with the SVG rendering.

@kdschlosser
Copy link
Contributor Author

OK I am going to need an education here.. what is the Cairo GraphicsRenderer?

@RobinD42
Copy link
Member

RobinD42 commented Dec 17, 2019

The wx.GraphicsContext class delegates most of its operations to a platform-specific renderer class. You can see the base class API in the docs for wx.GraphicsRenderer. When you create a wx.GraphicsContext it will create an instance of the default renderer class for the platform, or you can create an instance of some renderer and have it create the context using that renderer as the backend.

Cairo is an advanced 2D vector based drawing library. It was designed to be used as part of the GTK family of libraries, but it is generic enough that it can be used on other platforms and even in non-GUI use cases. With a couple extra dependencies[1] you can use Cairo directly from Python in a wxPython application. The Cairo.py and Cairo_snippets.py samples in the demo show how to do so, and some of the capabilities.

The Cairo GraphicsRenderer is the graphics renderer implementation that uses the Cairo library to implement the GraphicsContext functionality. You can create a context using it from Python like this:

renderer = wx.GraphicsRenderer.GetCairoRenderer()
context = renderer.CreateContext(dc)

[1] The dependencies are the cairoffi Python package from PyPI, and the Cairo shared libraries. Those libs are available on any commonly used Linux distro. On Windows I've included DLLs in wxPython's wx package folder. On OSX you'll probably need to build the libs using a tool like MacPorts or HomeBrew. There is a bit more info about this in the wx.lib.wxcairo docstring.

@Metallicow
Copy link
Contributor

@kdschlosser iirc pycairo is the easiest way to get the cairo official demo stuff working, so this should work last I checked...

pip install pycairo

...otherwise when you fire up the cairo demos in the wxPy Demo it might spit back some missing dependencies message errorpanel.

@kdschlosser
Copy link
Contributor Author

I had to install pycairo using a prebuilt binary. it will not insutall using pip. I get a compilation error.

@RobinD42
Copy link
Member

cairocffi is easier. It is pure Python so there isn't any need to build an extension module. Instead it dynamically invokes the Cairo API functions via cffi.

@RobinD42
Copy link
Member

RobinD42 commented Dec 17, 2019

Also, using wx.lib.wxcairo will make it easier to use either cairocffi or pycairo, plus it provides functions for integrating with wxPython DCs, Bitmaps, and Fonts.

@kdschlosser
Copy link
Contributor Author

OK so now my question is how do I obtain the Cairo binary for Windows without installing GTK or any other package.. I only keep on finding it prepackaged with something else. I also read that the Cairo source is not MSVC compatible and needs to have changes made to it to make it MSVC compatible. Now This information is gotten from the internet so I do not know the age of the information nor do I hold it as absolute truth LOL....

I am sure with spending half a day I will be able to build or locate Cairo, but for the sake of saving me the effort if someone has the information and they are willing to share it.. I am all ears.. (eyes really)

@Metallicow
Copy link
Contributor

Metallicow commented Dec 17, 2019

Just to run the wxPy demos for cairo on windows is pretty simple
install Python
install wxPython
install cairocffi or pycairo
download the demo from the snapshots builds page and extract it to desktop, etc...
then run the main wxPy Demo or run the 2 individual samples for cairo (Cairo.py & Cairo_Snippets.py) included

... or was you having some other issues or needed to build for a specific purpose
if pip install didn't work for pycairo try pip install cairocffi
I got the demos running on my machine atm
Cairo

@RobinD42
Copy link
Member

OK so now my question is how do I obtain the Cairo binary for Windows without installing GTK or any other package

The DLLs are included with wxPython. No need to build anything or extract from other packages. I've already done the latter for you. See the docstring for wx.lib.wxcairo.

@kdschlosser
Copy link
Contributor Author

I am good to go.. I have it running..

The only thing I dislike about the current interface to cairocffi is the voodoo magic code that does not allow an IDE to autocomplete or show type hints.. so a lot of poking through the wx code and then the cairocffi code to see what can be done.. and then you toss in the heap of voodoo magic code cairocffi is using as well, makes everything a mystery!...

So I have already ported all of the header files for Cairo to python. this way I have a reference.

need to deep six the voodoo magic code and code it the good ol fashion way.. subclass the cairocffi classes so a data path can be seen. Better yet use my port of the Cairo headers and build classes from that. so a full data path is available and an IDE will work properly all the way back to the shared lib for every available exported function the lib has to offer. my port already has all of the structures, enums, constants and functions coded. need to assemble them into python classes.

I am going to have to check again. but I think that Cairo has private objects that get passed as parameters to public functions....

@Metallicow
Copy link
Contributor

Ah... IDE stuff. Yea that is always an issue with people depending on how much they know python.
Whether to have a notepad style editor or an IDE that "thinks" it knows what you want to do.
porting stuff to a skeleton file just so you can get references is yes a bit of work but often times it helps in the end cause then it opens up a pathway for people to better document stuff.
While I'm a bit old fashioned and recommend reading the docs, I understand the need for IDE features that do stuff like this. SourceCoder targets itself mainly, so basically I just had to wrap all the python, wxPython, and Scintilla stuff all into one-liner functions in single files. The issue with other editors is that as far as I know none of them do this to make them truly hackable(besides maybe atom) and with that the language it is written in plays a big part. ... so to make the story short and sweet, if your editor is not written in python, then effectively you cannot have an interpreted editor with an intelligent autocomplete/snippets engine that can edit the editor itself or completely rebuild itself also in a scripted manner with docs or by-the-docs. To do this with python, the abstract syntax tree must be completely wrapped also which is a big job. Most IDEs have a snippets engine but none provide completely wrapped libraries of snippets. Cairo is a external lib wxPython wraps and I don't make much use of it, so therefore I cant help you with a skeleton file or even snippets as of yet. With wxPy4.1 introducing svg stuff, that is likely to change at some point when I get to writing that stuff. Most all I have wrapped/snippetized is wxPy base dc stuff for drawing functions and some coloring stuff.

... Which IDE are you using? Sounds like maybe PyCharm...?
Sadly for me PyCharm is very slow working with stuff, hard to get into for beginners, and most importantly isn't written in python.

@kdschlosser
Copy link
Contributor Author

actually there is quite a bit of PyCharm written in python.. The bits that deal with the stub files is written in python. The issue I have with PyCharm is it doesn't do well with large projects.. 150K lines and up. or a single file that has say... 30K lines of code in it.

Other then that it works pretty well. The default JVM settings are for the birds.. those need to be changed right out of the gate.. once that is done you will find that PyCharm runs pretty decent. it is also pretty simple to use. You will want to install their version of the JVM "OpenJDK by JetBrains. It will give you the option to use that when you install PyCharm. then go into the help menu and click on "Edit Custom VM Options" It will probably tell you that it needs to make a file. say yes.. and paste in the code below, the only 2 options that you will need to change are -Xms2g and -Xmx12g

this is where you set the memory to allocate to PyCharm.. the -Xms2g is the smallest size the heap will be. 2 gig in my case.
and you guessed it the other option is the largest the heap can be. for most projects 2 gig and 4 gig will work without issue. if you notice lagging in the GUI then you need to up the max heap allocation or close some of the open windows.

-server
-Xms2g
-Xmx12g
-XX:NewRatio=3
-Xss16m
-XX:+UseConcMarkSweepGC
-XX:+CMSParallelRemarkEnabled
-XX:ConcGCThreads=4
-XX:ReservedCodeCacheSize=240m
-XX:+AlwaysPreTouch
-XX:+TieredCompilation
-XX:+UseCompressedOops
-XX:SoftRefLRUPolicyMSPerMB=50
-Dsun.io.useCanonCaches=false
-Djava.net.preferIPv4Stack=true
-ea

I like the type hinting and the autocomplete. But when there is voodoo magic code involved unless there is a stub file specifically written to handle it there will be no type hinting or autocomplete.. and if you are going to go through the work of writing a stub file.. why not just write the code in a manner that will provide the type hinting right out of the gate...

I think the intention of a stub file is for extension libraries. (pyd files) because there is no way to sneak a peek at what's inside in order to provide the information needed, stub files can be used in order to achieve this. There is really no reason as to why a stub file should need to be created for python code.

and the issue with an IDE being written in python is the speed of Python. I have tried Spyder, It really doesn't play nice with large projects. Worse then PyCharm actually. The other thing is PyCharm is a "full featured" IDE and the code inspections for the most part work properly unlike Visual Studio's Python integration.

I am not an advocate for PyCharm. It has some really big flaws and problems, I would love to change to a different IDE. I am unable to find anything that is close to providing the same features and functionality that PyCharm has.

I'm 45 years old. The gray matter is not what it used to be.. so type hinting and also autocomplete are must have features. code inspections are also a must have. I can't keep track of what syntax works with that version of python. or what is depreciated and what is not.. Far easier to have the IDE inform me of these things before run time.

@RobinD42
Copy link
Member

I am unable to find anything that is close to providing the same features and functionality that PyCharm has.

VS Studio gets very close for most features that were important to me in PyCharm, exceeds it in a few features too. I recently had to fire up PyCharm while working on a hairy problem, but that was the first time in probably a year. Also, VS Studio is a lot less resource hungry. And, as an added bonus: https://marketplace.visualstudio.com/items?itemName=RobinD42.robins-blue-theme 😉

@kdschlosser
Copy link
Contributor Author

It has been over a year since I have tried the Visual Studio Python extension.. The last time I had tried it it would should that a variable did not exist if the variable was in the parent scope.

some_variable = 'whatever'

def go():
    print(some_variable)

it would say that some_variable in the function go didn't exist.. when we know it does.. There were other issues similar to that when dealing with imports. I do not remember if it handled type hinting either. It could now.. It may be the time to have a look at it again.

PyCharm does have a pretty large memory leak in it's code inspections. that is the reason why it cannot handle large files. The leak occurs because of the creation of inspection objects over and over again that are the same error but in different parts of the code. If the same error is repetitive for some reason ram disappears FAST. 70K line file. my server which has 128GB of ram I set the heap size to 100GB and I ran out of heap inspecting the code in that file and it crashed PyCharm..
the same problem exists from 2017 to current. I have not tried an earlier version of PyCharm.

I do know that VS has a far smaller memory and processor footprint then PyCharm does. Now on the flip side the disk footprint of VS compared to PyCharm is massive.. That is strange actually.. I opened the exact same project and took the memor samples while a code inspection of the whole project was running. The project has 750K lines of Python code.

  • VS:

    • disk footprint: 4.5GB
    • memory: 1.81GB
    • CPU: 19%
  • PyCharm:

    • disk footprint: 0.9GB
    • memory: 12GB (it needed more and crashed PyCharm)
    • CPU 100%

I just gave the python extension for VS another go. It does appear they have fixed the variable issue i outlined above.. also as you can see above it is much lighter on the resources. but the UI does the same thing that PyCharm does when dealing with large files/projects.. It studders and becomes a pain to use. I would have to use it more to see if this goes away once it finishes up with the inspection.. PyCharm will rescan the whole file if you make a change and that causes it to keep on having issues. I do not know if VS does the same or not. I am going to use it for a while and see if I encounter the same effects.. I already found one thing that I do not like/does not work.. when I set the error window (inspections) to only do the inspections for the current file it doesn't. it still does the inspection for the whole project and also displays the results for the whole project. I may be doing something wrong i am going to have to mess around with it a bit more.

the theme is nice as well. it is a little to hard on my eyes with the blue.. But your point is correct about the code editor and it almost always being the same color as the rest of the UI.. It gets lost. I would probably use 45, 45, 45 for the editor and 60, 60, 60 for the rest of the UI..I think that might be enough of a shade difference to make the editor different from the rest of the UI while retaining the dark to reduce the eye strain. I have photophobia so I like to have a UI stay pretty dark in color for the majority of it.

@kdschlosser
Copy link
Contributor Author

Oh and the other thing I just noticed is that you are using Visual Studio Code.. and not Visual Studio. I did not know there is a python extension for VSCode. is it the same extension that is used for VS?

@RobinD42
Copy link
Member

I'm not sure. I know the debugger backend is shared between them, I expect there's some other overlap as well.

@kdschlosser
Copy link
Contributor Author

Visual Studio and Visual Studio code end up with GUI hiccups just like PyCharm does. They don't crash but the studdering of the GUI make it almost unusable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants