PyQt5 更新嵌套的 QWidgets
PyQt5 updating nested QWidgets
我正在尝试编写我的第一个 PyQt 项目,并希望在我从菜单栏中选择“新建模式”选项时更新右侧的文本字段和左侧的绘图。我认为菜单栏中的操作可以正确触发,但触发的功能本身不会正确更新 Canvas 图或标签(所以最后当我点击创建时没有任何反应)。我尝试了不同版本的 self.update() 并没有真正找到我在 pyqt 文档中找到解决方案的方法,因为我只找到更新普通 QWidget 的解决方案但我的结构是嵌套的,所以也许只有一个我不太明白的小错误...
由于我对 Python 或 PyQt 本身不太熟悉,因此我也希望对我的代码风格提供任何帮助或反馈。
import sys
import numpy as np
from screeninfo import get_monitors
from PyQt5.QtWidgets import QApplication, QMainWindow, QMenuBar, QAction, QHBoxLayout, QVBoxLayout, QWidget, QLabel
from PyQt5.QtGui import QPalette, QColor
import matplotlib.pyplot as plt
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg
from matplotlib.figure import Figure
# grid class
class Grid(FigureCanvasQTAgg):
def __init__(self, parent = None, width = 5, height = 5, dpi = 120):
fig = Figure(figsize=(width, height), dpi=dpi)
self.ax = fig.add_subplot()
self.ax.set_ylim(-8.75, 8.75)
self.ax.set_xlim(-8.75, 8.75)
ticks = list(range(-8, 9))
self.ax.xaxis.set_ticks(ticks)
self.ax.yaxis.set_ticks(ticks)
self.ax.grid(visible = True)
self.ax.set_axisbelow(True)
self.ax.tick_params(axis='both', which='both', length=0, labeltop=True, labelright=True)
self.ax.set_aspect('equal')
for spine in self.ax.spines.values():
spine.set_visible(False)
self.title_font_ = {'fontsize': 16, 'fontweight': "normal", 'color': "black",
'verticalalignment': "center", 'horizontalalignment': "center"}
self.ax.set_title("Grid Title", fontdict = self.title_font_, pad = 35)
self.circles = []
super(Grid, self).__init__(fig)
def createPattern(self, dots = 8, unified = True):
self.dots = dots
self.unified = unified
# change title
self.ax.set_title("Add Pattern", fontdict = self.title_font_, pad = 35)
x = list(range(-8, -8+dots))
y = [8.01]*dots
if self.unified:
coord = np.array(list(map(list, zip(x, y))))
for i in range(self.pairs):
circ = self.ax.add_patch(plt.Circle((coord[i,0], coord[i,1]), 0.35, color="royalblue"))
self.circles.append(circ)
else:
xw = list(range(1, 1+dots))
coord_blue = np.array(list(map(list, zip(x, y))))
coord_pink = np.array(list(map(list, zip(xw, y))))
for i in range(dots):
circ = self.ax.add_patch(plt.Circle((coord_pink[i,0], coord_pink[i,1]), 0.35, color="deeppink"))
self.circles.append(circ)
for i in range(dots):
circ = self.ax.add_patch(plt.Circle((coord_blue[i,0], coord_blue[i,1]), 0.35, color="deepskyblue"))
self.circles.append(circ)
class Side(QWidget):
def __init__(self, color):
super(Side, self).__init__()
# background color
self.setAutoFillBackground(True)
palette = self.palette()
palette.setColor(QPalette.Window, QColor(color))
self.setPalette(palette)
# add layout and text
self.layout = QVBoxLayout()
self.label = QLabel("Welcome to My first program")
self.layout.addWidget(self.label)
self.setLayout(self.layout)
def createPattern(self):
self.label = QLabel("Now we will create a pattern")
#self.update() ??
#super(Side, self).update() ??
class MainWindow(QMainWindow):
def __init__(self, parent = None):
super().__init__(parent)
screen = get_monitors()[0]
self.setGeometry(int(screen.width*0.125), int(screen.height*0.125),
int(screen.width*0.75), int(screen.height*0.75))
self.setWindowTitle("My Program")
self._createActions()
self._createMenuBar()
# a figure instance to plot on
self.grid = Grid(width=8, height=8, dpi=140)
# a side panel
self.side = Side('white')
self.centralwidget = QWidget()
self.setCentralWidget(self.centralwidget)
self.layout = QHBoxLayout(self.centralwidget)
self.layout.addWidget(self.grid, 55)
self.layout.addWidget(self.side, 45)
def _createActions(self):
self.newPatternAction = QAction("&New Pattern", self)
def _createMenuBar(self):
menuBar = QMenuBar(self)
self.setMenuBar(menuBar)
patternMenu = menuBar.addMenu("&Pattern")
patternMenu.addAction(self.newPatternAction)
def _connectActions(self):
self.newPatternAction.triggered.connect(self.newPattern)
def newPattern(self):
# Logic for creating a new file goes here...
self.grid.createPattern()
self.side.createPattern()
def window():
app = QApplication(sys.argv)
win = MainWindow()
win.show()
sys.exit(app.exec_())
if __name__ == "__main__":
app = QApplication(sys.argv)
app.setQuitOnLastWindowClosed(True)
win = MainWindow()
win.show()
sys.exit(app.exec_())
解决办法比较尴尬——我没有正确连接菜单操作。
import sys
import numpy as np
from screeninfo import get_monitors
from PyQt5.QtWidgets import QApplication, QMainWindow, QMenuBar, QAction, QHBoxLayout, QVBoxLayout, QWidget, QLabel
from PyQt5.QtGui import QPalette, QColor
import matplotlib.pyplot as plt
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg
from matplotlib.figure import Figure
# grid class
class Grid(FigureCanvasQTAgg):
def __init__(self, parent = None, width = 5, height = 5, dpi = 120):
fig = Figure(figsize=(width, height), dpi=dpi)
self.ax = fig.add_subplot()
self.ax.set_ylim(-8.75, 8.75)
self.ax.set_xlim(-8.75, 8.75)
ticks = list(range(-8, 9))
self.ax.xaxis.set_ticks(ticks)
self.ax.yaxis.set_ticks(ticks)
self.ax.grid(visible = True)
self.ax.set_axisbelow(True)
self.ax.tick_params(axis='both', which='both', length=0, labeltop=True, labelright=True)
self.ax.set_aspect('equal')
for spine in self.ax.spines.values():
spine.set_visible(False)
self.title_font_ = {'fontsize': 16, 'fontweight': "normal", 'color': "black",
'verticalalignment': "center", 'horizontalalignment': "center"}
self.ax.set_title("Grid Title", fontdict = self.title_font_, pad = 35)
self.circles = []
super(Grid, self).__init__(fig)
def createPattern(self, dots = 8, unified = True):
self.dots = dots
self.unified = unified
# change title
self.ax.set_title("Add Pattern", fontdict = self.title_font_, pad = 35)
x = list(range(-8, -8+dots))
y = [8.01]*dots
if self.unified:
coord = np.array(list(map(list, zip(x, y))))
for i in range(self.pairs):
circ = self.ax.add_patch(plt.Circle((coord[i,0], coord[i,1]), 0.35, color="royalblue"))
self.circles.append(circ)
else:
xw = list(range(1, 1+dots))
coord_blue = np.array(list(map(list, zip(x, y))))
coord_pink = np.array(list(map(list, zip(xw, y))))
for i in range(dots):
circ = self.ax.add_patch(plt.Circle((coord_pink[i,0], coord_pink[i,1]), 0.35, color="deeppink"))
self.circles.append(circ)
for i in range(dots):
circ = self.ax.add_patch(plt.Circle((coord_blue[i,0], coord_blue[i,1]), 0.35, color="deepskyblue"))
self.circles.append(circ)
# THIS IS NEW TO UPDATE THE PLOT
self.draw()
class Side(QWidget):
def __init__(self, color):
super(Side, self).__init__()
# background color
self.setAutoFillBackground(True)
palette = self.palette()
palette.setColor(QPalette.Window, QColor(color))
self.setPalette(palette)
# add layout and text
self.layout = QVBoxLayout()
self.label = QLabel("Welcome to My first program")
self.layout.addWidget(self.label)
self.setLayout(self.layout)
def createPattern(self):
# THIS IS NEW - THANK YOU MUSICAMENTE
self.label.setText("Now we will create a pattern")
class MainWindow(QMainWindow):
def __init__(self, parent = None):
super().__init__(parent)
screen = get_monitors()[0]
self.setGeometry(int(screen.width*0.125), int(screen.height*0.125),
int(screen.width*0.75), int(screen.height*0.75))
self.setWindowTitle("My Program")
self._createActions()
self._createMenuBar()
# THIS IS NEW TO PROPERLY CONNECT THE MENU ACTION
self._connectActions()
# a figure instance to plot on
self.grid = Grid(width=8, height=8, dpi=140)
# a side panel
self.side = Side('white')
self.centralwidget = QWidget()
self.setCentralWidget(self.centralwidget)
self.layout = QHBoxLayout(self.centralwidget)
self.layout.addWidget(self.grid, 55)
self.layout.addWidget(self.side, 45)
def _createActions(self):
self.newPatternAction = QAction("&New Pattern", self)
def _createMenuBar(self):
menuBar = QMenuBar(self)
self.setMenuBar(menuBar)
patternMenu = menuBar.addMenu("&Pattern")
patternMenu.addAction(self.newPatternAction)
def _connectActions(self):
self.newPatternAction.triggered.connect(self.newPattern)
def newPattern(self):
# Logic for creating a new file goes here...
self.grid.createPattern()
self.side.createPattern()
def window():
app = QApplication(sys.argv)
win = MainWindow()
win.show()
sys.exit(app.exec_())
if __name__ == "__main__":
app = QApplication(sys.argv)
app.setQuitOnLastWindowClosed(True)
win = MainWindow()
win.show()
sys.exit(app.exec_())
我正在尝试编写我的第一个 PyQt 项目,并希望在我从菜单栏中选择“新建模式”选项时更新右侧的文本字段和左侧的绘图。我认为菜单栏中的操作可以正确触发,但触发的功能本身不会正确更新 Canvas 图或标签(所以最后当我点击创建时没有任何反应)。我尝试了不同版本的 self.update() 并没有真正找到我在 pyqt 文档中找到解决方案的方法,因为我只找到更新普通 QWidget 的解决方案但我的结构是嵌套的,所以也许只有一个我不太明白的小错误...
由于我对 Python 或 PyQt 本身不太熟悉,因此我也希望对我的代码风格提供任何帮助或反馈。
import sys
import numpy as np
from screeninfo import get_monitors
from PyQt5.QtWidgets import QApplication, QMainWindow, QMenuBar, QAction, QHBoxLayout, QVBoxLayout, QWidget, QLabel
from PyQt5.QtGui import QPalette, QColor
import matplotlib.pyplot as plt
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg
from matplotlib.figure import Figure
# grid class
class Grid(FigureCanvasQTAgg):
def __init__(self, parent = None, width = 5, height = 5, dpi = 120):
fig = Figure(figsize=(width, height), dpi=dpi)
self.ax = fig.add_subplot()
self.ax.set_ylim(-8.75, 8.75)
self.ax.set_xlim(-8.75, 8.75)
ticks = list(range(-8, 9))
self.ax.xaxis.set_ticks(ticks)
self.ax.yaxis.set_ticks(ticks)
self.ax.grid(visible = True)
self.ax.set_axisbelow(True)
self.ax.tick_params(axis='both', which='both', length=0, labeltop=True, labelright=True)
self.ax.set_aspect('equal')
for spine in self.ax.spines.values():
spine.set_visible(False)
self.title_font_ = {'fontsize': 16, 'fontweight': "normal", 'color': "black",
'verticalalignment': "center", 'horizontalalignment': "center"}
self.ax.set_title("Grid Title", fontdict = self.title_font_, pad = 35)
self.circles = []
super(Grid, self).__init__(fig)
def createPattern(self, dots = 8, unified = True):
self.dots = dots
self.unified = unified
# change title
self.ax.set_title("Add Pattern", fontdict = self.title_font_, pad = 35)
x = list(range(-8, -8+dots))
y = [8.01]*dots
if self.unified:
coord = np.array(list(map(list, zip(x, y))))
for i in range(self.pairs):
circ = self.ax.add_patch(plt.Circle((coord[i,0], coord[i,1]), 0.35, color="royalblue"))
self.circles.append(circ)
else:
xw = list(range(1, 1+dots))
coord_blue = np.array(list(map(list, zip(x, y))))
coord_pink = np.array(list(map(list, zip(xw, y))))
for i in range(dots):
circ = self.ax.add_patch(plt.Circle((coord_pink[i,0], coord_pink[i,1]), 0.35, color="deeppink"))
self.circles.append(circ)
for i in range(dots):
circ = self.ax.add_patch(plt.Circle((coord_blue[i,0], coord_blue[i,1]), 0.35, color="deepskyblue"))
self.circles.append(circ)
class Side(QWidget):
def __init__(self, color):
super(Side, self).__init__()
# background color
self.setAutoFillBackground(True)
palette = self.palette()
palette.setColor(QPalette.Window, QColor(color))
self.setPalette(palette)
# add layout and text
self.layout = QVBoxLayout()
self.label = QLabel("Welcome to My first program")
self.layout.addWidget(self.label)
self.setLayout(self.layout)
def createPattern(self):
self.label = QLabel("Now we will create a pattern")
#self.update() ??
#super(Side, self).update() ??
class MainWindow(QMainWindow):
def __init__(self, parent = None):
super().__init__(parent)
screen = get_monitors()[0]
self.setGeometry(int(screen.width*0.125), int(screen.height*0.125),
int(screen.width*0.75), int(screen.height*0.75))
self.setWindowTitle("My Program")
self._createActions()
self._createMenuBar()
# a figure instance to plot on
self.grid = Grid(width=8, height=8, dpi=140)
# a side panel
self.side = Side('white')
self.centralwidget = QWidget()
self.setCentralWidget(self.centralwidget)
self.layout = QHBoxLayout(self.centralwidget)
self.layout.addWidget(self.grid, 55)
self.layout.addWidget(self.side, 45)
def _createActions(self):
self.newPatternAction = QAction("&New Pattern", self)
def _createMenuBar(self):
menuBar = QMenuBar(self)
self.setMenuBar(menuBar)
patternMenu = menuBar.addMenu("&Pattern")
patternMenu.addAction(self.newPatternAction)
def _connectActions(self):
self.newPatternAction.triggered.connect(self.newPattern)
def newPattern(self):
# Logic for creating a new file goes here...
self.grid.createPattern()
self.side.createPattern()
def window():
app = QApplication(sys.argv)
win = MainWindow()
win.show()
sys.exit(app.exec_())
if __name__ == "__main__":
app = QApplication(sys.argv)
app.setQuitOnLastWindowClosed(True)
win = MainWindow()
win.show()
sys.exit(app.exec_())
解决办法比较尴尬——我没有正确连接菜单操作。
import sys
import numpy as np
from screeninfo import get_monitors
from PyQt5.QtWidgets import QApplication, QMainWindow, QMenuBar, QAction, QHBoxLayout, QVBoxLayout, QWidget, QLabel
from PyQt5.QtGui import QPalette, QColor
import matplotlib.pyplot as plt
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg
from matplotlib.figure import Figure
# grid class
class Grid(FigureCanvasQTAgg):
def __init__(self, parent = None, width = 5, height = 5, dpi = 120):
fig = Figure(figsize=(width, height), dpi=dpi)
self.ax = fig.add_subplot()
self.ax.set_ylim(-8.75, 8.75)
self.ax.set_xlim(-8.75, 8.75)
ticks = list(range(-8, 9))
self.ax.xaxis.set_ticks(ticks)
self.ax.yaxis.set_ticks(ticks)
self.ax.grid(visible = True)
self.ax.set_axisbelow(True)
self.ax.tick_params(axis='both', which='both', length=0, labeltop=True, labelright=True)
self.ax.set_aspect('equal')
for spine in self.ax.spines.values():
spine.set_visible(False)
self.title_font_ = {'fontsize': 16, 'fontweight': "normal", 'color': "black",
'verticalalignment': "center", 'horizontalalignment': "center"}
self.ax.set_title("Grid Title", fontdict = self.title_font_, pad = 35)
self.circles = []
super(Grid, self).__init__(fig)
def createPattern(self, dots = 8, unified = True):
self.dots = dots
self.unified = unified
# change title
self.ax.set_title("Add Pattern", fontdict = self.title_font_, pad = 35)
x = list(range(-8, -8+dots))
y = [8.01]*dots
if self.unified:
coord = np.array(list(map(list, zip(x, y))))
for i in range(self.pairs):
circ = self.ax.add_patch(plt.Circle((coord[i,0], coord[i,1]), 0.35, color="royalblue"))
self.circles.append(circ)
else:
xw = list(range(1, 1+dots))
coord_blue = np.array(list(map(list, zip(x, y))))
coord_pink = np.array(list(map(list, zip(xw, y))))
for i in range(dots):
circ = self.ax.add_patch(plt.Circle((coord_pink[i,0], coord_pink[i,1]), 0.35, color="deeppink"))
self.circles.append(circ)
for i in range(dots):
circ = self.ax.add_patch(plt.Circle((coord_blue[i,0], coord_blue[i,1]), 0.35, color="deepskyblue"))
self.circles.append(circ)
# THIS IS NEW TO UPDATE THE PLOT
self.draw()
class Side(QWidget):
def __init__(self, color):
super(Side, self).__init__()
# background color
self.setAutoFillBackground(True)
palette = self.palette()
palette.setColor(QPalette.Window, QColor(color))
self.setPalette(palette)
# add layout and text
self.layout = QVBoxLayout()
self.label = QLabel("Welcome to My first program")
self.layout.addWidget(self.label)
self.setLayout(self.layout)
def createPattern(self):
# THIS IS NEW - THANK YOU MUSICAMENTE
self.label.setText("Now we will create a pattern")
class MainWindow(QMainWindow):
def __init__(self, parent = None):
super().__init__(parent)
screen = get_monitors()[0]
self.setGeometry(int(screen.width*0.125), int(screen.height*0.125),
int(screen.width*0.75), int(screen.height*0.75))
self.setWindowTitle("My Program")
self._createActions()
self._createMenuBar()
# THIS IS NEW TO PROPERLY CONNECT THE MENU ACTION
self._connectActions()
# a figure instance to plot on
self.grid = Grid(width=8, height=8, dpi=140)
# a side panel
self.side = Side('white')
self.centralwidget = QWidget()
self.setCentralWidget(self.centralwidget)
self.layout = QHBoxLayout(self.centralwidget)
self.layout.addWidget(self.grid, 55)
self.layout.addWidget(self.side, 45)
def _createActions(self):
self.newPatternAction = QAction("&New Pattern", self)
def _createMenuBar(self):
menuBar = QMenuBar(self)
self.setMenuBar(menuBar)
patternMenu = menuBar.addMenu("&Pattern")
patternMenu.addAction(self.newPatternAction)
def _connectActions(self):
self.newPatternAction.triggered.connect(self.newPattern)
def newPattern(self):
# Logic for creating a new file goes here...
self.grid.createPattern()
self.side.createPattern()
def window():
app = QApplication(sys.argv)
win = MainWindow()
win.show()
sys.exit(app.exec_())
if __name__ == "__main__":
app = QApplication(sys.argv)
app.setQuitOnLastWindowClosed(True)
win = MainWindow()
win.show()
sys.exit(app.exec_())