如何以交互方式将点绘制到 PyQT 中 QLabel 上的 Pixmap 上

发布于 2024-11-13 10:08:07 字数 371 浏览 2 评论 0原文

我正在构建一个小型 GUI 界面,并且有一个 QLabel,它通过将图像设置为像素图来将图像从目录绘制到自身上。我希望用户能够交互地单击此像素图上的点,并在单击的位置出现一个小的绿色“x”。我尝试重新实现 PaintEvent 方法,但这根本不是我想要的功能。每当有理由在 QLabel 上绘画时,paintEvent 就会被调用...而我想单独保留基础绘图(图像),只需将点放置在已绘制图像的顶部。最终,我希望用户能够使用第三方跟踪算法通过一系列图像交互式地跟踪这些点。因此,我需要让用户能够移动点、删除点、添加点和修改它们,而无需重新绘制它们后面的图像。网上有几个关于简单绘制点的教程,但它们都涉及重新实现paintEvent方法,然后将mouseEvent连接到paintEvent。我正在努力避免这种情况。有什么建议吗?

I am building a small GUI interface and I have a QLabel that draws images from a directory onto itself by setting them as the pixmap. I want the user to be able to interactively click points on this pixmap and have a small green 'x' appear at the clicked locations. I have tried re-implementing the paintEvent method, but this is not the functionality I want at all. paintEvent is what gets called every time there is a reason to paint on the QLabel... whereas I want to leave the base drawing (the image) alone and simply place points on top of the already-drawn image. Eventually, I am going to want the user to be able to interactively track these points through a sequence of images, using third-party tracking algorithms. Thus, I need the capability of having the user move points around, remove points, add points, and modify them without needing to re-draw the image behind them. There are several tutorials online about simply drawing points, but they all involve re-implementing the paintEvent method and then connecting a mouseEvent to the paintEvent. I am trying to specifically avoid this. Any suggestions?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

红ご颜醉 2024-11-20 10:08:07

您实际上确实想使用 paintEvent() 覆盖。即使您确实只想在图像上绘制内容,如果您删除或移动在图像上绘制的内容,则小部件仍然需要能够重绘图像的某些部分,并且这发生在 paintEvent().如果你想在渲染中添加一些东西,你也必须这样做。

paintEvent()视为绘制widget-that's-visible-Event()的整个部分。如果您使用的是QLabel的子类,那么您的重写应该调用QLabel::paintEvent(e),然后调用您的东西。

听起来您将维护一个点列表,因此您的 PaintEvent() 部分应该以您需要的方式绘制所有点。

您的鼠标事件应该对点列表执行某些操作(例如添加点或移动点),然后调用 update() 这将触发对 paintEvent() 的调用这将使用背景图像和更新的点重新绘制整个小部件。不应将鼠标事件连接到 paintEvent() 或尝试在 paintEvent() 内跟踪或处理鼠标事件。

要记住的主要事情是,鼠标事件将修改您的“模型”,并且只要模型发生变化,paintEvent()就会绘制整个模型。即使有一个抽象/功能只需要你绘制新的东西或改变的东西,在幕后,很多东西仍然需要擦除和重新绘制。

这可以通过使用传递给 paintEvent() 的事件对象中的区域信息来优化,但这通常是不必要的。

您可以在 an 中查看有点类似的示例回答我提供的另一个问题,尽管它可能与您已经看到的其他示例没有什么不同。不幸的是它不在Python 中。

您可以对内存中的图像进行所有渲染,然后仅更新标签显示的图像,但 paintEvent() 覆盖是更好的选择。

You actually do want to use a paintEvent() override. Even if you do want to only draw things over an image, the widget still needs to be able to redraw portions of the image if you remove or move things that are drawn over it and this happens in the paintEvent(). If you want to add things to the rendering, that's where you have to do it too.

Think of the paintEvent() as draw-the-entire-part-of-the-widget-that's-visible-Event(). If you are using a subclass of QLabel, then your override should call QLabel::paintEvent(e) and then your stuff.

It sounds like you will be maintaining a list of points so your part of the paintEvent() should draw all of your points in the manner you require.

Your mouse events should do something to your list of points (like add a point or move a point) and then call update() which will trigger a call to paintEvent() which will redraw the entire widget with the background image and your updated points. There should be no connecting of mouse events to paintEvent() or messing around with trying to track or handle mouse events inside paintEvent().

The main thing to remember is that mouse events will modify your "model" and the paintEvent() will draw the entire model whenever it changes. Even if there was an abstraction/function that only required you to draw new things or things that changed, under the covers, lots of stuff still needs to be erased and redrawn.

This can be optimized by making use of the region information in the event object passed into paintEvent() but this usually isn't necessary.

You can look at a somewhat similar example in an answer to another question that I provided although it may not be that different from other examples you've already seen. It isn't in Python unfortunately.

You could do all of your rendering to an in-memory image and then just update the image that the label is displaying but the paintEvent() override is a better option.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文