这是完整的代码库。我试图模拟在self.graph这是plotwidget的图形中的鼠标单击。我希望鼠标单击在plotrunnable类中发生,所以在我单击图形按钮后,它将自动更新,就在睡觉之前,它将模拟对图形的单击,使其看起来像是在自动更新
# Form implementation generated from reading ui file 'U:\Embedded Graphics View2.ui'
#
# Created by: PyQt5 UI code generator 5.9.2
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
import pyqtgraph as pg
import pyodbc as db
import pandas as pd
import time, os
from time import strptime as strptime
from time import mktime as mktime
from time import gmtime, strftime
from pyqtgraph import AxisItem
from datetime import datetime, timedelta
from numpy import ceil
import numpy as np
import sip
os.environ['TZ']='EST'
now=time.asctime(time.localtime())
start_time=time.time()
print('starting at '+now)
def time(date):
if date == '':
return None
else:
datetime = date
pattern = '%Y%m%d %H:%M:%S'
epoch = int(mktime(strptime(datetime, pattern)))
return epoch
def connecttosql():
host='{SQL Server}'
server='SERVER' ######### DEV - WILL CHANGE TO PRODUCTION WHEN DELIVERED
database='DB'
username='user'
password='pass'
try:
cs= 'Driver=%s;Server=%s;Uid=%s;Pwd=%s;Database=%s;' % (host,server, username, password, database)
global conn #### THIS WILL BE USED ON THE QUERY
conn= db.connect(cs)
print ('Connected successfully to '+host+', '+server)
except Exception as e:
print ('Error: ' + str (e))
def testconnection():
cursor=conn.cursor()
try:
cursor.execute("SELECT VERSION()")
res=cursor.fetchone()
print(res)
ver=res[0]
if ver in None:
return False
else:
return True
except:
print ("ERROR IN CONNECTION")
return False
def closeconnection():
conn.close
print('CONNECTION WITH DATABASE HAS BEEN CLOSED')
def query(ticker,interval,ST,ET):
# target='U:/py/sql csv/'+ticker+' - '+interval+'.csv'
global conn
table = 'BAR_BB' ### hard code
qry = f"SELECT * FROM {table} WHERE SY = {ticker} AND IL = {interval} AND ST >= {ST} AND ST <= {ET}"
df=pd.read_sql(qry,conn) ###### format will change
df.set_index('ST',inplace=True)
#df.to_csv(target,encoding='utf-8',index=False)
st=df.index.tolist()
op=df['O'].tolist()
hi=df['H'].tolist()
lo=df['L'].tolist()
cl=df['C'].tolist()
bars=[]
x=0
for i in st:
bar=[st[x],op[x],cl[x],lo[x],hi[x]]
bars.append(bar)
x=x+1
data=bars
return data
##Picture that goes in the UI
class CandlestickItem(pg.GraphicsObject):
def __init__(self):
pg.GraphicsObject.__init__(self)
self.flagHasData = False
@QtCore.pyqtSlot(list)
def set_data(self, data):
self.data = data
self.flagHasData = True
self.generatePicture()
self.informViewBoundsChanged()
def generatePicture(self):
## pre-computing a QPicture object allows paint() to run much more quickly,
## rather than re-drawing the shapes every time.
self.picture = QtGui.QPicture()
p = QtGui.QPainter(self.picture)
p.setPen(pg.mkPen('w'))
w = (self.data[1][0] - self.data[0][0]) / 3.
for (t, open, close, min, max) in self.data:
p.drawLine(QtCore.QPointF(t, min), QtCore.QPointF(t, max))
if open > close:
p.setBrush(pg.mkBrush('r'))
else:
p.setBrush(pg.mkBrush('g'))
p.drawRect(QtCore.QRectF(t-w, open, w*2, close-open))
p.end()
def paint(self, p, *args):
p.drawPicture(0, 0, self.picture)
def boundingRect(self):
## boundingRect _must_ indicate the entire area that will be drawn on
## or else we will get artifacts and possibly crashing.
## (in this case, QPicture does all the work of computing the bouning rect for us)
return QtCore.QRectF(self.picture.boundingRect())
class DateAxisItem(AxisItem):
"""
A tool that provides a date-time aware axis. It is implemented as an
AxisItem that interpretes positions as unix timestamps (i.e. seconds
since 1970).
The labels and the tick positions are dynamically adjusted depending
on the range.
It provides a :meth:`attachToPlotItem` method to add it to a given
PlotItem
"""
# Max width in pixels reserved for each label in axis
_pxLabelWidth = 80
def __init__(self, *args, **kwargs):
AxisItem.__init__(self, *args, **kwargs)
self._oldAxis = None
def tickValues(self, minVal, maxVal, size):
"""
Reimplemented from PlotItem to adjust to the range and to force
the ticks at "round" positions in the context of time units instead of
rounding in a decimal base
"""
maxMajSteps = int(size/self._pxLabelWidth)
dt1 = datetime.fromtimestamp(minVal)
dt2 = datetime.fromtimestamp(maxVal)
dx = maxVal - minVal
majticks = []
if dx > 63072001: # 3600s*24*(365+366) = 2 years (count leap year)
d = timedelta(days=366)
for y in range(dt1.year + 1, dt2.year):
dt = datetime(year=y, month=1, day=1)
majticks.append(mktime(dt.timetuple()))
elif dx > 5270400: # 3600s*24*61 = 61 days
d = timedelta(days=31)
dt = dt1.replace(day=1, hour=0, minute=0,
second=0, microsecond=0) + d
while dt < dt2:
# make sure that we are on day 1 (even if always sum 31 days)
dt = dt.replace(day=1)
majticks.append(mktime(dt.timetuple()))
dt += d
elif dx > 172800: # 3600s24*2 = 2 days
d = timedelta(days=1)
dt = dt1.replace(hour=0, minute=0, second=0, microsecond=0) + d
while dt < dt2:
majticks.append(mktime(dt.timetuple()))
dt += d
elif dx > 7200: # 3600s*2 = 2hours
d = timedelta(hours=1)
dt = dt1.replace(minute=0, second=0, microsecond=0) + d
while dt < dt2:
majticks.append(mktime(dt.timetuple()))
dt += d
elif dx > 1200: # 60s*20 = 20 minutes
d = timedelta(minutes=10)
dt = dt1.replace(minute=(dt1.minute // 10) * 10,
second=0, microsecond=0) + d
while dt < dt2:
majticks.append(mktime(dt.timetuple()))
dt += d
elif dx > 120: # 60s*2 = 2 minutes
d = timedelta(minutes=1)
dt = dt1.replace(second=0, microsecond=0) + d
while dt < dt2:
majticks.append(mktime(dt.timetuple()))
dt += d
elif dx > 20: # 20s
d = timedelta(seconds=10)
dt = dt1.replace(second=(dt1.second // 10) * 10, microsecond=0) + d
while dt < dt2:
majticks.append(mktime(dt.timetuple()))
dt += d
elif dx > 2: # 2s
d = timedelta(seconds=1)
majticks = range(int(minVal), int(maxVal))
else: # <2s , use standard implementation from parent
return AxisItem.tickValues(self, minVal, maxVal, size)
L = len(majticks)
if L > maxMajSteps:
majticks = majticks[::int(ceil(float(L) / maxMajSteps))]
return [(d.total_seconds(), majticks)]
def tickStrings(self, values, scale, spacing):
"""Reimplemented from PlotItem to adjust to the range"""
ret = []
if not values:
return []
if spacing >= 31622400: # 366 days
fmt = "%Y"
elif spacing >= 2678400: # 31 days
fmt = "%Y %b"
elif spacing >= 86400: # = 1 day
fmt = "%b/%d"
elif spacing >= 3600: # 1 h
fmt = "%b/%d-%Hh"
elif spacing >= 60: # 1 m
fmt = "%H:%M"
elif spacing >= 1: # 1s
fmt = "%H:%M:%S"
else:
# less than 2s (show microseconds)
# fmt = '%S.%f"'
fmt = '[+%fms]' # explicitly relative to last second
for x in values:
try:
t = datetime.fromtimestamp(x)
ret.append(t.strftime(fmt))
except ValueError: # Windows can't handle dates before 1970
ret.append('')
return ret
def attachToPlotItem(self, plotItem):
"""Add this axis to the given PlotItem
:param plotItem: (PlotItem)
"""
self.setParentItem(plotItem)
viewBox = plotItem.getViewBox()
self.linkToView(viewBox)
self._oldAxis = plotItem.axes[self.orientation]['item']
self._oldAxis.hide()
plotItem.axes[self.orientation]['item'] = self
pos = plotItem.axes[self.orientation]['pos']
plotItem.layout.addItem(self, *pos)
self.setZValue(-1000)
def detachFromPlotItem(self):
"""Remove this axis from its attached PlotItem
(not yet implemented)
"""
raise NotImplementedError() # TODO
class TimeAxisItem(pg.AxisItem):
def tickStrings(self, values, scale, spacing):
return [datetime.fromtimestamp(value) for value in values]
##UI SetUP
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(1442, 1018)
MainWindow.setAutoFillBackground(False)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.graphicsView = QtWidgets.QWidget(self.centralwidget)
self.flagHasData = False
self.graphicsView.setGeometry(QtCore.QRect(0, 0, 1201, 991))
font = QtGui.QFont()
font.setPointSize(18)
self.graphicsView.setFont(font)
brush = QtGui.QBrush(QtGui.QColor(0, 0, 0))
brush.setStyle(QtCore.Qt.SolidPattern)
self.graphicsView.setObjectName("graphicsView")
self.lineEdit = QtWidgets.QLineEdit(self.centralwidget)
self.lineEdit.setEnabled(True)
self.lineEdit.setGeometry(QtCore.QRect(1280, 20, 151, 21))
font = QtGui.QFont()
font.setPointSize(11)
self.lineEdit.setFont(font)
self.lineEdit.setObjectName("lineEdit")
self.lineEdit_2 = QtWidgets.QLineEdit(self.centralwidget)
self.lineEdit_2.setGeometry(QtCore.QRect(1280, 80, 151, 20))
font = QtGui.QFont()
font.setPointSize(11)
self.lineEdit_2.setFont(font)
self.lineEdit_2.setText("")
self.lineEdit_2.setObjectName("lineEdit_2")
self.lineEdit_3 = QtWidgets.QLineEdit(self.centralwidget)
self.lineEdit_3.setGeometry(QtCore.QRect(1280, 160, 151, 20))
font = QtGui.QFont()
font.setPointSize(11)
self.lineEdit_3.setFont(font)
self.lineEdit_3.setObjectName("lineEdit_3")
self.lineEdit_4 = QtWidgets.QLineEdit(self.centralwidget)
self.lineEdit_4.setGeometry(QtCore.QRect(1280, 230, 151, 20))
font = QtGui.QFont()
font.setPointSize(11)
self.lineEdit_4.setFont(font)
self.lineEdit_4.setObjectName("lineEdit_4")
self.label = QtWidgets.QLabel(self.centralwidget)
self.label.setGeometry(QtCore.QRect(1280, 0, 91, 16))
self.label.setObjectName("label")
self.label_2 = QtWidgets.QLabel(self.centralwidget)
self.label_2.setGeometry(QtCore.QRect(1280, 60, 111, 16))
self.label_2.setObjectName("label_2")
self.label_3 = QtWidgets.QLabel(self.centralwidget)
self.label_3.setGeometry(QtCore.QRect(1280, 120, 51, 16))
self.label_3.setObjectName("label_3")
self.label_4 = QtWidgets.QLabel(self.centralwidget)
self.label_4.setGeometry(QtCore.QRect(1280, 190, 101, 16))
self.label_4.setObjectName("label_4")
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
self.pushButton.setGeometry(QtCore.QRect(1280, 260, 75, 23))
self.pushButton.setObjectName("pushButton")
self.label_5 = QtWidgets.QLabel(self.centralwidget)
self.label_5.setGeometry(QtCore.QRect(1280, 140, 170, 20))
self.label_5.setObjectName("label_5")
self.label_6 = QtWidgets.QLabel(self.centralwidget)
self.label_6.setGeometry(QtCore.QRect(1280, 210, 170, 20))
self.label_6.setObjectName("label_6")
self.pushButton_2 = QtWidgets.QPushButton(self.centralwidget)
self.pushButton_2.setGeometry(QtCore.QRect(1360, 260, 75, 23))
self.pushButton_2.setObjectName("pushButton_2")
MainWindow.setCentralWidget(self.centralwidget)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.pushButton.clicked.connect(self.btn_click)
self.pushButton_2.clicked.connect(self.clear)
self.main_layout = QtWidgets.QHBoxLayout()
self.graphicsView.setLayout(self.main_layout)
self.graph = None
self.glayout = None
self.data = []
self.vb = None
self.main_layout.addWidget(self.graph)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
##renaming all the Labels and Window
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "Graph Interface"))
self.label.setText(_translate("MainWindow", "Ticker (Bloomberg)"))
self.label_2.setText(_translate("MainWindow", "Interval (In Seconds)"))
self.label_3.setText(_translate("MainWindow", "Start Time"))
self.label_4.setText(_translate("MainWindow", "End Time (Optional)"))
self.pushButton.setText(_translate("MainWindow", "Graph"))
self.label_5.setText(_translate("MainWindow", "YYYYMMDD 00:00:00 (UTC)"))
self.label_6.setText(_translate("MainWindow", "YYYYMMDD 00:00:00 (UTC)"))
self.pushButton_2.setText(_translate("MainWindow", "Clear"))
global mouse_click_event
def mouse_click_event(self):
graph.clicked()
#Button Click function.
def btn_click(self):
global ticker, interval, start_time, end_time, graph
global DRAW_GRAPH
connecttosql()
self.data = [ ## fields are (time, open, close, min, max).
(1., 10, 13, 5, 15),
(2., 13, 17, 9, 20),
(3., 17, 14, 11, 23),
(4., 14, 15, 5, 19),
(5., 15, 9, 8, 22),
(6., 9, 15, 8, 16)]
self.graph = pg.PlotWidget(name = 'Whatever', aixsItems = {'bottom' : TimeAxisItem(orientation = 'bottom')})
# self.ticker = self.lineEdit.text()
#self.interval = self.lineEdit_2.text()
#self.start_time = time(self.lineEdit_3.text())
#self.end_time = time(self.lineEdit_4.text())
# if self.end_time == None:
# self.end_time = time(strftime("%Y%m%d %H:%M:%S", gmtime()))
# else:
# self.end_time = time((self.lineEdit_4.text()))
# self.ticker = "'{}'".format(self.ticker)
# self.interval = "'{}'".format(self.interval)
# ticker = self.ticker
# interval = self.interval
# start_time = self.start_time
# end_time = self.end_time
self.glayout = pg.GraphicsLayout()
self.vb = self.glayout.addViewBox()
self.vb.enableAutoRange(axis='xy',enable = True)
#self.data = query(self.ticker,self.interval,self.start_time,self.end_time)
self.item = CandlestickItem()
self.item.set_data(self.data)
self.graph.addItem(self.item)
self.axis1 = DateAxisItem(orientation = 'bottom')
self.axis1.attachToPlotItem(self.graph.getPlotItem())
self.graph.showGrid(y=True, alpha = 0.8)
self.main_layout.addWidget(self.graph)
runnable = PlotRunnable(self.item)
QtCore.QThreadPool.globalInstance().start(runnable)
def clear(self):
self.parent = self.graph.parent()
self.graph.setParent(None)
self.graph.setParent(self.parent)
class PlotRunnable(QtCore.QRunnable):
def __init__(self, it):
QtCore.QRunnable.__init__(self)
self.it = it
def run(self):
while True:
data = self.it.data
# end_time = end_time = time(strftime("%Y%m%d %H:%M:%S", gmtime()))
rand =[ ## fields are (time, open, close, min, max).
(1., 10, 13, 5, 15),
(2., 13, 17, 9, 20),
(3., 17, 14, 11, 23),
(4., 14, 15, 5, 19),
(5., 15, 9, 8, 22),
(6., 9, 15, 8, 16),
(7., 8, 16, 10, 17)]
new_bar = rand[-1]
data.append(new_bar)
QtCore.QMetaObject.invokeMethod(self.it, "set_data",
QtCore.Qt.QueuedConnection,
QtCore.Q_ARG(list, data))
#put mouse click here
print("ran")
#interval = int("{}".format(interval))
QtCore.QThread.msleep(1000)
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
if __name__ == '__main__':
import sys
if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
QtGui.QApplication.instance().exec_()