'How to make marquee on tkinter in label?

I have this source code:

from Tkinter import *
import tkMessageBox
import time
class Window(Tk):
    def __init__(self,parent):
        Tk.__init__(self,parent)
        self.parent = parent
        self.initialize()


    def initialize(self):
        self.geometry('450x250+0+0')
        self.configure(background="#379DDB")
        self.title('Konversi Bilangan')
        **self.label = Label(self, text='Konversi Dari',font=('times',24,'italic'),bg="#379DDB")**
        self.label.pack()
        self.tombol=Button(self, text='Biner',font=(18),borderwidth='3px',width=10,command=self.OnButtonClick1,bg="#69ABD3")
        self.tombol.pack(side=TOP)
        self.tombol2=Button(self, text='Desimal',font=(18),borderwidth='3px' ,width=10, command=self.OnButtonClick2,bg="#69ABD3")
        self.tombol2.pack(side=TOP)
        self.tombol3=Button(self, text='Oktal',font=(18),borderwidth='3px' ,width=10,command=self.OnButtonClick3,bg="#69ABD3")
        self.tombol3.pack()
        self.tombol4=Button(self, text='Hexa',font=(18),borderwidth='3px' ,width=10,command=self.OnButtonClick4,bg="#69ABD3")
        self.tombol4.pack()
        self.tombol5=Button(self,text='Quit',font=(18),borderwidth='3px' ,width=10, fg='red', command= self.quit,bg="#69ABD3")
        self.tombol5.pack()

How to make marquee from that I bold? If it is not possible how to make marquee like vb in tkinter?



Solution 1:[1]

The pattern for doing animation in tkinter is to use after to schedule one frame of the animation at a time. It looks something like this, where fps is defined as the number of frames you want per second, and widget is a tkinter widget:

def animate():
    <draw one frame of animation>
    widget.after(int(1000/fps), animate)

As for a marquee, one of the easiest solutions is to use a canvas, since it has a convenient move method that can be used to move text from right to left.

Here's an example:

import tkinter as tk

class Marquee(tk.Canvas):
    def __init__(self, parent, text, margin=2, borderwidth=1, relief='flat', fps=30):
        super().__init__(parent, borderwidth=borderwidth, relief=relief)

        self.fps = fps
        
        # start by drawing the text off screen, then asking the canvas
        # how much space we need. Use that to compute the initial size
        # of the canvas. 
        text = self.create_text(0, -1000, text=text, anchor="w", tags=("text",))
        (x0, y0, x1, y1) = self.bbox("text")
        width = (x1 - x0) + (2*margin) + (2*borderwidth)
        height = (y1 - y0) + (2*margin) + (2*borderwidth)
        self.configure(width=width, height=height)

        # start the animation
        self.animate()

    def animate(self):
        (x0, y0, x1, y1) = self.bbox("text")
        if x1 < 0 or y0 < 0:
            # everything is off the screen; reset the X
            # to be just past the right margin
            x0 = self.winfo_width()
            y0 = int(self.winfo_height()/2)
            self.coords("text", x0, y0)
        else:
            self.move("text", -1, 0)

        # do again in a few milliseconds
        self.after_id = self.after(int(1000/self.fps), self.animate)
        
root = tk.Tk()
marquee = Marquee(root, text="Hello, world", borderwidth=1, relief="sunken")
marquee.pack(side="top", fill="x", pady=20)

root.mainloop()

Solution 2:[2]

This is going to be hard to integrate because tkinter doesn't "play nice" with infinite loops.

The below program written with assistance from here creates a marquee, this is simply an example to prove this can be done and is a poor way of doing this.

from tkinter import *

root = Tk()

text="Lorem Ipsum"

text = (' '*20) + text + (' '*20)

marquee = Text(root, height=1, width=20)
marquee.pack()

i = 0

def command(x, i):
    marquee.insert("1.1", x)
    if i == len(text):
        i = 0
    else:
        i = i+1
    root.after(100, lambda:command(text[i:i+20], i))

button = Button(root, text="Start", command=lambda: command(text[i:i+20], i))
button.pack()

root.mainloop()

This also uses the Text widget instead of the Label widget, mostly because it's simpler to do this way.


To start it on program launch, simply adjust it to the below:

from tkinter import *

root = Tk()

text="Lorem Ipsum"

text = (' '*20) + text + (' '*20)

marquee = Text(root, height=1, width=20)
marquee.pack()

i = 0

def command(x, i):
    marquee.insert("1.1", x)
    if i == len(text):
        i = 0
    else:
        i = i+1
    root.after(100, lambda:command(text[i:i+20], i))

command(text[i:i+20], i)

root.mainloop()

Solution 3:[3]

I have no experience in Tkinter but I hope this will help you to understand to implement this in your code. Thanks!

import sys
import time


def main():
    program = animate()
    program.data = input("Enter string : ") + " "
    program.width = int(input("Enter width : "))
    program.animate()


class animate:
    def __init__(self):
        self.data = ""
        self.width = 0

    def animate(self):
        try:
            while True:
                for x in range(0, self.width):
                    time.sleep(0.1)
                    msg = "\r{}{}".format(" " * x, self.data)
                    sys.stdout.write(msg)
                    sys.stdout.flush()

                for x in range(self.width, 0, -1):
                    time.sleep(0.1)
                    msg = "\r{}{}".format(" " * x, self.data)
                    sys.stdout.write(msg)
                    sys.stdout.flush()
        except KeyboardInterrupt:
            print("Exiting")


if __name__ == "__main__":
    main()

Solution 4:[4]

Hello I do not know if you can use this code to make an imitation of the marquee, it should be noted that it is for a window of 800 x 600 if they are other measures just have to change the 805 by the measure of the width of your window.

class MarqueeAnimation:

  def __init__(self,master=None,text="",eje_x = 0,velocity = 0):
      self.root = master
      self.marqueetext = text
      self.posx = eje_x
      self.velocity = velocity
      #Marquee Label
      self.lbl = Label(self.root,text=self.marqueetext,font=(12))
      self.reqposx = self.lbl.winfo_reqwidth() * -1
      self.lbl.place(x=0,y=250)

  def StarAnimation(self):
      try:
         self.posx += 1
         self.lbl.update()
         self.lbl.place(x=self.posx,y=265)
         if self.posx == 805:
            self.posx = self.reqposx
         self.animation = self.root.after(10,self.StarAnimation)
      except:
         pass
  
   def ChangeAnimation(self,newtext=""):
      self.lbl.configure(text=newtext)
      self.lbl.update_idletasks()
      self.reqposx = self.lbl.winfo_reqwidth() * -1

   def StopAnimation(self):
      self.root.after_cancel(self.animation)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2
Solution 3 Ali
Solution 4 Chema