Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python Tkinter puzzling result

Tags:

python

tkinter

I'm new at Python, trying to fill a canvas with random pixels. Could someone tell me why it's doing horizontal stripes?

import tkinter
from random  import randint
from binascii import  hexlify
class App:
    def __init__(self, t):
        x=200
        y=200
        xy=x*y
        b=b'#000000 '
        s=bytearray(b*xy)
        c = tkinter.Canvas(t, width=x, height=y);
        self.i = tkinter.PhotoImage(width=x,height=y)
        for k in range (0,8*xy,8):
          s[k+1:k+7]=hexlify(bytes([randint(0,255) for i in range(3)]))
        print (s[:100])      
        pixels=s.decode("ascii")                                        
        self.i.put(pixels,(0,0,x,y))
        print (len(s),xy*8)
        c.create_image(0, 0, image = self.i, anchor=tkinter.NW)
        c.pack()

t = tkinter.Tk()
a = App(t)    
t.mainloop()

Which gives e.g.:

Window full of colourful stripes

like image 950
Antoni Gual Via Avatar asked Jul 23 '26 17:07

Antoni Gual Via


1 Answers

I would suggest you do something a bit simpler, e.g.:

class App:

    def __init__(self, t, w=200, h=200):
        self.image = tkinter.PhotoImage(width=w, height=h)  # create empty image
        for x in range(w):  # iterate over width
            for y in range(h):  # and height
                rgb = [randint(0, 255) for _ in range(3)]  # generate one pixel
                self.image.put("#{:02x}{:02x}{:02x}".format(*rgb), (y, x))  # add pixel
        c = tkinter.Canvas(t, width=w, height=h);
        c.create_image(0, 0, image=self.image, anchor=tkinter.NW)
        c.pack()

This is much easier to understand, and gives me:

Windowful of fuzzy colours

which I suspect is what you were hoping for.


To reduce the number of image.puts, note that the format for data is (for a 2x2 black image):

'{#000000 #000000} {#000000 #000000}'

You could therefore use:

self.image = tkinter.PhotoImage(width=w, height=h)
lines = []
for _ in range(h):
    line = []
    for _ in range(w):
        rgb = [randint(0, 255) for _ in range(3)]
        line.append("#{:02x}{:02x}{:02x}".format(*rgb))
    lines.append('{{{}}}'.format(' '.join(line)))
self.image.put(' '.join(lines))

which only has one image.put (see e.g. Why is Photoimage put slow?) and gives a similar-looking image. Your image was stripy because it was interpreting each pixel colour as a line colour, as you hadn't included the '{' and '}' for each line.

like image 173
jonrsharpe Avatar answered Jul 26 '26 07:07

jonrsharpe



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!