我对Qt并不陌生,我正在尝试做一个程序,该程序我以前在tkinter中完成过,以学习如何使用它。我已经在Qt窗口中嵌入了FigureCanvasQtAgg。我已经在上面画了东西。现在,我想在此画布上用用户的鼠标单击绘制一个圆圈。
我在Tkinter上所做的就是使用
:self.canvas.get_tk_widget().create_oval()
在PySide2中是否有简单的方法来获得相同的结果?
这是我尝试过的更简单的代码:
from PySide2.QtWidgets import *
from PySide2.QtCore import *
from PySide2.QtGui import *
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
import matplotlib.pyplot as plt
import numpy as np
import sys
class MyPaintWidget(QWidget):
def __init__(self):
super().__init__()
layout_canvas = QVBoxLayout()
self.fig = plt.gcf()
plt.plot(np.cos([i for i in np.arange(0, 10, 0.1)]))
self.canvas = FigureCanvas(self.fig)
self.canvas.mpl_connect('button_press_event', self._on_left_click)
layout_canvas.addWidget(self.canvas)
self.setLayout(layout_canvas)
def _on_left_click(self, event):
print(event.xdata, event.ydata)
qp = QPainter()
qp.drawEllipse(QPointF(event.x, event.y), 10, 10)
qp.end()
self.canvas.draw()
if __name__=="__main__":
app = QApplication(sys.argv)
w = MyPaintWidget()
w.show()
app.exec_()
我在tkinter中所做的事情(当我在画布上单击时,确实会出现一个绿点):
import tkinter as tk
import tkinter.ttk as ttk
import numpy as np
import sys
from matplotlib.backends.backend_tkagg import (FigureCanvasTkAgg, NavigationToolbar2Tk)
from matplotlib.backend_bases import key_press_handler
import matplotlib.pyplot as plt
class MainFrame(ttk.Frame):
def __init__(self, master):
ttk.Frame.__init__(self, master)
self.master = master
self.fig = plt.gcf()
plt.plot(np.cos([i for i in np.arange(0, 10, 0.1)]))
self.canvas = FigureCanvasTkAgg(self.fig, master=self.master) # A tk.DrawingArea.
self.canvas.get_tk_widget().grid(row=0, column=0)
self.canvas.draw()
self.canvas.mpl_connect('button_press_event', self._on_left_click)
def _on_left_click(self, event):
self._add_point(event.x, event.y)
def _add_point(self, x, y):
self.canvas.get_tk_widget().create_oval(x - 4, self.canvas.get_tk_widget().winfo_height() - (y - 4), x + 4,
self.canvas.get_tk_widget().winfo_height() - (y + 4), fill='green')
if __name__=="__main__":
window = tk.Tk()
main_frame = MainFrame(window)
window.mainloop()
在QT中获得此结果的任何想法?谢谢!
答案 0 :(得分:1)
与tkinter不同,Qt并未实现诸如create_oval()之类的函数来制作圆圈,因此一种替代方法是使用matplotlib工具。
from PySide2 import QtCore, QtGui, QtWidgets
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
import matplotlib.pyplot as plt
import numpy as np
class MyPaintWidget(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.figure = plt.gcf()
self.canvas = FigureCanvas(self.figure)
self.canvas.mpl_connect("button_press_event", self._on_left_click)
self.axes = self.figure.add_subplot(111)
x = np.arange(0, 10, 0.1)
y = np.cos(x)
self.axes.plot(x, y)
layout_canvas = QtWidgets.QVBoxLayout(self)
layout_canvas.addWidget(self.canvas)
def _on_left_click(self, event):
self.axes.scatter(event.xdata, event.ydata)
self.figure.canvas.draw()
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = MyPaintWidget()
w.show()
app.exec_()
另一种可能的解决方法是实现从FigureCanvas类继承的create_oval()方法:
from PySide2 import QtCore, QtGui, QtWidgets
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
import numpy as np
class PainterCanvas(FigureCanvas):
def __init__(self, parent=None, width=5, height=4, dpi=100):
fig = Figure(figsize=(width, height), dpi=dpi)
FigureCanvas.__init__(self, fig)
self.setParent(parent)
self._instructions = []
self.axes = self.figure.add_subplot(111)
def paintEvent(self, event):
super().paintEvent(event)
painter = QtGui.QPainter(self)
painter.setRenderHint(QtGui.QPainter.Antialiasing, True)
width, height = self.get_width_height()
for x, y, rx, ry, br_color in self._instructions:
x_pixel, y_pixel_m = self.axes.transData.transform((x, y))
# In matplotlib, 0,0 is the lower left corner,
# whereas it's usually the upper right
# for most image software, so we'll flip the y-coor
y_pixel = height - y_pixel_m
painter.setBrush(QtGui.QColor(br_color))
painter.drawEllipse( QtCore.QPoint(x_pixel, y_pixel), rx, ry)
def create_oval(self, x, y, radius_x=5, radius_y=5, brush_color="red"):
self._instructions.append([x, y, radius_x, radius_y, brush_color])
self.update()
class MyPaintWidget(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.canvas = PainterCanvas()
self.canvas.mpl_connect("button_press_event", self._on_left_click)
x = np.arange(0, 10, 0.1)
y = np.cos(x)
self.canvas.axes.plot(x, y)
layout_canvas = QtWidgets.QVBoxLayout(self)
layout_canvas.addWidget(self.canvas)
def _on_left_click(self, event):
self.canvas.create_oval(event.xdata, event.ydata, brush_color="green")
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = MyPaintWidget()
w.show()
app.exec_()