【问题标题】:Create a clickable grid in python在python中创建一个可点击的网格
【发布时间】:2021-02-24 09:55:34
【问题描述】:

我是 python 新手,我需要一些帮助来启动我的应用程序。我想为我的硕士论文编写一个免费的开源应用程序,其目的是解决静态结构。

到目前为止,我有两个主要的 python 库:PyQt5(用于用户界面)和matplotlib(以便在解决结构后显示一些有用的图表)。

我需要一些功能来让用户“绘制”他们想要分析的结构。我曾想过(并尝试过)使用matplotlib 作为这个“抽屉”,但我认为我不应该走这条路,因为这不是库设计的目的。我在下面解释所需的功能。

静态结构是通过“节点”和“条”定义的。我的愿景是,当开始一个项目时,会出现一个带有可测量网格的画布。在这里,单击一个按钮,用户可以在画布中单击以创建一个可以由圆形或其他形式表示的“节点”。在用户决定删除它之前,该节点将保留在原位。

我附上image,目的是澄清解释。

是否有任何提供此功能的软件包?或者有人知道如何实现这个功能?

【问题讨论】:

  • 我确信你可以通过 matplotlib 的 f.canvas.mpl_connect 功能实现这一点......我会尝试给你一个工作示例,但你可能需要 1-2 个陷阱考虑一下你是否对 python 完全陌生(比如可变和不可变对象等)

标签: python graphics grid structure clickable


【解决方案1】:

我试了一下,因为我很好奇自己需要付出多少努力才能将 matplotlib 变成一个简单的绘图工具...

这是一个工作(纯 matplotlib!)示例,您应该可以将其用作起点来做您想做的事情。

import matplotlib.pyplot as plt

f = plt.figure(figsize=(8, 8))
ax = f.add_subplot()

# initialize your grid
ax.set_xlim(0, 10)
ax.set_ylim(0, 10)
ax.xaxis.set_major_locator(plt.FixedLocator(range(10)))
ax.yaxis.set_major_locator(plt.FixedLocator(range(10)))
ax.grid()


# print some info text
t1 = ax.text(.5, .5,
"""LEFT-click to draw a line
RIGHT-click to remove the last point
MIDDLE-click to toggle 'snap-to-grid'""",
bbox=dict(facecolor='w',
          edgecolor='black',
          boxstyle='round, pad=1, rounding_size=1', pad=0))

t2 = ax.text(7, .5,
"""'snap-to-grid active!'""",
bbox=dict(facecolor='w',
          edgecolor='red',
          boxstyle='round, pad=1, rounding_size=1', pad=0))
t2.set_visible(False)


# draw initial lines that will be updated later
l, = ax.plot([], [], lw=2, marker='o', c='k')
p, = ax.plot([], [], lw=0, marker='.', c='r', alpha=0.25)
p_round, = ax.plot([], [], lw=0, marker='o', c='r')


# get a dict to store the values you need to change during runtime
retdict = dict(points=[],
               round_to_int=False)

# define what to do when a mouse-click event is happening
def on_click(event):
    if event.inaxes != ax:
        return
    if event.button == 1:  # (e.g. left-click)
        if retdict['round_to_int']:
            retdict['points'] += [[round(event.xdata), round(event.ydata)]]
        else:
            retdict['points'] += [[event.xdata, event.ydata]]
    elif event.button == 3:  # (e.g. right-click)
        if len(retdict['points']) >= 1:
            retdict['points'] = retdict['points'][:-1]
            plt.draw()

    elif event.button == 2:  # (e.g. middle-click)
        retdict['round_to_int'] = not retdict['round_to_int']
        if retdict['round_to_int']:
            t2.set_visible(True)
        else:
            t2.set_visible(False)
        plt.draw()

    if len(retdict['points']) > 0:
        l.set_visible(True)
        l.set_data(list(zip(*retdict['points'])))

        plt.draw()
    else:
        l.set_visible(False)


# define what to do when a motion-event is detected
def on_move(event):
    if event.inaxes != ax:
        return

    p.set_data(event.xdata, event.ydata)

    if retdict['round_to_int']:
        p_round.set_data(round(event.xdata), round(event.ydata))

    plt.draw()

# connect the callbacks to the figure
f.canvas.mpl_connect('button_press_event', on_click)
f.canvas.mpl_connect('motion_notify_event', on_move)

【讨论】:

  • 首先,非常感谢您的回答,我衷心感谢您为研究和编写代码所付出的努力。我试图运行它,但我收到一条错误消息:QApplication: invalid style override 'kvantum' passed, ignoring it。可用样式:Windows、Fusion。我认为这是一个 PyQt5 错误,我不确定为什么会在这里,因为代码中没有使用该库。我要做一项研究以找出答案。我只是想尽快感谢你。
  • 不客气 :-) 我从来没有听说过这个错误,是的......它似乎与你的 python 环境的设置方式有关......我已经在 windows 和 linux 的新环境中检查了脚本,它完成了它的工作......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-04-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多