9

I am trying to add finplot, https://pypi.org/project/finplot/, as a widget to one of the layouts in my UI. I created a widget for finplot and added it to the widgets in the layout but I get the following error:

self.tab1.layout.addWidget(self.tab1.fplt_widget)
TypeError: addWidget(self, QWidget, stretch: int = 0, alignment: Union[Qt.Alignment, Qt.AlignmentFlag] = Qt.Alignment()): argument 1 has unexpected type 'PlotItem'

Here is the code that I used.

import sys
from PyQt5.QtWidgets import *
import finplot as fplt
import yfinance


# Creating the main window
class App(QMainWindow):
    def __init__(self):
        super().__init__()
        self.title = 'PyQt5 - QTabWidget'
        self.left = 0
        self.top = 0
        self.width = 600
        self.height = 400
        self.setWindowTitle(self.title)
        self.setGeometry(self.left, self.top, self.width, self.height)

        self.tab_widget = MyTabWidget(self)
        self.setCentralWidget(self.tab_widget)

        self.show()

    # Creating tab widgets


class MyTabWidget(QWidget):
    def __init__(self, parent):
        super(QWidget, self).__init__(parent)
        self.layout = QVBoxLayout(self)

        # Initialize tab screen
        self.tabs = QTabWidget()
        self.tabs.setTabPosition(QTabWidget.East)
        self.tabs.setMovable(True)

        self.tab1 = QWidget()

        self.tabs.resize(600, 400)

        # Add tabs
        self.tabs.addTab(self.tab1, "tab1")


        self.tab1.layout = QVBoxLayout(self)
        self.tab1.label = QLabel("AAPL")
        self.tab1.df = yfinance.download('AAPL')
        self.tab1.fplt_widget = fplt.create_plot_widget(self.window())
        fplt.candlestick_ochl(self.tab1.df[['Open', 'Close', 'High', 'Low']])
        self.tab1.layout.addWidget(self.tab1.label)
        self.tab1.layout.addWidget(self.tab1.fplt_widget)
        self.tab1.setLayout(self.tab1.layout)

        # Add tabs to widget
        self.layout.addWidget(self.tabs)
        self.setLayout(self.layout)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = App()
    sys.exit(app.exec_())
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
afp_2008
  • 1,940
  • 1
  • 19
  • 46

3 Answers3

6

The create_plot_widget() function creates a PlotItem that cannot be added to a layout, the solution is to use some QWidget that can display the content of the PlotItem as the PlotWidget:

import pyqtgraph as pg

# ...

self.tab1.df = yfinance.download("AAPL")
self.tab1.fplt_widget = pg.PlotWidget(
    plotItem=fplt.create_plot_widget(self.window())
)
fplt.candlestick_ochl(self.tab1.df[["Open", "Close", "High", "Low"]])
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
  • Thanks for your quick answer. How can I show the entire x-axis? It seems like the plot shows only the first five data points. There are hundreds of datapoint. Is there any parameter to pass to show all? – afp_2008 Sep 26 '20 at 06:07
5

To add a widget you use the widget member of the axis you create, like so:

self.tab1.layout.addWidget(self.tab1.fplt_widget.ax_widget)
self.window().axs = [self.tab1.fplt_widget] # required property of window

To get the window to scale the X-axis properly as displaying you call show() here:

self.setCentralWidget(self.tab_widget)
fplt.show(qt_exec=False)
self.show()
Jonas Byström
  • 25,316
  • 23
  • 100
  • 147
  • 1
    I'm trying days and nights to find out how to deal with your eminent module. I'm very glad that you created it and will be so happy to see new releases and some documentation.In a single word I can say THANK YOU MAN. Your answer to this question is true but when I make an app with three `finplot` widgets just the last one shows a correct crosshair and full chart and the others has no working crosshair and they don't show a good chart at first(just a few candles ). You can see it in following image. How can I fix it? https://i.stack.imgur.com/PPipU.png – Seyfi Nov 29 '20 at 17:28
  • 1
    @Seyfi Thanks for the kind words! I've seen this problem before when people didn't call `finplt.show(qt_exec=True)`, but only had their own Qt show called. Did you try the code in my second example? – Jonas Byström Nov 29 '20 at 20:55
  • 1
    Yes. I've tried the code in question combined with whole of your answer and I called `fplt.show(qt_exec=False)` before `self.show()`. I can with some trouble zoom out and see complete chart but I want to see a good chart in first view. And crosshair problem is there( not working crosshair problem). – Seyfi Nov 30 '20 at 09:18
  • 1
    in addition, after I tested above question mixed with your answer then I made my own code based on that code. – Seyfi Nov 30 '20 at 11:36
  • 1
    This is not the right forum, but I need to see your code to find out what's going on. Best advice that aside is to remove one thing after another to distill the smallest reproducible code containing the bug. If you still can't find the error, I'll have a look. – Jonas Byström Nov 30 '20 at 14:38
  • 1
    I appreciate your dedication. In this link you can see my code https://www.codepile.net/pile/mABja5AY – Seyfi Nov 30 '20 at 17:02
  • 1
    I don't have your contact info. You're missing `self.window().axs = [self.one.fplt_widget, self.two.fplt_widget, self.three.fplt_widget]`. – Jonas Byström Dec 01 '20 at 07:21
  • 1
    I'm also on github "BSeyfi". I tested this method. It is good but muse movement is just available in last widget. – Seyfi Dec 01 '20 at 14:22
2

managed to make it work

from PyQt5.QtWidgets import *
import finplot as fplt
import yfinance
import pyqtgraph as pg
import sys

# Creating the main window
class App(QMainWindow):
    def __init__(self):
        super().__init__()
        self.title = 'PyQt5 - QTabWidget'
        self.left = 0
        self.top = 0
        self.width = 600
        self.height = 400
        self.setWindowTitle(self.title)
        self.setGeometry(self.left, self.top, self.width, self.height)

        self.tab_widget = MyTabWidget(self)
        self.setCentralWidget(self.tab_widget)

        # Insert policies
       
        fplt.refresh()
        self.show()

    # Creating tab widgets


class MyTabWidget(QWidget):
    def __init__(self, parent):
        super(QWidget, self).__init__(parent)
        self.layout = QVBoxLayout(self)

        # Initialize tab screen
        self.tabs = QTabWidget()
        self.tabs.setTabPosition(QTabWidget.East)
        self.tabs.setMovable(True)

        self.tab1 = QWidget()

        self.tabs.resize(600, 400)

        # Add tabs
        self.tabs.addTab(self.tab1, "tab1")
        self.tab1.layout = QVBoxLayout(self)
        self.tab1.label = QLabel("AAPL")

        # finplot
        self.tab1.df = yfinance.download("AAPL")
        self.tab1.fplt_widget = pg.PlotWidget(
            plotItem=fplt.create_plot_widget(self.window())
        )
        fplt.candlestick_ochl(self.tab1.df[["Open", "Close", "High", "Low"]])
        self.tab1.layout.addWidget(self.tab1.fplt_widget)
        self.window().axs = [self.tab1.fplt_widget.plotItem]


        self.tab1.setLayout(self.tab1.layout)
        # Add tabs to widget
        self.layout.addWidget(self.tabs)
        self.setLayout(self.layout)



if __name__ == '__main__':
    app = QApplication([])
    ex = App()
    sys.exit(app.exec_())