Fill space between Tkinter canvas objects with color

Python 2.7.8, Windows 7

I subclassed the Tkinter canvas widget and I added a new method to create a rounded rectangle.

import Tkinter as tk

class MyCanvas(tk.Canvas):
    def __init__(self, *args, **kwargs):
        tk.Canvas.__init__(self, *args, **kwargs)

    def create_rounded(self, x1, y1, x2, y2, r):
        self.create_arc(x1, y1, x1+r, y1+r, start=90, extent=90, style=tk.ARC)
        self.create_arc(x2-r, y1, x2, y1+r, start=0, extent=90, style=tk.ARC)
        self.create_arc(x1, y2-r, x1+r, y2, start=180, extent=90, style=tk.ARC)
        self.create_arc(x2-r, y2-r, x2, y2, start=270, extent=90, style=tk.ARC)
        self.create_line(x1+r/2, y1, x2-r/2, y1)
        self.create_line(x1, y1+r/2, x1, y2-r/2)
        self.create_line(x1+r/2, y2, x2-r/2, y2)
        self.create_line(x2, y1+r/2, x2, y2-r/2)

      

I want to fill a rounded rectangle that I created with one color. How should I do it.

This is what I get when I run it with some parameters

This is what I want

+3


source to share


2 answers


Instead of drawing an outline and trying to fill the interior with red, why not create a rounded rectangle from existing canvas objects? Four round pieces of pie for the corners and two rectangles for a cross? Something like that:

import Tkinter as tk

class MyCanvas(tk.Canvas):
    def __init__(self, *args, **kwargs):
        tk.Canvas.__init__(self, *args, **kwargs)

    def create_rounded(self, x1, y1, x2, y2, r):
        self.create_arc(x1, y1, x1+r, y1+r, start=90, extent=90, style=tk.PIESLICE, fill = "red")
        self.create_arc(x2-r, y1, x2, y1+r, start=0, extent=90, style=tk.PIESLICE, fill = "red")
        self.create_arc(x1, y2-r, x1+r, y2, start=180, extent=90, style=tk.PIESLICE, fill = "red")
        self.create_arc(x2-r, y2-r, x2, y2, start=270, extent=90, style=tk.PIESLICE, fill = "red")
        self.create_rectangle(x1+r/2, y1-r/2, x2-r/2, y2+r/2, fill = "red")
        self.create_rectangle(x1, y1, x2, y2, fill="red")

      



I haven't tested this, so I may have misunderstood the coordinates or put in a syntax error, but I think you can understand what I mean.

+2


source


I modified the suggestion from saulspatz to correct the coordinates as follows. Unfortunately it draws lines for arcs and rectangles. I added width = 0 but for some reason I can still see some lines. One option might be to draw these lines with a fill color line. Seems a little tedious.

class Rounded():
def __init__(self, canvas, x1, y1, x2, y2, r, color='red'):
    self.canvas = canvas  
    self.canvas.create_arc(x1, y1, x1+r, y1+r, start=90, extent=90, style=TK.PIESLICE, fill = color, width=0)
    self.canvas.create_arc(x2-r, y1, x2, y1+r, start=0, extent=90, style=TK.PIESLICE, fill = color, width=0)
    self.canvas.create_arc(x1, y2-r, x1+r, y2, start=180, extent=90, style=TK.PIESLICE, fill = color, width=0)
    self.canvas.create_arc(x2-r, y2-r, x2, y2, start=270, extent=90, style=TK.PIESLICE, fill = color, width=0)
    self.canvas.create_rectangle(x1+r/2, y1, x2-r/2, y2, fill=color, width=0)
    self.canvas.create_rectangle(x1, y1+r/2, x2, y2-r/2, fill=color, width=0)

      

Then I thought about how to draw horizontal lines. The advantage here is that you can implement a gradient on an object. The code is here: -

    def using_lines(self):
    # Try to draw rounded rectangle using lines!
    xx = [3,5,6,7,8,8,9,9,9,10]
    zz = [10,9,9,9,8,8,7,6,5,3]
    x = 10
    y = 150
    width = 100
    height = 30
    radius = 10
    #self.canvas.create_rectangle(x,y,x+width, y+height)
    r_width = width - 2*radius
    left = x + radius
    right = x + width - radius
    for r in range(radius):
        self.canvas.create_line(left, y+r, right, y+r, fill='green')
        left = x + radius - xx[r] 
        right = x + width - radius + xx[r]
    for r in range(height - 2 * r):
        self.canvas.create_line(x, y+radius+r, x + width, y+radius+r, fill='green')
    left = x
    right = x + width
    top = y + height - radius
    for r in range(radius):
        self.canvas.create_line(left, top+r, right, top+r, fill='green')
        left = x + (radius - zz[r])
        right = x + width - radius + zz[r]

      



I guessed that the numbers draw lines of different lengths to fit the arc, but I'm sure a calculation could be worked out.

Strings can be given the same tag, so it's easy to change the whole color. To add a border, I also added code from Charlito, although it didn't exactly match the lines I was drawing.

Sorry for the rough code, I just wanted to take a quick look at the proof of concept before going any further.

If speed is not important, the length of the line can be calculated. For standard buttons and labels, they can be predefined to correspond to a fixed radius. I am interested in creating buttons and shortcuts from these ideas.

0


source







All Articles