Search code examples
pythontkinterplotcanvassurface

Is it possible to maintain the canvas background color while displaying a plot object on it?


I have the following code which generates and 3D surface plot:

import numpy as np
import matplotlib.pyplot as plt

# Creating a figure object
surf_3D = plt.figure()

# Creating a axes object
axes_3d = plt.axes(projection = "3d")

# Populating X and y
x_demo3d = np.arange(-5,5,0.1)
y_demo3d = np.arange(-5,5,0.1)

# Creating Mesh with newly generated numbers
X3,Y3 = np.meshgrid(x_demo3d, y_demo3d)

# Populating Z with sin and cos function
Z3 = np.sin(X3) * np.cos(Y3)

# Adding 
axes_3d.plot_surface(X3, Y3, Z3, cmap = "plasma")

# Making the panes transparent
axes_3d.xaxis.set_pane_color((1.0, 1.0, 1.0, 0.0))
axes_3d.yaxis.set_pane_color((1.0, 1.0, 1.0, 0.0))
axes_3d.zaxis.set_pane_color((1.0, 1.0, 1.0, 0.0))

# Hiding the axes ticks
axes_3d.set_xticks([])
axes_3d.set_yticks([])
axes_3d.set_zticks([])

# Displaying the figure object
surf_3D.show()

The Output is the following:

enter image description here

How can I change the Canvas background after I place the figure on it? As you can see I have defined the canvas width and height with a bg color. But apparently, my figure takes all the canva's space. Is it possible to display the background color of the unoccupied canvas space?

import numpy as np
import matplotlib.pyplot as plt
from tkinter import *
from matplotlib.backends.backend_tkagg import (
     FigureCanvasTkAgg, NavigationToolbar2Tk)


class Program_Class:
    
    def __init__(self, master):

        # Main Window parameters
        Main.resizable(0,0)
        Main.geometry("900x550")
        Main.title("Main")

        # Creating a figure object
        surf_3D = plt.figure(figsize=(2,2))

        # Creating axes object
        axes_3d = plt.axes(projection = "3d")

        # Populating with x and y list variables
        x = np.arange(-5,5,0.1)
        y = np.arange(-5,5,0.1)

        # Creating Mesh and rewriting list variables x and y
        x, y = np.meshgrid(x, y)

        # Populating z with sin and cos function
        z = np.sin(x) * np.cos(y)

        # Creating the surface 3D plot
        axes_3d.plot_surface(x, y, z, cmap = "plasma")

        # Making the panes transparent
        axes_3d.xaxis.set_pane_color((1.0, 1.0, 1.0, 0.0))
        axes_3d.yaxis.set_pane_color((1.0, 1.0, 1.0, 0.0))
        axes_3d.zaxis.set_pane_color((1.0, 1.0, 1.0, 0.0))

        # Hiding the axes ticks
        axes_3d.set_xticks([])
        axes_3d.set_yticks([])
        axes_3d.set_zticks([])

        # My attempt to draw the canvas with the surf_3D figure object
        # Canvas background color should be dark red (139, 0, 0)
        Canvas_demo3d = Canvas(Main, width=300, height =200, borderwidth=0, highlightthickness=0, 
                                    bg='#%02x%02x%02x' % (139, 0, 0))
        Canvas_demo3d = FigureCanvasTkAgg(surf_3D, master=Main)
        Canvas_demo3d.get_tk_widget().place(x=300,y=71)
        Canvas_demo3d.draw()



Main = Tk()
Program_Class(Main)
Main.mainloop()

Here is the class output:

enter image description here

Any help, will be appreciated.


Solution

  • Note that Canvas_demo3d = Canvas(...) is useless because it is override by the line Canvas_demo3d = FigureCanvasTkAgg(...).

    You can set the background color of the canvas by:

    color = '#%02x%02x%02x' % (139, 0, 0)
    Canvas_demo3d.get_tk_widget().config(bg=color)
    

    However in order to see the canvas background color, you need to make the plot background transparent:

    transparent = (0, 0, 0, 0)
    
    # Creating a figure object
    surf_3D = plt.figure(figsize=(2,2), facecolor=transparent)
    
    # Creating axes object
    axes_3d = plt.axes(projection="3d", facecolor=transparent)
    

    Result:

    enter image description here