Python Tkinter Embed Matplotlib: Candlestick + Volume charts in GUI - python-2.7

I'm trying to embed candlestick and volume charts (using matplotlib) in my Tkinter GUI coded in Python. I tried these sites as a reference: http://matplotlib.org/examples/user_interfaces/embedding_in_tk.html
http://matplotlib.org/examples/user_interfaces/embedding_in_tk2.html
and additional solutions finded here but I still have some issues. Separately works everything fine, but when I'm trying to get it together, two windows appear (one for charts and one for Tkinter frame with some widgets) instead of one.
#!/usr/bin/env python
import matplotlib
matplotlib.use('TkAgg')
import sys
if sys.version_info[0] < 3:
import Tkinter as Tk
else:
import tkinter as Tk
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
from matplotlib.figure import Figure
from tkFileDialog import askopenfilename
import ttk
import urllib2
import time
import datetime
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.ticker as mticker
import matplotlib.dates as mdates
from matplotlib.finance import candlestick
import matplotlib.dates
matplotlib.rcParams.update({'font.size': 9})
eachStock = 'TSLA', 'AAPL'
# Frames --------------------------------------------------------
root = Tk.Tk()
root.minsize(900,700)
main_frame = Tk.Frame(root)
main_frame.pack()
menu_frame = Tk.Frame(root)
menu_frame.pack()
tab_frame = Tk.Frame(root)
tab_frame.pack()
chart_frame = Tk.Frame(root)
chart_frame.pack()
statusbar_frame = Tk.Frame(root)
statusbar_frame.pack(side=Tk.BOTTOM, fill=Tk.BOTH, expand=True)
# -------------------------------------------------------------
# functions ---------------------------------------------
def NewFile():
print "New File!"
def OpenFile():
name = askopenfilename()
print name
def About():
print "This is a simple example of a menu"
# ----------------------------------------------------------
# Menu --------------------------------------------------------
menu = Tk.Menu(menu_frame)
root.config(menu=menu)
filemenu = Tk.Menu(menu)
menu.add_cascade(label="File", menu=filemenu)
filemenu.add_command(label="New", command=NewFile)
filemenu.add_command(label="Open...", command=OpenFile)
filemenu.add_separator()
filemenu.add_command(label="Exit", command=root.destroy)
helpmenu = Tk.Menu(menu)
menu.add_cascade(label="Help", menu=helpmenu)
helpmenu.add_command(label="About...", command=About)
# ----------------------------------------------------------
# Drawing charts --------------------------------------------
def graphData(stock):
try:
stockFile = 'data.csv'
date, closep, highp, lowp, openp, volume = np.loadtxt(stockFile,delimiter=',', unpack=True, converters={ 0: mdates.strpdate2num('%Y%m%d')})
x = 0
y = len(date)
candleAr = []
while x < y:
appendLine = date[x],openp[x],closep[x],highp[x],lowp[x],volume[x]
candleAr.append(appendLine)
x+=1
fig = plt.figure()
ax1 = plt.subplot2grid((5,4), (0,0), rowspan=4, colspan=4)
candlestick(ax1, candleAr, width=1, colorup='g', colordown='r')
ax1.grid(True)
ax1.xaxis.set_major_locator(mticker.MaxNLocator(10))
ax1.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))
plt.ylabel('Stock price')
ax2 = plt.subplot2grid((5,4), (4,0), sharex=ax1, rowspan=1, colspan=4)
ax2.bar(date, volume, color='red', align='center')
ax2.grid(True)
plt.ylabel('Volume')
for label in ax2.xaxis.get_ticklabels():
label.set_rotation(45)
plt.xlabel('Date')
plt.suptitle(stock+' Stock Price')
plt.setp(ax1.get_xticklabels(), visible=False)
plt.subplots_adjust(left=.09, bottom=.18, right=.94, top=.94, wspace=.20, hspace=0)
plt.show()
except Exception,e:
print 'main loop', str(e)
graphData('TSLA')

Add section alike this:
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
class UiSuperFrame( Frame ): # The user interface:
def __init__( self, master = None ):
Frame.__init__( self, master )
self.grid()
self.fig = Figure( ( 6, 6 ), dpi = 100 )
canvas = FigureCanvasTkAgg( self.fig, master = self )
canvas.get_tk_widget().grid( row = 0, column = 0 )
label = Label( self, text = 'TSLA, AAPL' )
label.grid( row = 1, column = 1 )
#
# .
# ..
# .... move the rest of GUI setup here ...
def TkDemo(): # Finally, set up <root> & start UI
""" HELP: Tk-GUI-MVC via a Class
TESTS: TkDemo()
"""
root = Tk()
root.title( 'TSLA/AAPL' )
root.lift()
app = UiSuperFrame( root )
app.mainloop()
pass

Related

Using the keyboard print data

I have a problem with python 2.7.
Question: When I use the zoom function, I can not use the "keyboard" to print my real data. Here, I add the keyboard event in my code.
How do I exist in both functions? How should I debug the code?
import matplotlib
import sys
import random
matplotlib.use("Qt5Agg")
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
from matplotlib.figure import Figure
import matplotlib.pyplot as plt
import numpy as np
from PyQt5.QtCore import *
import re
class MyMplCanvas(FigureCanvas):
def __init__(self, parent=None, width=10, height=4, dpi=100):
FigureCanvas.__init__(self, Figure(figsize=(width, height), dpi=dpi))
self.setParent(parent)
FigureCanvas.setSizePolicy(self, QSizePolicy.Expanding, QSizePolicy.Expanding)
FigureCanvas.updateGeometry(self)
self.axes = self.figure.add_subplot(211)
self.mpl_connect("motion_notify_event", self.on_move)
self.po_annotation = []
self.ff=[]
def start_static_plot(self):
for i in range(0, 990):
(point,) = self.axes.plot(x, y, "-o")
annotation = self.axes.annotate(
("x=" + str(x), "y=" + str(y)),
textcoords="data",
horizontalalignment="left",
arrowprops=dict(arrowstyle="simple",connectionstyle="arc3,rad=+0.2"), bbox=dict(boxstyle="round", facecolor="w", edgecolor="0.1", alpha=0.9)
annotation.set_visible(False)
self.po_annotation.append([point, annotation])
self.axes.set_xlim(-0.5, 1000)
self.axes.set_ylim(-5, 9.5 ** 2)
def on_move(self, event):
visibility_changed = Ture
for point, annotation in self.po_annotation:
should_be_visible = point.contains(event)[4]
if should_be_visible != annotation.get_visible():
visibility_changed = True
annotation.set_visible(should_be_visible)
datachouse=str(annotation)
self.ff = np.loadtxt(f)
if visibility_changed:
self.draw()
def mouseReleaseEvent(self, event):
if(event.button() == Qt.LeftButton):
def initUi(self):
self.mpl.start_static_plot()
self.layout.addWidget(self.mpl)
if __name__ == '__main__':
app = QApplication(sys.argv)
sys.exit(app.exec_())
If you don't want to remove the default behavior of a method then you must invoke the parent method:
def mouseReleaseEvent(self, event):
super(MyMplCanvas, self).mouseReleaseEvent(event)
if event.button() == Qt.LeftButton:
print("result=", self.ff)

How to search an item in list widget using with pyqt4

Here in my sample program,I want to display the lot of names in list widget.In that, I want to search a particular item in list widget using search button,and I want to print that item name in list widget.
Given below is my code:
import sys
from PyQt4 import QtGui, QtCore
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
auto_search_vbox = QtGui.QVBoxLayout(self)
hbox=QtGui.QHBoxLayout()
le_search = QtGui.QLineEdit()
se_btn = QtGui.QPushButton("Search")
se_btn.clicked.connect(self.find_item)
hbox.addWidget(le_search)
hbox.addWidget(se_btn)
auto_search_vbox.addLayout(hbox)
self.listwidget = QtGui.QListWidget()
self.total_list =["machine","printer","xerox bundles"]
self.listwidget.addItems(self.total_list)
auto_search_vbox.addWidget(self.listwidget)
self.show()
def find_item(self):
out = self.listwidget.findItems("mac", QtCore.Qt.MatchExactly)
print out
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
Sorry, I have PyQt5. Try it:
flags Qt::MatchFlags
This enum describes the type of matches that can be used when searching for items in a model.
import sys
#from PyQt4.QtGui import *
#from PyQt4.QtCore import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
class Example(QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
self.le_search = QLineEdit() # self. +++
se_btn = QPushButton("Search")
se_btn.clicked.connect(self.find_item)
self.listwidget = QListWidget()
self.total_list = ["machine", "mac1", "printer", "Printer","xerox bundles", "2mac"]
self.listwidget.addItems(self.total_list)
hbox = QHBoxLayout()
hbox.addWidget(self.le_search) # self. +++
hbox.addWidget(se_btn)
auto_search_vbox = QVBoxLayout(self)
auto_search_vbox.addLayout(hbox)
auto_search_vbox.addWidget(self.listwidget)
def find_item(self):
# out = self.listwidget.findItems("mac", QtCore.Qt.MatchExactly) # ---
# out = self.listwidget.findItems(self.le_search.text(), Qt.MatchExactly)
out = self.listwidget.findItems(self.le_search.text(),
Qt.MatchContains | # +++
Qt.MatchCaseSensitive) # +++
print("out->", [ i.text() for i in out ] )
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
ex.show()
sys.exit(app.exec_())

Not able to Dynamical Update Kivy Label Text

I am trying to add rows to a table like GUI.
These rows are to be a list of labels.
Each row that is updated has the following methods in that class:
AddRow - To add the list of strings that will be the text in that
label.
AddLabel - Adds a label to that row and appends the Label list
AddLabelRow - Creates the list Row in the actual table and
initializes the text to "empty"
ChangeLableText - Takes an input list of strings and changes the string in the label for that class.
I then have initialized a list of objects ContentList[] for this class and call the methods
But no matter which object's ChangeLabelText is called, only the text for ContentList[0] is updated.
import json
import requests
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.gridlayout import GridLayout
from kivy.uix.textinput import TextInput
from kivy.lang import Builder
from kivy.uix.scrollview import ScrollView
from kivy.core.window import Window
from kivy.uix.button import Button
from kivy.app import runTouchApp
class AddContent(GridLayout):
#response = requests.get("http://localhost:10010/")
# Get the response data as a python object. Verify that it's a dictionary.
#data = response.json()[3]
#Column_keys = ["country", "date", "answered_calls", "total_calls", "asr", "mou", "aou"]
RowList = []
Label_List = []
size = 0
def AddRow(self, InputList):
self.RowList = InputList
self.size = len(InputList)
def AddLabel(self,LayoutObj):
lbl = Label(size_hint_y = None, height = 30)
LayoutObj.add_widget(lbl)
return lbl
def AddLabelRow(self,LayoutObj):
for i in range(self.size):
Lbl = self.AddLabel(LayoutObj)
Lbl.text = "empty"
#self.Label_List[i].text = data[Column_keys[i]]
#Lbl.text = str(self.data[self.Column_keys[i]])
self.Label_List.append(Lbl)
def ChangeLabel_ListText(self, TextList):
for i in range(self.size):
#self.Label_List[i].text = data[Column_keys[i]] #data is fetched from Db
self.Label_List[i].text = TextList[i]
class TableView(GridLayout):
Col_Names = ["Date","Vendor","Country","MOU","ASR","AOU"]
ContentList = [AddContent(),AddContent(),AddContent()]
def __init__(self,**kwargs):
self.layout = GridLayout(cols = len(self.Col_Names), padding =5)
self.layout.bind(minimum_height=self.layout.setter('height'))
for i in range(len(self.Col_Names)):
btn = Button(text=self.Col_Names[i], size_hint_y=None, height=30)
self.layout.add_widget(btn)
self.ContentList[0].AddRow(['1sample1','1sample2','1sample3','1sample4','1sample5','1sample6'])
self.ContentList[1].AddRow(['2sample1','2sample2','2sample3','2sample4','2sample5','2sample6'])
self.ContentList[2].AddRow(['3sample1','3sample2','3sample3','3sample4','3sample5','3sample6'])
for i in range(3):
self.ContentList[i].AddLabelRow(self.layout)
self.ContentList[2].ChangeLabel_ListText(['a','b','c','d','e','f'])
if __name__ == '__main__':
Table = TableView()
runTouchApp(Table.layout)
The line self.ContentList[2].ChangeLabel_ListText(['a','b','c','d','e','f'])
updates only the first row whatever number is given for the index.
I have been breaking my head over this for the past week. I had initially done this with only one class instead of two which gave the same output.
Any help will help greatly. Thanks!
Your first problem is that RowList, Label_List, and size are class attributes in your code. But you want to set them in every instance individually. Solution: initialize these attributes inside the __init__ method like this:
def __init__(self, **kwargs):
super(AddContent, self).__init__(**kwargs)
self.RowList = []
self.Label_List = []
self.size = 0
The second problem is, that the GridLayout (which your class is subclassing) also contains an attribute called size. Solution: pick a different name for this attribute like so:
self.length = 0
If you now do
self.ContentList[i].ChangeLabel_ListText(['a','b','c','d','e','f'])
your i-th ContentList-entry will be changed.
Here is the complete solution:
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.gridlayout import GridLayout
from kivy.uix.textinput import TextInput
from kivy.lang import Builder
from kivy.uix.scrollview import ScrollView
from kivy.core.window import Window
from kivy.uix.button import Button
from kivy.app import runTouchApp
class AddContent(GridLayout):
#response = requests.get("http://localhost:10010/")
# Get the response data as a python object. Verify that it's a dictionary.
#data = response.json()[3]
#Column_keys = ["country", "date", "answered_calls", "total_calls", "asr", "mou", "aou"]
def __init__(self, **kwargs):
super(AddContent, self).__init__(**kwargs)
self.RowList = []
self.Label_List = []
self.length = 0
def AddRow(self, InputList):
self.RowList = InputList
self.length = len(InputList)
def AddLabel(self,LayoutObj):
lbl = Label(size_hint_y=None, height=30)
LayoutObj.add_widget(lbl)
return lbl
def AddLabelRow(self,LayoutObj):
for i in range(self.length):
Lbl = self.AddLabel(LayoutObj)
Lbl.text = "empty"
#self.Label_List[i].text = data[Column_keys[i]]
#Lbl.text = str(self.data[self.Column_keys[i]])
self.Label_List.append(Lbl)
def ChangeLabel_ListText(self, TextList):
for i in range(self.length):
#self.Label_List[i].text = data[Column_keys[i]] #data is fetched from Db
self.Label_List[i].text = TextList[i]
class TableView(GridLayout):
Col_Names = ["Date","Vendor","Country","MOU","ASR","AOU"]
ContentList = [AddContent(),AddContent(),AddContent()]
def __init__(self,**kwargs):
self.layout = GridLayout(cols = len(self.Col_Names), padding=5)
self.layout.bind(minimum_height=self.layout.setter('height'))
for i in range(len(self.Col_Names)):
btn = Button(text=self.Col_Names[i], size_hint_y=None, height=30)
self.layout.add_widget(btn)
self.ContentList[0].AddRow(['1sample1','1sample2','1sample3','1sample4','1sample5','1sample6'])
self.ContentList[1].AddRow(['2sample1','2sample2','2sample3','2sample4','2sample5','2sample6'])
self.ContentList[2].AddRow(['3sample1','3sample2','3sample3','3sample4','3sample5','3sample6'])
for i in range(3):
self.ContentList[i].AddLabelRow(self.layout)
self.ContentList[2].ChangeLabel_ListText(['a','b','c','d','e','f'])
if __name__ == '__main__':
Table = TableView()
runTouchApp(Table.layout)

Trouble with Importing Data and displaying it on a graph on a button click in python

from PyQt4.uic import loadUiType
import pandas as pd
from matplotlib.figure import Figure
from matplotlib.backends.backend_qt4agg import (
FigureCanvasQTAgg as FigureCanvas,
NavigationToolbar2QT as NavigationToolbar)
Ui_MainWindow, QMainWindow = loadUiType('EIA_20151504_v2.ui')
the above code i have done the following. I have imported the UI designed using QI designer and called matplotlib backend for putting matplotlib greaph in my app
class Main(QMainWindow, Ui_MainWindow):
def __init__(self, ):
super(Main, self).__init__()
self.setupUi(self)
self.RawData.clicked.connect(self.importdata)
def addmpl(self, fig):
self.canvas = FigureCanvas(fig)
self.mplvl.addWidget(self.canvas)
self.canvas.draw()
self.toolbar = NavigationToolbar(self.canvas,
self.MapCanvas, coordinates=True)
self.mplvl.addWidget(self.toolbar)
self.canvas.show()
def importdata(self):
choice = QtGui.QMessageBox.question(self, 'Import Data',"Do you want to import data?", QtGui.QMessageBox.Yes |QtGui.QMessageBox.No,QtGui.QMessageBox.No)
if choice == QtGui.QMessageBox.Yes:
xlsfile = pd.ExcelFile('import_file.xlsx')
self.dframe = xlsfile.parse('Sheet1', header=0, index_col=0, has_index_names=True)
self.xList = self.dframe.columns.values
self.xList = pd.to_datetime(self.xList)
self.yList = self.dframe.values
self.yList = self.yList.T
ax1f1.plot(self.xList,self.yList)
else:
pass
In the above code, I have declared a class Main which initialises the UI code imported from Qt designer and there are tw functions one is to initialise the map canvas and other to import data from another file and plot it on the click of the RawData button.
but if you try to run the code, the graph doesnot display any content
if __name__ == '__main__':
import sys
from PyQt4 import QtGui
import numpy as np
fig1 = Figure()
ax1f1 = fig1.add_subplot(111)
app = QtGui.QApplication(sys.argv)
main = Main()
main.addmpl(fig1)
main.show()
sys.exit(app.exec_())
Kindly let me know where I am going wrong
class Main(QMainWindow, Ui_MainWindow):
def __init__(self, ):
super(Main, self).__init__()
self.setupUi(self)
self.RawData.clicked.connect(self.importdata)
def addmpl(self, fig):
self.canvas = FigureCanvas(fig)
self.mplvl.addWidget(self.canvas)
self.canvas.draw()
self.toolbar = NavigationToolbar(self.canvas,
self.MapCanvas, coordinates=True)
self.mplvl.addWidget(self.toolbar)
self.canvas.show()
def rmmpl(self,):
self.mplvl.removeWidget(self.canvas)
self.canvas.close()
self.mplvl.removeWidget(self.toolbar)
self.toolbar.close()
def importdata(self):
choice = QtGui.QMessageBox.question(self, 'Import Data',"Do you want to import data?", QtGui.QMessageBox.Yes |QtGui.QMessageBox.No,QtGui.QMessageBox.No)
if choice == QtGui.QMessageBox.Yes:
xlsfile = pd.ExcelFile('import_file.xlsx')
self.dframe = xlsfile.parse('Sheet1', header=0, index_col=0, has_index_names=True)
self.xList = self.dframe.columns.values
self.xList = pd.to_datetime(self.xList)
self.yList = self.dframe.values
self.yList = self.yList.T
ax1f1.plot(self.xList,self.yList)
self.rmmpl()
self.addmpl(fig1)
else:
pass
def transition(self):
if __name__ == '__main__':
import sys
from PyQt4 import QtGui
import numpy as np
fig1 = Figure()
ax1f1 = fig1.add_subplot(111)
app = QtGui.QApplication(sys.argv)
main = Main()
main.addmpl(fig1)
main.show()
sys.exit(app.exec_())
There were some minor mistakes which I rectified.

python Attributes error

i just want to ask, what's wrong with my codes, or am i missing something. because when i call the function PausePlay() in the PlayAndPause() I always get an error saying:
self.dbusIfaceKey.Action(dbus.Int32("16"))
AttributeError: 'OpenOMX' object has no attribute 'dbusIfaceKey'
Here's the code:
OPTIONS = 'omxplayer -o local -t on --align center --win "0 0 {1} {2}" \"{0}\"'
from PyQt4 import QtCore, QtGui
from PyQt4.QtGui import *
from Tkinter import *
import sys
import os
from os import system
import dbus,time
from subprocess import Popen
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
_fromUtf8 = lambda s: s
MoviePath = '/media/HP v250w/Our Story in 1 Minute.mp4'
class OpenOMX(QtCore.QThread):
def __init__(self):
QtCore.QThread.__init__(self)
def run(self):
global MoviePath
global myctr
width = QtGui.QApplication.desktop().width()
height = QtGui.QApplication.desktop().height()
cmd = OPTIONS.format(MoviePath,width,height-60)
Popen([cmd], shell=True)
done,retry = 0,0
while done==0:
try:
with open('/tmp/omxplayerdbus', 'r+') as f:
omxplayerdbus = f.read().strip()
bus = dbus.bus.BusConnection(self.omxplayerdbus)
print 'connected'
object = bus.get_object('org.mpris.MediaPlayer2.omxplayer','/org/mpris/MediaPlayer2', introspect=False)
self.dbusIfaceProp = dbus.Interface(object,'org.freedesktop.DBus.Properties')
self.dbusIfaceKey = dbus.Interface(object,'org.mpris.MediaPlayer2.Player')
done=1
except:
retry+=1
if retry >= 50:
print 'ERROR'
raise SystemExit
def PausePlay(self):
self.dbusIfaceKey.Action(dbus.Int32('16'))
class VidControls(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
def setupUi(self, MainWindow):
'some codes here'
def retranslateUi(self, MainWindow):
self.btnPause.clicked.connect(self.PlayAndPause)
def PlayAndPause(self):
self.opn = OpenOMX()
self.opn.PausePlay()
if __name__=='__main__':
app = QtGui.QApplication(sys.argv)
ex = VidControls()
ex.show()
play = OpenOMX()
play.start()
sys.exit(app.exec_())
Any Comments or Suggestions would be highly appreciated. Thanks.