使用鼠标在 python tkinter 画布上绘制并获取指向列表的点?

Posted

技术标签:

【中文标题】使用鼠标在 python tkinter 画布上绘制并获取指向列表的点?【英文标题】:Draw on python tkinter canvas using mouse and obtain points to a list? 【发布时间】:2017-03-29 00:06:36 【问题描述】:

我正在使用 tkinter 开发 Python 应用程序。我想做的是在画布坐标上绘制,这些点将被记录到一个列表中,以便我稍后进行计算。 如果不可能,您会推荐任何其他可以做到这一点的工具或 GUI 平台吗?

编辑:到目前为止,我所拥有的是一个可以从列表中获取点并在画布上绘制的应用程序。我也想要相反的工作方式。

from tkinter import *
from tkinter.filedialog import askopenfilename
from tkinter.messagebox import showerror
from tkinter import ttk
import tkinter
import threading

another_points = []

class Waveform(Frame):
   def __init__(self, master):
      ttk.Frame.__init__(self, master)
      self.master = master

      self.points = [10, 20, 30]
      self.create_widget()

   def create_widget(self):

      self.LoadFrame = ttk.LabelFrame(self.master, text = "Load")
      self.LoadFrame.pack(side = "left", padx = 10, pady = 10)
      self.PlotFrame()

      self.anotherFrame = ttk.LabelFrame(self.LoadFrame, text = "Browse")
      self.anotherFrame.pack(fill = "both", padx = 10, pady = 10)
      self.OpenFileButton = ttk.Button(self.anotherFrame, text = "Browse", command = self.load_file)
      self.OpenFileButton.grid(row = 0, column = 0)

   def load_file(self):
      fname = askopenfilename(filetypes = (("Text files", "*.txt"), ("All files", "*.*")))
      another_points[:] = []
      self.points[:] = []
      if fname:
         try:
            print (fname)
            with open(fname) as f:
               for line in f:
                  another_points.append(float(line.rstrip()))

            self.points = another_points

         except:
            print ("Error")
         return


   def PlotFrame(self):
      self.PlotFrame = ttk.LabelFrame(self.master, text = "X/Y Coordinates")
      self.PlotFrame.pack(side = LEFT, padx = 10, pady = 10)

      self.width = 400
      self.height = 350
      self.pressure = 75
      self.x_increment = 1
      self.x_factor = 0.04
      self.y_amplitude = 80


      def draw():
         self.GraphFrame.delete(self.sin_line)
         self.xy1 = []
         self.xy2 = self.points
         for x in range(len(self.xy2)):
            self.xy1.append(x + 25)
            self.xy1.append(self.height - self.xy2[x])

         self.sin_line = self.GraphFrame.create_line(self.xy1, fill = "yellow")

      self.UpdateButton = ttk.Button(self.PlotFrame, text = "Update", command = draw)
      self.UpdateButton.pack()

      self.GraphFrame = Canvas(self.PlotFrame, width = self.width, height = self.height, bg = "black")

      self.GraphFrame.pack()
      self.original = []

      self.mock = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
      for x in range(len(self.mock)):
         self.original.append((x + 5)*10)
         self.original.append((self.height - self.mock[x])/100)

      self.sin_line = self.GraphFrame.create_line(self.original, fill = "yellow")


if __name__ == "__main__":
    master = Tk()
    Waveform(master).pack(side = "top", fill ="both", expand = True)
    master.mainloop()

-谢谢

【问题讨论】:

到目前为止你尝试过什么?现在,这个问题只是“为我写代码”。 此代码不会运行。 AttributeError: 'Waveform' object has no attribute 'CustomizedWaveformes' 您可以为鼠标移动和单击鼠标时添加绑定。您可以使用为绑定函数提供的信息来绘制线条。 @BryanOakley:代码已修复。谢谢你指出。你能举一个简单的例子吗?我也一定会试一试的。谢谢! 【参考方案1】:

开始

import tkinter as tk
root = tk.Tk()
def mmove(event):
    print(event.x, event.y)
root.bind('<Motion>', mmove)
root.mainloop()

然后根据需要进行详细说明。将运动绑定到画布、在画布上绘制点、将对附加到列表、绑定点击替代或附加、过滤点流等。

【讨论】:

【参考方案2】:

感谢特里提供了非常有用的提示。我设法让它工作。请注意,由于记录了冗余点,这不是最佳解决方案。这就是为什么我不得不把它弹出很多。但它至少有效。

import tkinter as tk

class ExampleApp(tk.Tk):
    def __init__(self):
        tk.Tk.__init__(self)
        self.previous_x = self.previous_y = 0
        self.x = self.y = 0
        self.points_recorded = []
        self.canvas = tk.Canvas(self, width=400, height=400, bg = "black", cursor="cross")
        self.canvas.pack(side="top", fill="both", expand=True)
        self.button_print = tk.Button(self, text = "Display points", command = self.print_points)
        self.button_print.pack(side="top", fill="both", expand=True)
        self.button_clear = tk.Button(self, text = "Clear", command = self.clear_all)
        self.button_clear.pack(side="top", fill="both", expand=True)
        self.canvas.bind("<Motion>", self.tell_me_where_you_are)
        self.canvas.bind("<B1-Motion>", self.draw_from_where_you_are)

    def clear_all(self):
        self.canvas.delete("all")

    def print_points(self):
        if self.points_recorded:
            self.points_recorded.pop()
            self.points_recorded.pop()
        self.canvas.create_line(self.points_recorded, fill = "yellow")
        self.points_recorded[:] = []

    def tell_me_where_you_are(self, event):
        self.previous_x = event.x
        self.previous_y = event.y

    def draw_from_where_you_are(self, event):
        if self.points_recorded:
            self.points_recorded.pop()
            self.points_recorded.pop()

        self.x = event.x
        self.y = event.y
        self.canvas.create_line(self.previous_x, self.previous_y, 
                                self.x, self.y,fill="yellow")
        self.points_recorded.append(self.previous_x)
        self.points_recorded.append(self.previous_y)
        self.points_recorded.append(self.x)     
        self.points_recorded.append(self.x)        
        self.previous_x = self.x
        self.previous_y = self.y

if __name__ == "__main__":
    app = ExampleApp()
    app.mainloop()

【讨论】:

你能告诉我如何将它导出为图像吗?顺便说一句,这比其他答案更好,谢谢.... 我以前从未这样做过。所以,我在另一个 SO 帖子上找到了这个。希望能帮助到你!!! ***.com/questions/9886274/…

以上是关于使用鼠标在 python tkinter 画布上绘制并获取指向列表的点?的主要内容,如果未能解决你的问题,请参考以下文章

matplotlib 在 tkinter 画布中的缩放功能

tkinter 中的 Python 3 unicode 编解码器错误绑定鼠标滚轮

Python,Tkinter:如何在可滚动画布上获取坐标

如何使用 PYTHON 的“tkinter”模块在画布上显示图像,特别适用于 linux?

Python Tkinter - 保存画布 - tkinter 崩溃

使用 Tkinter 和 Python 在 Mac OS X 中进行惯性滚动