Python 如何在固定位置设置yaxis勾号标签,以便在向左或向右滚动时,yaxis勾号标签应可见?

Python 如何在固定位置设置yaxis勾号标签,以便在向左或向右滚动时,yaxis勾号标签应可见?,python,matplotlib,pyqt5,Python,Matplotlib,Pyqt5,在我的程序中,我先画了一个图形,然后将figue导入画布。然后我将画布导入到滚动区域。当我运行程序时,如果我向左滚动,yaxis勾号标签将隐藏,或者向右滚动,yaxis勾号标签也将隐藏。 我取了两个轴。轴,轴2。我已经设置了axes2.yaxis.tick_right()和axes.yaxis.tick_right() 无论向左或向右滚动,我都希望yaxis勾号标签保持在右侧,并且始终可见。 输出图像: 当我向左滚动输出图像2时:这里有一种方法可以使用PyQtQtScrollBar滚动轴的内

在我的程序中,我先画了一个图形,然后将figue导入画布。然后我将画布导入到滚动区域。当我运行程序时,如果我向左滚动,yaxis勾号标签将隐藏,或者向右滚动,yaxis勾号标签也将隐藏。 我取了两个轴。轴,轴2。我已经设置了axes2.yaxis.tick_right()和axes.yaxis.tick_right()

无论向左或向右滚动,我都希望yaxis勾号标签保持在右侧,并且始终可见。

输出图像:


当我向左滚动输出图像2时:

这里有一种方法可以使用PyQt
QtScrollBar
滚动轴的内容。这是通过根据滚动条的值更改轴的限制来实现的。为此,注册对
QtScrollBar
actionTriggered
方法的回调,以更改轴的限制

import sys
import matplotlib
# Make sure that we are using QT5
matplotlib.use('Qt5Agg')
import matplotlib.pyplot as plt
from PyQt5 import QtWidgets, QtCore
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
import numpy as np

class ScrollableWindow(QtWidgets.QMainWindow):
    def __init__(self, fig, ax, step=0.1):
        plt.close("all")
        if not QtWidgets.QApplication.instance():
            self.app = QtWidgets.QApplication(sys.argv)
        else:
            self.app = QtWidgets.QApplication.instance() 

        QtWidgets.QMainWindow.__init__(self)
        self.widget = QtWidgets.QWidget()
        self.setCentralWidget(self.widget)
        self.widget.setLayout(QtWidgets.QVBoxLayout())
        self.widget.layout().setContentsMargins(0,0,0,0)
        self.widget.layout().setSpacing(0)

        self.fig = fig
        self.ax = ax
        self.canvas = FigureCanvas(self.fig)
        self.canvas.draw()
        self.scroll = QtWidgets.QScrollBar(QtCore.Qt.Horizontal)
        self.step = step
        self.setupSlider()
        self.nav = NavigationToolbar(self.canvas, self.widget)
        self.widget.layout().addWidget(self.nav)
        self.widget.layout().addWidget(self.canvas)
        self.widget.layout().addWidget(self.scroll)

        self.canvas.draw()
        self.show()
        self.app.exec_()

    def setupSlider(self):
        self.lims = np.array(self.ax.get_xlim())
        self.scroll.setPageStep(self.step*100)
        self.scroll.actionTriggered.connect(self.update)
        self.update()

    def update(self, evt=None):
        r = self.scroll.value()/((1+self.step)*100)
        l1 = self.lims[0]+r*np.diff(self.lims)
        l2 = l1 +  np.diff(self.lims)*self.step
        self.ax.set_xlim(l1,l2)
        print(self.scroll.value(), l1,l2)
        self.fig.canvas.draw_idle()


# create a figure and some subplots
fig, ax = plt.subplots()
t = np.linspace(0,3000,101)
x = np.cumsum(np.random.randn(len(t)))
ax.plot(t,x, marker="o")

# pass the figure to the custom window
a = ScrollableWindow(fig,ax)



有关图中的滚动条,请参见此处提供了一种使用PyQt
QtScrollBar
滚动轴内容的方法。这是通过根据滚动条的值更改轴的限制来实现的。为此,注册对
QtScrollBar
actionTriggered
方法的回调,以更改轴的限制

import sys
import matplotlib
# Make sure that we are using QT5
matplotlib.use('Qt5Agg')
import matplotlib.pyplot as plt
from PyQt5 import QtWidgets, QtCore
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
import numpy as np

class ScrollableWindow(QtWidgets.QMainWindow):
    def __init__(self, fig, ax, step=0.1):
        plt.close("all")
        if not QtWidgets.QApplication.instance():
            self.app = QtWidgets.QApplication(sys.argv)
        else:
            self.app = QtWidgets.QApplication.instance() 

        QtWidgets.QMainWindow.__init__(self)
        self.widget = QtWidgets.QWidget()
        self.setCentralWidget(self.widget)
        self.widget.setLayout(QtWidgets.QVBoxLayout())
        self.widget.layout().setContentsMargins(0,0,0,0)
        self.widget.layout().setSpacing(0)

        self.fig = fig
        self.ax = ax
        self.canvas = FigureCanvas(self.fig)
        self.canvas.draw()
        self.scroll = QtWidgets.QScrollBar(QtCore.Qt.Horizontal)
        self.step = step
        self.setupSlider()
        self.nav = NavigationToolbar(self.canvas, self.widget)
        self.widget.layout().addWidget(self.nav)
        self.widget.layout().addWidget(self.canvas)
        self.widget.layout().addWidget(self.scroll)

        self.canvas.draw()
        self.show()
        self.app.exec_()

    def setupSlider(self):
        self.lims = np.array(self.ax.get_xlim())
        self.scroll.setPageStep(self.step*100)
        self.scroll.actionTriggered.connect(self.update)
        self.update()

    def update(self, evt=None):
        r = self.scroll.value()/((1+self.step)*100)
        l1 = self.lims[0]+r*np.diff(self.lims)
        l2 = l1 +  np.diff(self.lims)*self.step
        self.ax.set_xlim(l1,l2)
        print(self.scroll.value(), l1,l2)
        self.fig.canvas.draw_idle()


# create a figure and some subplots
fig, ax = plt.subplots()
t = np.linspace(0,3000,101)
x = np.cumsum(np.random.randn(len(t)))
ax.plot(t,x, marker="o")

# pass the figure to the custom window
a = ScrollableWindow(fig,ax)



对于图中的滚动条,请参见上面的答案,它运行良好,但不能将控制权交还给spyder窗口或python命令行。在spyder中,它也只能运行一次。在退出QT窗口时,添加了从另一个线程看到的更多点,并对此进行了改进

import sys
import matplotlib
# Make sure that we are using QT5
matplotlib.use('Qt5Agg')
import matplotlib.pyplot as plt
from PyQt5 import QtWidgets, QtCore
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
import numpy as np

from PyQt5.QtWidgets import QMainWindow, QLabel, QGridLayout, QWidget
from PyQt5.QtCore import QSize

class HelloWindow(QMainWindow):
    def __init__(self, fig, ax , step = 0.1):


        plt.close("all")
        if not QtWidgets.QApplication.instance():
            self.app = QtWidgets.QApplication(sys.argv)
        else:
            self.app = QtWidgets.QApplication.instance() 

        
        QMainWindow.__init__(self)
 
        self.setMinimumSize(QSize(1500, 100))    
        self.setWindowTitle("Value Plotting") 

        self.step = step
        
        self.widget = QWidget() 
        self.setCentralWidget( self.widget )

        self.widget.setLayout(QtWidgets.QVBoxLayout())
        self.widget.layout().setContentsMargins(0,0,0,0)
        self.widget.layout().setSpacing(0)

        self.fig = fig
        self.ax = ax
        self.canvas = FigureCanvas(self.fig)
        self.canvas.draw()
        self.scroll = QtWidgets.QScrollBar(QtCore.Qt.Horizontal)
        self.step = step
        self.setupSlider()
        self.nav = NavigationToolbar(self.canvas, self.widget)#        self.widget.layout().addWidget(self.nav)
        self.widget.layout().addWidget(self.canvas)
        self.widget.layout().addWidget(self.scroll)

        menu = self.menuBar().addMenu('Action for quit')
        action = menu.addAction('Quit')
        action.triggered.connect(QtWidgets.QApplication.quit)

        self.canvas.draw()


        
    def setupSlider(self):
        self.lims = np.array(self.ax.get_xlim())
        self.scroll.setPageStep(self.step*100)
        self.scroll.actionTriggered.connect(self.update)
        self.update()

    def update(self, evt=None):
        r = self.scroll.value()/((1+self.step)*100)
        l1 = self.lims[0]+r*np.diff(self.lims)
        l2 = l1 +  np.diff(self.lims)*self.step
        self.ax.set_xlim(l1,l2)
        print(self.scroll.value(), l1,l2)
        self.fig.canvas.draw_idle()

        
 
if __name__ == "__main__":
    def run_app(fig,ax):
        app = QtWidgets.QApplication(sys.argv)
        mainWin = HelloWindow(fig,ax)
        mainWin.show()
        app.exec_()


    fig, ax = plt.subplots()
    t = np.linspace(0,3000,101)
    x = np.cumsum(np.random.randn(len(t)))
    ax.plot(t,x, marker="o")

    run_app(fig,ax)

发现它在python控制台上运行良好。在Spyder中大致退出。Top close(顶部关闭)按钮不起作用,但在从菜单操作时退出。

上述答案工作正常,但无法将控制权交还给spyder窗口或python命令行。在spyder中,它也只能运行一次。在退出QT窗口时,添加了从另一个线程看到的更多点,并对此进行了改进

import sys
import matplotlib
# Make sure that we are using QT5
matplotlib.use('Qt5Agg')
import matplotlib.pyplot as plt
from PyQt5 import QtWidgets, QtCore
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
import numpy as np

from PyQt5.QtWidgets import QMainWindow, QLabel, QGridLayout, QWidget
from PyQt5.QtCore import QSize

class HelloWindow(QMainWindow):
    def __init__(self, fig, ax , step = 0.1):


        plt.close("all")
        if not QtWidgets.QApplication.instance():
            self.app = QtWidgets.QApplication(sys.argv)
        else:
            self.app = QtWidgets.QApplication.instance() 

        
        QMainWindow.__init__(self)
 
        self.setMinimumSize(QSize(1500, 100))    
        self.setWindowTitle("Value Plotting") 

        self.step = step
        
        self.widget = QWidget() 
        self.setCentralWidget( self.widget )

        self.widget.setLayout(QtWidgets.QVBoxLayout())
        self.widget.layout().setContentsMargins(0,0,0,0)
        self.widget.layout().setSpacing(0)

        self.fig = fig
        self.ax = ax
        self.canvas = FigureCanvas(self.fig)
        self.canvas.draw()
        self.scroll = QtWidgets.QScrollBar(QtCore.Qt.Horizontal)
        self.step = step
        self.setupSlider()
        self.nav = NavigationToolbar(self.canvas, self.widget)#        self.widget.layout().addWidget(self.nav)
        self.widget.layout().addWidget(self.canvas)
        self.widget.layout().addWidget(self.scroll)

        menu = self.menuBar().addMenu('Action for quit')
        action = menu.addAction('Quit')
        action.triggered.connect(QtWidgets.QApplication.quit)

        self.canvas.draw()


        
    def setupSlider(self):
        self.lims = np.array(self.ax.get_xlim())
        self.scroll.setPageStep(self.step*100)
        self.scroll.actionTriggered.connect(self.update)
        self.update()

    def update(self, evt=None):
        r = self.scroll.value()/((1+self.step)*100)
        l1 = self.lims[0]+r*np.diff(self.lims)
        l2 = l1 +  np.diff(self.lims)*self.step
        self.ax.set_xlim(l1,l2)
        print(self.scroll.value(), l1,l2)
        self.fig.canvas.draw_idle()

        
 
if __name__ == "__main__":
    def run_app(fig,ax):
        app = QtWidgets.QApplication(sys.argv)
        mainWin = HelloWindow(fig,ax)
        mainWin.show()
        app.exec_()


    fig, ax = plt.subplots()
    t = np.linspace(0,3000,101)
    x = np.cumsum(np.random.randn(len(t)))
    ax.plot(t,x, marker="o")

    run_app(fig,ax)

发现它在python控制台上运行良好。在Spyder中大致退出。顶部关闭按钮不工作,但在从菜单操作时退出。

这里您正在查看完整的图形画布。看起来你想要的是在不连接画布的情况下创建一个scollbar,而是让它更改绘图的xlimits。谢谢你理解我的问题。你能把你的解释转换成代码吗?在这里你可以看到完整的图形画布。看起来你想要的是在不连接画布的情况下创建一个scollbar,而是让它更改绘图的xlimits。谢谢你理解我的问题。你能用代码解释一下吗?在Windows的Spyder/IPython中,这只工作一次,然后当窗口关闭时终端会锁定:/@endolith抱歉,我缩短了应用程序创建时间太多,应该修复now@ImportanceOfBeingErnestIMHO:代码更具可读性的是:
self.app=qtwidts.QApplication.instance()
如果self.app为None:
self.app=qtwidts.QApplication(sys.argv)
:-)我得到一个
AttributeError:ScrollableWindow对象在您的示例中没有属性qapp
错误。知道为什么会这样吗?(使用PyQt5版本5.13.0)@MarkLoyman是的,首先不应该有任何
qapp
,我更新了代码。在Windows中的Spyder/IPython中,这只工作一次,然后当窗口关闭时终端锁定:/@endolith抱歉,我缩短了太多的应用程序创建时间,应该是固定的now@ImportanceOfBeingErnestIMHO:更可读的代码是:
self.app=qtwidts.QApplication.instance()
如果self.app没有:
self.app=qtwidts.QApplication(sys.argv)
:-)我得到一个
AttributeError:ScrollableWindow对象没有属性qapp
错误。知道为什么会这样吗?(使用PyQt5版本5.13.0)@MarkLoyman是的,首先不应该有任何
qapp
,我更新了代码。