0

Is it possible?

Just to place it anywhere onto the window and drag it anywhere I want it.

Here is an example of draggable item I am looking to achieve like from HTML (I know, it's got nothing to do with html): How TO - Create a Draggable HTML Element.

Here is an example of what I mean by a ruler. A ruler like this:

image showing horizontal and vertical rulers at top-left of a rectangle

It's only for display purposes and not calculating anything..

I'll be using Grid manager in this case.

I'll be happy to see any examples!

Hakws Eye
  • 3
  • 3
  • Yes, I think so. See the question [Drag and Drop widgets tkinter](https://stackoverflow.com/questions/37280004/drag-and-drop-widgets-tkinter). – martineau Oct 14 '19 at 19:19
  • As written, this question is just too broad. – Bryan Oakley Oct 14 '19 at 19:24
  • Hi, I'd be happy to see any examples.. – Hakws Eye Oct 14 '19 at 19:25
  • using `place()` you can put it whatever you want, dragging could be small problem but problem can be to create rules with lines and numbers and recalculate values on rules when they change position. You have to create rules from scratch. So it is broad problem. – furas Oct 14 '19 at 19:40
  • It's for display purposes only if that solves the small problem @furas? – Hakws Eye Oct 14 '19 at 19:44
  • displaying can be the bigest problem - there is no rulers in tkinter's standard module and I don't know any external modul for tkinter. You would have to create it from scratch. Maybe using canvas you could create own widget which display lines and numbers like in ruler but it still would need to code to recalculate it when you want to move content or rescale. – furas Oct 14 '19 at 20:06
  • lets say the rule was just a `.jpg' image? – Hakws Eye Oct 14 '19 at 20:07
  • you can use `PhotoImage` to load image (it may need `PIL` to load `.png` or `.jpg`) and widget `Label( ..., image=...)` to display it. Using `place()` you can put widget in any place. Or you can put this `photoimage` on `Canvas` - `canvas.create_image(position, image)` – furas Oct 14 '19 at 20:13
  • BTW: I found that PyQt has [ruler](https://indigo.re/qruler/) (maybe it has also in standard module beacause it has many widgets). If you use Linux then you can use `PyGTK` which also has ruler [https://www.tutorialspoint.com/pygtk/pygtk_quick_guide.htm](https://www.tutorialspoint.com/pygtk/pygtk_quick_guide.htm). But you can't use it with `tkinter`. – furas Oct 14 '19 at 20:14
  • very interesting... i'll see what I can do, I'll try keep you updated on here – Hakws Eye Oct 14 '19 at 20:16

1 Answers1

1

Standard module tkinter and ttk doesn't have rulers and I don't know any external module for tkinter which has rulers.


Using Canvas I can create widget which draws lines with numbers.

enter image description here

But it is still primitive widget which doesn't resize, doesn't scroll lines and numbers, doesn't rescale, and doesn't show mouse position.

EDIT: Now rules show mouse position using red lines. But if there is no Canvas then they have to know offset - how far they are from left top corner of window.

enter image description here

import tkinter as tk

class VRuler(tk.Canvas):
    '''Vertical Ruler'''

    def __init__(self, master, width, height, offset=0):
        super().__init__(master, width=width, height=height)
        self.offset = offset

        step = 10

        # start at `step` to skip line for `0`
        for y in range(step, height, step):
            if y % 50 == 0:
                # draw longer line with text
                self.create_line(0, y, 13, y, width=2)
                self.create_text(20, y, text=str(y), angle=90)
            else:
                self.create_line(2, y, 7, y)

        self.position = self.create_line(0, 0, 50, 0, fill='red', width=2)

    def set_mouse_position(self, y):
        y -= self.offset
        self.coords(self.position, 0, y, 50, y) 

class HRuler(tk.Canvas):
    '''Horizontal Ruler'''

    def __init__(self, master, width, height, offset=0):
        super().__init__(master, width=width, height=height)
        self.offset = offset

        step = 10

        # start at `step` to skip line for `0`
        for x in range(step, width, step):
            if x % 50 == 0:
                # draw longer line with text
                self.create_line(x, 0, x, 13, width=2)
                self.create_text(x, 20, text=str(x))
            else:
                self.create_line((x, 2), (x, 7))

        self.position = self.create_line(0, 0, 0, 50, fill='red', width=2)

    def set_mouse_position(self, x):
        x -= self.offset
        self.coords(self.position, x, 0, x, 50) 

def motion(event):
    x, y = event.x, event.y
    hr.set_mouse_position(x)
    vr.set_mouse_position(y)

def click(event):
    print(event.x, event.y)

root = tk.Tk()
root['bg'] = 'black'

vr = VRuler(root, 25, 250)#, offset=25)
vr.place(x=0, y=28)

hr = HRuler(root, 250, 25)#, offset=25)
hr.place(x=28, y=0)

c = tk.Canvas(root, width=250, height=250)
c.place(x=28, y=28)

#root.bind('<Motion>', motion) # it needs offset=28 if there is no Canvas
#root.bind('<Button-1>', click)
c.bind('<Motion>', motion)
c.bind('<Button-1>', click)

root.mainloop()
furas
  • 134,197
  • 12
  • 106
  • 148