mostly functional example
This commit is contained in:
parent
eb6f724767
commit
148a35d430
153
examples/PaletteApplicationExample.py
Normal file
153
examples/PaletteApplicationExample.py
Normal file
@ -0,0 +1,153 @@
|
||||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Update a simple plot as rapidly as possible to measure speed.
|
||||
"""
|
||||
|
||||
## Add path to library (just for examples; you do not need this)
|
||||
import initExample
|
||||
|
||||
|
||||
import numpy as np
|
||||
|
||||
import pyqtgraph as pg
|
||||
from pyqtgraph.Qt import mkQApp, QtGui, QtCore, QtWidgets
|
||||
from pyqtgraph.ptime import time
|
||||
from pyqtgraph import functions as fn
|
||||
|
||||
|
||||
class MainWindow(QtWidgets.QMainWindow):
|
||||
""" example application main window """
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(MainWindow, self).__init__(*args, **kwargs)
|
||||
|
||||
main_wid = QtWidgets.QWidget()
|
||||
self.setCentralWidget(main_wid)
|
||||
self.setWindowTitle('pyqtgraph example: Palette application test')
|
||||
self.resize(600,600)
|
||||
|
||||
# pg.functions.SIGNAL_SOURCE.paletteChangedSignal.connect(self.testSignal) # test link
|
||||
# pg.palette.get('monogreen').apply()
|
||||
|
||||
main_layout = QtWidgets.QGridLayout( main_wid )
|
||||
gr_wid = pg.GraphicsLayoutWidget(show=True)
|
||||
main_layout.addWidget( gr_wid, 0,0, 1,4 )
|
||||
|
||||
btn = QtWidgets.QPushButton('continuous')
|
||||
btn.clicked.connect(self.handle_button_timer_on)
|
||||
main_layout.addWidget(btn, 1,0, 1,1 )
|
||||
|
||||
btn = QtWidgets.QPushButton('stop updates')
|
||||
btn.clicked.connect(self.handle_button_timer_off)
|
||||
main_layout.addWidget(btn, 2,0, 1,1 )
|
||||
|
||||
btn = QtWidgets.QPushButton('apply <legacy>')
|
||||
btn.clicked.connect(self.handle_button_pal1)
|
||||
main_layout.addWidget(btn, 1,2, 1,1 )
|
||||
|
||||
btn = QtWidgets.QPushButton('apply <mono green>')
|
||||
btn.clicked.connect(self.handle_button_pal2)
|
||||
main_layout.addWidget(btn, 1,3, 1,1 )
|
||||
|
||||
btn = QtWidgets.QPushButton('apply <relaxed - dark>')
|
||||
btn.clicked.connect(self.handle_button_pal3)
|
||||
main_layout.addWidget(btn, 2,2, 1,1 )
|
||||
|
||||
btn = QtWidgets.QPushButton('apply <relaxed - light>')
|
||||
btn.clicked.connect(self.handle_button_pal4)
|
||||
main_layout.addWidget(btn, 2,3, 1,1 )
|
||||
|
||||
# self.manager = pg.fn.NAMED_COLOR_MANAGER
|
||||
# self.pen1 = pg.NamedPen('p1') #,width=0.5)
|
||||
|
||||
self.plt = gr_wid.addPlot()
|
||||
self.plt.enableAutoRange(False)
|
||||
self.plt.setYRange( -7,7 )
|
||||
self.plt.setXRange( 0, 15 ) #500 )
|
||||
|
||||
self.plt.setLabel('bottom', 'Index', units='B')
|
||||
|
||||
self.data1 = +3 + np.random.normal(size=(15)) #500))
|
||||
self.data2 = -3 + np.random.normal(size=(15)) #500))
|
||||
|
||||
self.curve1 = pg.PlotDataItem(pen='r', symbol='o', symbolSize=10, symbolPen='gr_fg', symbolBrush=('y',127))
|
||||
self.plt.addItem(self.curve1)
|
||||
|
||||
self.curve2 = pg.PlotCurveItem(pen='p3', brush='p4')
|
||||
self.curve2.setFillLevel(0)
|
||||
self.plt.addItem(self.curve2)
|
||||
self.show()
|
||||
|
||||
self.pal_1 = pg.palette.get('legacy')
|
||||
self.pal_2 = pg.palette.get('monogreen')
|
||||
self.pal_3 = pg.palette.get('relaxed_dark')
|
||||
self.pal_4 = pg.palette.get('relaxed_light')
|
||||
|
||||
self.lastTime = time()
|
||||
self.fps = None
|
||||
self.timer = QtCore.QTimer(singleShot=False)
|
||||
self.timer.timeout.connect( self.timed_update )
|
||||
|
||||
self.timed_update()
|
||||
|
||||
def testSignal(self, val):
|
||||
""" demonstrate use of PaletteChanged signal """
|
||||
print('"Palette changed" signal was received with value', val)
|
||||
|
||||
|
||||
def handle_button_timer_on(self):
|
||||
""" (re-)activate timer """
|
||||
self.timer.start(1)
|
||||
|
||||
def handle_button_timer_off(self):
|
||||
""" de-activate timer """
|
||||
self.timer.stop()
|
||||
|
||||
def handle_button_pal1(self):
|
||||
""" apply palette 1 on request """
|
||||
print('--> legacy')
|
||||
self.pal_1.apply()
|
||||
|
||||
def handle_button_pal2(self):
|
||||
""" apply palette 2 on request """
|
||||
print('--> mono green')
|
||||
self.pal_2.apply()
|
||||
|
||||
def handle_button_pal3(self):
|
||||
""" apply palette 1 on request """
|
||||
print('--> relax(light)')
|
||||
self.pal_3.apply()
|
||||
|
||||
def handle_button_pal4(self):
|
||||
""" apply palette 1 on request """
|
||||
print('--> relax(light)')
|
||||
self.pal_4.apply()
|
||||
|
||||
def timed_update(self):
|
||||
""" update loop, called by timer """
|
||||
self.data1[:-1] = self.data1[1:]
|
||||
self.data1[-1] = +3 + np.random.normal()
|
||||
xdata = np.arange( len(self.data1) )
|
||||
self.curve1.setData( x=xdata, y=self.data1 )
|
||||
|
||||
self.data2[:-1] = self.data2[1:]
|
||||
self.data2[-1] = -3 + np.random.normal()
|
||||
self.curve2.setData( y=self.data2 )
|
||||
|
||||
now = time()
|
||||
dt = now - self.lastTime
|
||||
self.lastTime = now
|
||||
if self.fps is None:
|
||||
self.fps = 1.0/dt
|
||||
else:
|
||||
s = np.clip(dt*3., 0, 1)
|
||||
self.fps = self.fps * (1-s) + (1.0/dt) * s
|
||||
self.plt.setTitle('%0.2f fps' % self.fps)
|
||||
QtWidgets.QApplication.processEvents() ## force complete redraw for every plot
|
||||
|
||||
mkQApp("Palette test application")
|
||||
main_window = MainWindow()
|
||||
|
||||
## Start Qt event loop
|
||||
if __name__ == '__main__':
|
||||
QtWidgets.QApplication.instance().exec_()
|
@ -1,7 +1,6 @@
|
||||
from collections import OrderedDict
|
||||
from argparse import Namespace
|
||||
|
||||
|
||||
examples = OrderedDict([
|
||||
('Command-line usage', 'CLIexample.py'),
|
||||
('Basic Plotting', Namespace(filename='Plotting.py', recommended=True)),
|
||||
@ -21,6 +20,7 @@ examples = OrderedDict([
|
||||
('Auto-range', 'PlotAutoRange.py'),
|
||||
('Remote Plotting', 'RemoteSpeedTest.py'),
|
||||
('Scrolling plots', 'scrollingPlots.py'),
|
||||
('Palette adjustment','PaletteApplicationExample.py'),
|
||||
('HDF5 big data', 'hdf5.py'),
|
||||
('Demos', OrderedDict([
|
||||
('Optics', 'optics_demos.py'),
|
||||
|
@ -62,12 +62,17 @@ CONFIG_OPTIONS = {
|
||||
'useCupy': False, # When True, attempt to use cupy ( currently only with ImageItem and related functions )
|
||||
}
|
||||
|
||||
|
||||
def setConfigOption(opt, value):
|
||||
if opt not in CONFIG_OPTIONS:
|
||||
raise KeyError('Unknown configuration option "%s"' % opt)
|
||||
if opt == 'imageAxisOrder' and value not in ('row-major', 'col-major'):
|
||||
raise ValueError('imageAxisOrder must be either "row-major" or "col-major"')
|
||||
# setConfigOption should be relocated to have access to functions.py
|
||||
# Then background / foreground updates can be intercepted and applied to the palette
|
||||
# if opt == 'background':
|
||||
# functions.Colors['gr_bg'] = functions.Colors[value]
|
||||
# if opt == 'foreground':
|
||||
# functions.Colors['gr_fg'] = functions.Colors[value]
|
||||
CONFIG_OPTIONS[opt] = value
|
||||
|
||||
def setConfigOptions(**opts):
|
||||
@ -280,6 +285,7 @@ from .ptime import time
|
||||
from .Qt import isQObjectAlive
|
||||
from .ThreadsafeTimer import *
|
||||
from .namedPen import *
|
||||
from .namedBrush import *
|
||||
from .palette import *
|
||||
|
||||
|
||||
|
@ -22,6 +22,7 @@ from .Qt import QtGui, QtCore, QT_LIB, QtVersion
|
||||
from . import Qt
|
||||
from .namedColorManager import NamedColorManager
|
||||
from .namedPen import NamedPen
|
||||
from .namedBrush import NamedBrush
|
||||
|
||||
from .metaarray import MetaArray
|
||||
from collections import OrderedDict
|
||||
@ -219,25 +220,66 @@ class Color(QtGui.QColor):
|
||||
return (self.red, self.green, self.blue, self.alpha)[ind]()
|
||||
|
||||
|
||||
def parseNamedColorSpecification(*args):
|
||||
"""
|
||||
check if args specify a NamedColor, looking for
|
||||
'name' or ('name', alpha) information.
|
||||
Returns:
|
||||
None if invalid
|
||||
('name', alpha) if a valid name and alpha value is given
|
||||
('name', None) if no alpha value is available
|
||||
('', None) if an empty name is given, indicating a blank color
|
||||
None if the specification does not match a NamedColor
|
||||
"""
|
||||
while len(args) <= 1:
|
||||
if len(args) == 0:
|
||||
return None
|
||||
if len(args) == 1:
|
||||
arg = args[0]
|
||||
if isinstance(arg, str):
|
||||
if len(arg) == 0:
|
||||
return ('', None) # valid, but blank
|
||||
if arg[0] == '#':
|
||||
return None # hexadecimal string not handled as NamedColor
|
||||
if arg in Colors:
|
||||
return (arg, None) # valid name, no alpha given
|
||||
if isinstance(arg, tuple) or isinstance(arg, list):
|
||||
args = arg # promote to top level
|
||||
else:
|
||||
return None #numerical values not handled as NamedColor
|
||||
if len(args) == 2:
|
||||
if isinstance(arg[0], str):
|
||||
return (arg[0], arg[1]) # return ('name', alpha) tuple
|
||||
return None # all other cases not handled as NamedColor
|
||||
|
||||
|
||||
def mkColor(*args):
|
||||
"""
|
||||
Convenience function for constructing QColor from a variety of argument types. Accepted arguments are:
|
||||
|
||||
================ ================================================
|
||||
'c' one of: r, g, b, c, m, y, k, w
|
||||
'name' any color name specifed in palette
|
||||
R, G, B, [A] integers 0-255
|
||||
(R, G, B, [A]) tuple of integers 0-255
|
||||
float greyscale, 0.0-1.0
|
||||
int see :func:`intColor() <pyqtgraph.intColor>`
|
||||
(int, hues) see :func:`intColor() <pyqtgraph.intColor>`
|
||||
"RGB" hexadecimal strings; may begin with '#'
|
||||
"RGBA"
|
||||
"RRGGBB"
|
||||
"RRGGBBAA"
|
||||
"#RGB" hexadecimal strings; should begin with '#'
|
||||
"#RGBA"
|
||||
"#RRGGBB"
|
||||
"#RRGGBBAA"
|
||||
QColor QColor instance; makes a copy.
|
||||
================ ================================================
|
||||
"""
|
||||
err = 'Not sure how to make a color from "%s"' % str(args)
|
||||
result = parseNamedColorSpecification(args) # check if this is a named palette color
|
||||
if result is not None: # make a return palette color
|
||||
name, alpha = result
|
||||
if name == '':
|
||||
return QtGui.QColor(0,0,0,0) # empty string means "no color"
|
||||
qcol = Colors[name]
|
||||
if alpha is not None: qcol.setAlpha( alpha )
|
||||
return qcol
|
||||
if len(args) == 1:
|
||||
if isinstance(args[0], basestring):
|
||||
c = args[0]
|
||||
@ -301,116 +343,115 @@ def mkColor(*args):
|
||||
return QtGui.QColor(*args)
|
||||
|
||||
|
||||
def mkBrush(*args, **kwds):
|
||||
def mkBrush(*args, **kargs):
|
||||
"""
|
||||
| Convenience function for constructing Brush.
|
||||
| This function always constructs a solid brush and accepts the same arguments as :func:`mkColor() <pyqtgraph.mkColor>`
|
||||
| Calling mkBrush(None) returns an invisible brush.
|
||||
"""
|
||||
print('mkBrush called with',args,kwds)
|
||||
if 'color' in kwds:
|
||||
color = kwds['color']
|
||||
elif len(args) == 1:
|
||||
arg = args[0]
|
||||
if arg is None:
|
||||
return QtGui.QBrush(QtCore.Qt.NoBrush)
|
||||
elif isinstance(arg, QtGui.QBrush):
|
||||
return QtGui.QBrush(arg)
|
||||
while ( # unravel single element sublists
|
||||
( isinstance(args, tuple) or isinstance(args,list) )
|
||||
and len(args) == 1
|
||||
):
|
||||
args = args[0]
|
||||
# now args is either a non-list entity, or a multi-element tuple
|
||||
# short-circuits:
|
||||
if isinstance(args, NamedBrush):
|
||||
return args # pass through predefined NamedPen directly
|
||||
elif isinstance(args, QtGui.QBrush):
|
||||
return QtGui.QBrush(args) ## return a copy of this brush
|
||||
elif isinstance(args, dict):
|
||||
return mkBrush(**args) # retry with kwargs assigned from dictionary
|
||||
elif args is None:
|
||||
return QtGui.QBrush( QtCore.Qt.NoBrush ) # explicit None means "no brush"
|
||||
# no short-circuit, continue parsing to construct QPen or NamedPen
|
||||
if 'hsv' in kargs: # hsv argument takes precedence
|
||||
qcol = hsvColor( *kargs['hsv'] )
|
||||
qbrush = QtGui.QBrush(qcol)
|
||||
else:
|
||||
if 'color' in kargs:
|
||||
args = kargs['color'] # 'color' KW-argument overrides unnamed arguments
|
||||
if args is None:
|
||||
return QtGui.QBrush( QtCore.Qt.NoBrush ) # explicit None means "no brush"
|
||||
if args == () or args == []:
|
||||
print(' functions: returning default color NamedBrush')
|
||||
qpen = NamedBrush( 'gr_fg' ) # default foreground color
|
||||
else:
|
||||
color = arg
|
||||
elif len(args) > 1:
|
||||
color = args
|
||||
return QtGui.QBrush(mkColor(color))
|
||||
|
||||
def mkNamedPen(name, **kargs):
|
||||
"""
|
||||
Try to create a named pen.
|
||||
Currently, this quietly returns None if 'name' does not specify a color.
|
||||
This causes mkPen to keep trying to parse color information.
|
||||
|
||||
In addition to arguments 'style', 'width', 'dash' and 'cosmetic',
|
||||
'alpha' = 0-255 sets the opacity of the named pen
|
||||
"""
|
||||
alpha = kargs.get('alpha', None)
|
||||
try:
|
||||
pen = NamedPen( name, alpha=alpha )
|
||||
except ValueError:
|
||||
print(' failed to make NamedPen',name,kargs)
|
||||
return None
|
||||
if kargs == {}:
|
||||
print(' prepared NamedPen',name,'(no kargs)')
|
||||
return pen # default pen of width zero is cosmetic by default
|
||||
style = kargs.get('style', None) # in many cases, a predefined pen is just passed through
|
||||
width = kargs.get('width', 1) # collect remaining kargs to define properties
|
||||
dash = kargs.get('dash', None)
|
||||
cosmetic = kargs.get('cosmetic', True)
|
||||
|
||||
pen.setCosmetic(cosmetic)
|
||||
if style is not None: pen.setStyle(style)
|
||||
if dash is not None: pen.setDashPattern(dash)
|
||||
print(' prepared NamedPen',name,kargs)
|
||||
return pen
|
||||
|
||||
result = parseNamedColorSpecification(args)
|
||||
if result is not None: # make a NamedBrush
|
||||
name, alpha = result
|
||||
if name == '':
|
||||
return QtGui.QBrush( QtCore.Qt.NoBrush ) # empty string means "no brush"
|
||||
qbrush = NamedBrush(name, alpha=alpha)
|
||||
else: # make a QBrush
|
||||
qcol = mkColor(args)
|
||||
qbrush = QtGui.QBrush(qcol)
|
||||
# here we would apply additional style based on KW-arguments
|
||||
return qbrush
|
||||
|
||||
def mkPen(*args, **kargs):
|
||||
"""
|
||||
Convenience function for constructing QPen.
|
||||
|
||||
Examples::
|
||||
|
||||
mkPen(color)
|
||||
mkPen(color, width=2)
|
||||
mkPen(cosmetic=False, width=4.5, color='r')
|
||||
mkPen({'color': "FF0", width: 2})
|
||||
mkPen(None) # (no pen)
|
||||
mkPen() # default color
|
||||
|
||||
In these examples, *color* may be replaced with any arguments accepted by :func:`mkColor() <pyqtgraph.mkColor>` """
|
||||
|
||||
# print('mkPen called:',args,kargs)
|
||||
color = kargs.get('color', None) # collect only immediately required properties
|
||||
style = kargs.get('style', None) # in many cases, a predefined pen is just passed through
|
||||
|
||||
pen = None
|
||||
if len(args) == 1:
|
||||
arg = args[0]
|
||||
if isinstance(arg, str):
|
||||
if len(arg) == 0: # empty string sets "no pen"
|
||||
style = QtCore.Qt.NoPen
|
||||
elif arg[0] != '#':
|
||||
pen = mkNamedPen(arg)
|
||||
elif isinstance(arg, NamedPen):
|
||||
return arg # pass through predefined NamedPen directly
|
||||
elif isinstance(arg, QtGui.QPen):
|
||||
return QtGui.QPen(arg) ## return a copy of this pen
|
||||
elif isinstance(arg, dict):
|
||||
return mkPen(**arg)
|
||||
elif arg is None:
|
||||
style = QtCore.Qt.NoPen
|
||||
while ( # unravel single element sublists
|
||||
( isinstance(args, tuple) or isinstance(args,list) )
|
||||
and len(args) == 1
|
||||
):
|
||||
args = args[0]
|
||||
# now args is either a non-list entity, or a multi-element tuple
|
||||
# short-circuits:
|
||||
if isinstance(args, NamedPen):
|
||||
return args # pass through predefined NamedPen directly
|
||||
elif isinstance(args, QtGui.QPen):
|
||||
return QtGui.QPen(args) ## return a copy of this pen
|
||||
elif isinstance(args, dict):
|
||||
return mkPen(**args) # retry with kwargs assigned from dictionary
|
||||
elif args is None:
|
||||
return QtGui.QPen( QtCore.Qt.NoPen ) # explicit None means "no pen"
|
||||
# no short-circuit, continue parsing to construct QPen or NamedPen
|
||||
width = kargs.get('width', 1) # width 1 unless specified otherwise
|
||||
if 'hsv' in kargs: # hsv argument takes precedence
|
||||
qcol = hsvColor( *kargs['hsv'] )
|
||||
qpen = QtGui.QPen(QtGui.QBrush(qcol), width)
|
||||
else:
|
||||
if 'color' in kargs:
|
||||
args = kargs['color'] # 'color' KW-argument overrides unnamed arguments
|
||||
if args is None:
|
||||
return QtGui.QPen( QtCore.Qt.NoPen ) # explicit None means "no pen"
|
||||
if args == () or args == []:
|
||||
qpen = NamedPen( 'gr_fg', width=width ) # default foreground color
|
||||
else:
|
||||
color = arg
|
||||
elif len(args) > 1:
|
||||
color = args
|
||||
|
||||
result = parseNamedColorSpecification(args)
|
||||
if result is not None: # make a NamedPen
|
||||
name, alpha = result
|
||||
if name == '':
|
||||
return QtGui.QPen( QtCore.Qt.NoPen ) # empty string means "no pen"
|
||||
qpen = NamedPen( name, alpha=alpha, width=width )
|
||||
else: # make a QPen
|
||||
qcol = mkColor(args)
|
||||
qpen = QtGui.QPen(QtGui.QBrush(qcol), width)
|
||||
# now apply styles according to kw arguments:
|
||||
style = kargs.get('style', None)
|
||||
width = kargs.get('width', 1) # collect remaining kargs to define properties
|
||||
dash = kargs.get('dash', None)
|
||||
cosmetic = kargs.get('cosmetic', True)
|
||||
hsv = kargs.get('hsv', None)
|
||||
|
||||
if color is None:
|
||||
color = mkColor('l')
|
||||
if hsv is not None:
|
||||
color = hsvColor(*hsv)
|
||||
else:
|
||||
color = mkColor(color)
|
||||
|
||||
if pen is None:
|
||||
pen = QtGui.QPen(QtGui.QBrush(color), width)
|
||||
pen.setCosmetic(cosmetic)
|
||||
assert qpen is not None
|
||||
qpen.setCosmetic(cosmetic)
|
||||
if style is not None:
|
||||
pen.setStyle(style)
|
||||
qpen.setStyle(style)
|
||||
if dash is not None:
|
||||
pen.setDashPattern(dash)
|
||||
return pen
|
||||
qpen.setDashPattern(dash)
|
||||
return qpen
|
||||
|
||||
|
||||
def hsvColor(hue, sat=1.0, val=1.0, alpha=1.0):
|
||||
|
@ -104,7 +104,7 @@ class AxisItem(GraphicsWidget):
|
||||
self.setPen(pen)
|
||||
|
||||
if textPen is None:
|
||||
self.setTextPen('gr_fg') # default foreground color
|
||||
self.setTextPen('gr_txt') # default text color
|
||||
else:
|
||||
self.setTextPen(pen)
|
||||
|
||||
@ -1217,4 +1217,6 @@ class AxisItem(GraphicsWidget):
|
||||
def styleHasChanged(self):
|
||||
""" self.picture needs to be invalidated to initiate full redraw """
|
||||
self.picture = None
|
||||
self.labelStyle['color'] = self._textPen.color().name()
|
||||
self._updateLabel()
|
||||
super().styleHasChanged()
|
||||
|
@ -5,6 +5,7 @@ from .GraphicsItem import GraphicsItem
|
||||
from .. import functions as fn
|
||||
|
||||
__all__ = ['GraphicsObject']
|
||||
DEBUG = False
|
||||
|
||||
try: # prepare common definition for slot decorator across PyQt / Pyside:
|
||||
QT_CORE_SLOT = QtCore.pyqtSlot
|
||||
@ -58,4 +59,4 @@ class GraphicsObject(GraphicsItem, QtGui.QGraphicsObject):
|
||||
""" called to trigger redraw after all named colors have been updated """
|
||||
# self._boundingRect = None
|
||||
self.update()
|
||||
print('redraw after style change:', self)
|
||||
if DEBUG: print(' GrpahicsObject: redraw after style change:', self)
|
@ -4,6 +4,7 @@ from .GraphicsItem import GraphicsItem
|
||||
from .. import functions as fn
|
||||
|
||||
__all__ = ['GraphicsWidget']
|
||||
DEBUG = False
|
||||
|
||||
try: # prepare common definition for slot decorator across PyQt / Pyside:
|
||||
QT_CORE_SLOT = QtCore.pyqtSlot
|
||||
@ -22,7 +23,6 @@ class GraphicsWidget(GraphicsItem, QtGui.QGraphicsWidget):
|
||||
"""
|
||||
QtGui.QGraphicsWidget.__init__(self, *args, **kargs)
|
||||
GraphicsItem.__init__(self)
|
||||
# fn.NAMED_COLOR_MANAGER.paletteChangeSignal.connect(self.styleChange)
|
||||
fn.NAMED_COLOR_MANAGER.paletteHasChangedSignal.connect(self.styleHasChanged)
|
||||
|
||||
## done by GraphicsItem init
|
||||
@ -64,16 +64,9 @@ class GraphicsWidget(GraphicsItem, QtGui.QGraphicsWidget):
|
||||
#print "shape:", p.boundingRect()
|
||||
return p
|
||||
|
||||
# @QT_CORE_SLOT(dict)
|
||||
# # @QtCore.Slot()
|
||||
# def styleChange(self, color_dict):
|
||||
# """ stub function called after Palette.apply(), specific ractions to palette redefinitions execute here """
|
||||
# print('style change request:', self, type(color_dict))
|
||||
|
||||
@QT_CORE_SLOT()
|
||||
# @QtCore.Slot(dict)
|
||||
def styleHasChanged(self):
|
||||
""" called to trigger redraw after all named colors have been updated """
|
||||
# self._boundingRect = None
|
||||
self.update()
|
||||
print('redraw after style change:', self)
|
||||
if DEBUG: print(' GraphicsWidget: redraw after style change:', self)
|
||||
|
@ -15,16 +15,19 @@ class LabelItem(GraphicsWidget, GraphicsWidgetAnchor):
|
||||
Note: To display text inside a scaled view (ViewBox, PlotWidget, etc) use TextItem
|
||||
"""
|
||||
|
||||
|
||||
def __init__(self, text=' ', parent=None, angle=0, **args):
|
||||
GraphicsWidget.__init__(self, parent)
|
||||
GraphicsWidgetAnchor.__init__(self)
|
||||
self.item = QtGui.QGraphicsTextItem(self)
|
||||
self.opts = {
|
||||
'color': None,
|
||||
'color': 'gr_txt', # default text color. Was: None,
|
||||
'justify': 'center'
|
||||
}
|
||||
self.opts.update(args)
|
||||
self._brush = fn.mkBrush(self.opts['color']) # make a NamedBrush by default
|
||||
self._hex_color_override = None
|
||||
self._optlist = []
|
||||
|
||||
self._sizeHint = {}
|
||||
self.setText(text)
|
||||
self.setAngle(angle)
|
||||
@ -32,6 +35,9 @@ class LabelItem(GraphicsWidget, GraphicsWidgetAnchor):
|
||||
def setAttr(self, attr, value):
|
||||
"""Set default text properties. See setText() for accepted parameters."""
|
||||
self.opts[attr] = value
|
||||
if attr == 'color':
|
||||
self._brush = fn.mkBrush(value) # make a new NamedBrush/QBrush
|
||||
self._hex_color_override = None # to use for all normal output
|
||||
|
||||
def setText(self, text, **args):
|
||||
"""Set the text and text properties in the label. Accepts optional arguments for auto-generating
|
||||
@ -46,25 +52,28 @@ class LabelItem(GraphicsWidget, GraphicsWidgetAnchor):
|
||||
==================== ==============================
|
||||
"""
|
||||
self.text = text
|
||||
if 'color' in args:
|
||||
# temporary override for color:
|
||||
col = fn.mkColor(opts['color'])
|
||||
self._hex_color_override = col.name()
|
||||
color_opt = self._hex_color_override
|
||||
else:
|
||||
self._hex_color_override = None # return to defined color
|
||||
color_opt = self._brush.color().name()
|
||||
|
||||
opts = self.opts
|
||||
for k in args:
|
||||
opts[k] = args[k]
|
||||
|
||||
optlist = []
|
||||
|
||||
color = self.opts['color']
|
||||
if color is None:
|
||||
color = getConfigOption('foreground')
|
||||
color = fn.mkColor(color)
|
||||
optlist.append('color: #' + fn.colorStr(color)[:6])
|
||||
|
||||
self.optlist = []
|
||||
# self.optlist.append('color: ' + col.name()
|
||||
if 'size' in opts:
|
||||
optlist.append('font-size: ' + opts['size'])
|
||||
self.optlist.append('font-size: ' + opts['size'])
|
||||
if 'bold' in opts and opts['bold'] in [True, False]:
|
||||
optlist.append('font-weight: ' + {True:'bold', False:'normal'}[opts['bold']])
|
||||
self.optlist.append('font-weight: ' + {True:'bold', False:'normal'}[opts['bold']])
|
||||
if 'italic' in opts and opts['italic'] in [True, False]:
|
||||
optlist.append('font-style: ' + {True:'italic', False:'normal'}[opts['italic']])
|
||||
full = "<span style='%s'>%s</span>" % ('; '.join(optlist), text)
|
||||
#print full
|
||||
self.optlist.append('font-style: ' + {True:'italic', False:'normal'}[opts['italic']])
|
||||
full = "<span style='color: {:s}; {:s}'>{:s}</span>".format(color_opt, '; '.join(self.optlist), self.text)
|
||||
self.item.setHtml(full)
|
||||
self.updateMin()
|
||||
self.resizeEvent(None)
|
||||
@ -133,10 +142,18 @@ class LabelItem(GraphicsWidget, GraphicsWidgetAnchor):
|
||||
|
||||
def itemRect(self):
|
||||
return self.item.mapRectToParent(self.item.boundingRect())
|
||||
|
||||
|
||||
def styleHasChanged(self):
|
||||
""" overridden to update color without changing the text """
|
||||
if self._hex_color_override is not None:
|
||||
return # nothing to do, overridden text color will not change.
|
||||
color_opt = self._brush.color().name() # get updated color
|
||||
full = "<span style='color: {:s}; {:s}'>{:s}</span>".format(color_opt, '; '.join(self.optlist), self.text)
|
||||
self.item.setHtml(full)
|
||||
super().styleHasChanged()
|
||||
|
||||
#def paint(self, p, *args):
|
||||
#p.setPen(fn.mkPen('r'))
|
||||
#p.drawRect(self.rect())
|
||||
#p.setPen(fn.mkPen('g'))
|
||||
#p.drawRect(self.itemRect())
|
||||
|
||||
|
@ -20,6 +20,7 @@ from ..python2_3 import basestring
|
||||
|
||||
|
||||
__all__ = ['ScatterPlotItem', 'SpotItem']
|
||||
DEBUG = False
|
||||
|
||||
|
||||
# When pxMode=True for ScatterPlotItem, QPainter.drawPixmap is used for drawing, which
|
||||
@ -253,6 +254,7 @@ class SymbolAtlas(object):
|
||||
images = []
|
||||
data = []
|
||||
for key, style in styles.items():
|
||||
if DEBUG: print('\nrender:', style[2].color().name(), style[3].color().name(), style)
|
||||
img = renderSymbol(*style)
|
||||
arr = fn.imageToArray(img, copy=False, transpose=False)
|
||||
images.append(img) # keep these to delay garbage collection
|
||||
@ -411,8 +413,8 @@ class ScatterPlotItem(GraphicsObject):
|
||||
'name': None,
|
||||
'symbol': 'o',
|
||||
'size': 7,
|
||||
'pen': fn.mkPen(getConfigOption('foreground')),
|
||||
'brush': fn.mkBrush(100, 100, 150),
|
||||
'pen': fn.mkPen('gr_fg'), # getConfigOption('foreground')),
|
||||
'brush': fn.mkBrush(('gr_fg',128)), # (100, 100, 150),
|
||||
'hoverable': False,
|
||||
'tip': 'x: {x:.3g}\ny: {y:.3g}\ndata={data}'.format,
|
||||
}
|
||||
@ -489,7 +491,6 @@ class ScatterPlotItem(GraphicsObject):
|
||||
Add new points to the scatter plot.
|
||||
Arguments are the same as setData()
|
||||
"""
|
||||
|
||||
## deal with non-keyword arguments
|
||||
if len(args) == 1:
|
||||
kargs['spots'] = args[0]
|
||||
@ -1235,6 +1236,19 @@ class ScatterPlotItem(GraphicsObject):
|
||||
def _hasHoverStyle(self):
|
||||
return any(self.opts['hover' + opt.title()] != _DEFAULT_STYLE[opt]
|
||||
for opt in ['symbol', 'size', 'pen', 'brush'])
|
||||
|
||||
def styleHasChanged(self):
|
||||
""" overridden to trigger symbol atlas refresh """
|
||||
if DEBUG:
|
||||
print(' ScatterPlotItem: style update!')
|
||||
print(' pens:',self.data['pen'] )
|
||||
print(' default pen :', self.opts[ 'pen' ].color().name(), self.opts[ 'pen' ] )
|
||||
print(' default brush:', self.opts['brush'].color().name(), self.opts['brush'] )
|
||||
self.fragmentAtlas.clear()
|
||||
self.data['sourceRect'] = (0, 0, 0, 0)
|
||||
self.updateSpots(self.data)
|
||||
super().styleHasChanged()
|
||||
|
||||
|
||||
|
||||
class SpotItem(object):
|
||||
|
@ -87,7 +87,8 @@ def test_init_spots():
|
||||
# check data is correct
|
||||
spots = s.points()
|
||||
|
||||
defPen = pg.mkPen(pg.getConfigOption('foreground'))
|
||||
# defPen = pg.mkPen(pg.getConfigOption('foreground'))
|
||||
defPen = pg.mkPen('gr_fg')
|
||||
|
||||
assert spots[0].pos().x() == 0
|
||||
assert spots[0].pos().y() == 1
|
||||
|
80
pyqtgraph/namedBrush.py
Normal file
80
pyqtgraph/namedBrush.py
Normal file
@ -0,0 +1,80 @@
|
||||
# from ..Qt import QtGui
|
||||
from .Qt import QtGui, QtCore
|
||||
|
||||
from . import functions as fn
|
||||
|
||||
__all__ = ['NamedBrush']
|
||||
DEBUG = False
|
||||
|
||||
class NamedBrush(QtGui.QBrush):
|
||||
""" Extends QPen to retain a functional color description """
|
||||
def __init__(self, name, alpha=None ):
|
||||
"""
|
||||
Creates a new NamedBrush object.
|
||||
'name' should be in 'functions.Colors'
|
||||
'alpha' controls opacity which persists over palette changes
|
||||
"""
|
||||
if DEBUG: print(' NamedBrush created as',name,alpha)
|
||||
super().__init__(QtCore.Qt.SolidPattern) # Initialize QBrush superclass
|
||||
self._identifier = (name, alpha)
|
||||
self._updateQColor(self._identifier)
|
||||
fn.NAMED_COLOR_MANAGER.register( self ) # manually register for callbacks
|
||||
|
||||
def __eq__(self, other): # make this a hashable object
|
||||
# return other is self
|
||||
if isinstance(other, self.__class__):
|
||||
return self._identifier == other._identifier
|
||||
else:
|
||||
return False
|
||||
|
||||
def __ne__(self, other):
|
||||
return not self.__eq__(other)
|
||||
|
||||
def __hash__(self):
|
||||
return id(self)
|
||||
|
||||
def setColor(self, name=None, alpha=None):
|
||||
""" update color name. This does not trigger a global redraw. """
|
||||
if name is None:
|
||||
name = self._identifier[0]
|
||||
elif isinstance(name, QtGui.QColor):
|
||||
# Replicates alpha adjustment workaround in NamedPen, allowing only alpha to be adjusted retroactively
|
||||
if alpha is None:
|
||||
alpha = name.alpha() # extract from given QColor
|
||||
name = self._identifier[0]
|
||||
if DEBUG: print(' NamedBrush: setColor(QColor) call: set alpha to', alpha)
|
||||
self._identifier = (name, alpha)
|
||||
self._updateQColor(self._identifier)
|
||||
|
||||
def setAlpha(self, alpha):
|
||||
""" update opacity value """
|
||||
self._identifier = (self._identifier[0], alpha)
|
||||
self._updateQColor(self._identifier)
|
||||
|
||||
def _updateQColor(self, identifier, color_dict=None):
|
||||
""" update super-class QColor """
|
||||
name, alpha = identifier
|
||||
if color_dict is None:
|
||||
color_dict = fn.NAMED_COLOR_MANAGER.colors()
|
||||
try:
|
||||
qcol = fn.Colors[name]
|
||||
except ValueError as exc:
|
||||
raise ValueError("Color '{:s}' is not in list of defined colors".format(str(name)) ) from exc
|
||||
if alpha is not None:
|
||||
qcol.setAlpha( alpha )
|
||||
if DEBUG: print(' NamedBrush '+name+' updated to QColor ('+str(qcol.name())+', alpha='+str(alpha)+')')
|
||||
super().setColor( qcol )
|
||||
|
||||
def identifier(self):
|
||||
""" return current color identifier """
|
||||
return self._identifier
|
||||
|
||||
def paletteChange(self, color_dict):
|
||||
""" refresh QColor according to lookup of identifier in functions.Colors """
|
||||
if DEBUG: print(' NamedBrush: style change request:', self, type(color_dict))
|
||||
self._updateQColor(self._identifier, color_dict=color_dict)
|
||||
if DEBUG:
|
||||
qcol = super().color()
|
||||
name, alpha = self._identifier
|
||||
print(' NamedBrush: retrieved new QColor ('+str(qcol.name())+') '
|
||||
+ 'for name '+str(name)+' ('+str(alpha)+')' )
|
@ -34,7 +34,7 @@ for idx, col in enumerate( ( # twelve predefined plot colors
|
||||
) ):
|
||||
key = 'p{:X}'.format(idx)
|
||||
DEFAULT_COLORS[key] = DEFAULT_COLORS[col]
|
||||
|
||||
|
||||
# define and instantiate a SignalSource object to pass signals to all pyqtgraph elements
|
||||
class NamedColorManager(QtCore.QObject): # this needs to emit QEvents
|
||||
"""
|
||||
@ -64,6 +64,7 @@ class NamedColorManager(QtCore.QObject): # this needs to emit QEvents
|
||||
def register(self, obj):
|
||||
""" register a function for paletteChange callback """
|
||||
self.registered_objects.add( obj )
|
||||
# if DEBUG: print(' NamedColorManager: New list', self.registered_objects )
|
||||
|
||||
def redefinePalette(self, color_dic):
|
||||
""" update list of named colors, emitsignals to color objects and widgets """
|
||||
|
@ -11,42 +11,31 @@ class NamedPen(QtGui.QPen):
|
||||
def __init__(self, name, width=1, alpha=None ):
|
||||
"""
|
||||
Creates a new NamedPen object.
|
||||
'identifier' should be a 'name' included in 'functions.Colors' or
|
||||
'(name, alpha)' to include transparency
|
||||
'name' should be included in 'functions.Colors'
|
||||
'width' specifies linewidth and defaults to 1
|
||||
'alpha' controls opacity which persists over palette changes
|
||||
"""
|
||||
try:
|
||||
qcol = fn.Colors[name]
|
||||
# print('QColor alpha is', qcol.alpha() )
|
||||
except ValueError as exc:
|
||||
raise ValueError("Color {:s} is not in list of defined colors".format(str(name)) ) from exc
|
||||
if alpha is not None:
|
||||
if DEBUG: print(' NamedPen: setting alpha to',alpha)
|
||||
qcol.setAlpha( alpha )
|
||||
|
||||
super().__init__( QtGui.QBrush(qcol), width) # Initialize QPen superclass
|
||||
if DEBUG: print(' NamedBrush created as',name,alpha)
|
||||
super().__init__(QtCore.Qt.SolidLine) # Initialize QPen superclass
|
||||
super().setWidth(width)
|
||||
super().setCosmetic(True)
|
||||
self._identifier = (name, alpha)
|
||||
self._updateQColor(self._identifier)
|
||||
fn.NAMED_COLOR_MANAGER.register( self ) # manually register for callbacks
|
||||
|
||||
def __eq__(self, other): # make this a hashable object
|
||||
return other is self
|
||||
# return other is self
|
||||
if isinstance(other, self.__class__):
|
||||
return self._identifier == other._identifier
|
||||
else:
|
||||
return False
|
||||
|
||||
def __ne__(self, other):
|
||||
return not self.__eq__(other)
|
||||
|
||||
def __hash__(self):
|
||||
return id(self)
|
||||
|
||||
# def _parse_identifier(self, identifier):
|
||||
# """ parse identifier parameter, which can be 'name' or '(name, alpha)' """
|
||||
# alpha = None
|
||||
# if isinstance(identifier, str):
|
||||
# name = identifier
|
||||
# else:
|
||||
# try:
|
||||
# name, alpha = identifier
|
||||
# except ValueError as exc:
|
||||
# raise ValueError("Invalid argument. 'identifier' should be 'name' or ('name', 'alpha'), but is {:s}".format(str(color)) ) from exc
|
||||
# if name[0] == '#':
|
||||
# raise TypeError("NamedPen should not be used for fixed colors ('name' = {:s} was given)".format(str(name)) )
|
||||
# return name, alpha
|
||||
|
||||
def setColor(self, name=None, alpha=None):
|
||||
""" update color name. This does not trigger a global redraw. """
|
||||
if name is None:
|
||||
@ -54,23 +43,33 @@ class NamedPen(QtGui.QPen):
|
||||
elif isinstance(name, QtGui.QColor):
|
||||
# this is a workaround for the alpha adjustements in AxisItem:
|
||||
# While the color will not change, the alpha value can be adjusted as needed.
|
||||
alpha = name.alpha() # extract
|
||||
self._identifier = self._identifier[0], alpha
|
||||
# print(' NamedColor setColor(QColor) call: set alpha to', name.alpha())
|
||||
if alpha is None:
|
||||
alpha = name.alpha() # extract from given QColor
|
||||
name = self._identifier[0]
|
||||
if DEBUG: print(' NamedPen: setColor(QColor) call: set alpha to', alpha)
|
||||
self._identifier = (name, alpha)
|
||||
self._updateQColor(self._identifier)
|
||||
|
||||
def setAlpha(self, alpha):
|
||||
""" update opacity value """
|
||||
self._identifier = (self._identifier[0], alpha)
|
||||
self._updateQColor(self._identifier)
|
||||
|
||||
def _updateQColor(self, identifier, color_dict=None):
|
||||
""" update super-class QColor """
|
||||
name, alpha = identifier
|
||||
if color_dict is None:
|
||||
color_dict = fn.NAMED_COLOR_MANAGER.colors()
|
||||
try:
|
||||
qcol = fn.Colors[name]
|
||||
except ValueError as exc:
|
||||
raise ValueError("Color {:s} is not in list of defined colors".format(str(name)) ) from exc
|
||||
if alpha is not None:
|
||||
raise ValueError("Color '{:s}' is not in list of defined colors".format(str(name)) ) from exc
|
||||
if alpha is not None:
|
||||
qcol.setAlpha( alpha )
|
||||
if DEBUG: print(' NamedPen updated to QColor ('+str(qcol.name())+')')
|
||||
super().setColor( qcol )
|
||||
self._identifier = (name, alpha)
|
||||
|
||||
|
||||
# def setBrush(self):
|
||||
# """ disabled """
|
||||
# return None
|
||||
|
||||
|
||||
def paletteChange(self, color_dict):
|
||||
""" refresh QColor according to lookup of identifier in functions.Colors """
|
||||
|
@ -30,12 +30,12 @@ LEGACY_PLOT = [ # plot / accent colors:
|
||||
]
|
||||
|
||||
MONOGREEN_RAW = {
|
||||
'col_g0':'#000000', 'col_g1':'#014801', 'col_g2':'#077110', 'col_g3':'#159326',
|
||||
'col_g0':'#001000', 'col_g1':'#014801', 'col_g2':'#077110', 'col_g3':'#159326',
|
||||
'col_g4':'#2DB143', 'col_g5':'#50CD65', 'col_g6':'#7FE7A0', 'col_g7':'#BFFFD4'
|
||||
}
|
||||
MONOGREEN_FUNC = {
|
||||
'gr_fg' : 'col_g5',
|
||||
'gr_bg' : 'col_g1', # for distinction in testing, should be col_g0
|
||||
'gr_bg' : 'col_g0', # for distinction in testing, should be col_g0
|
||||
'gr_txt' : 'col_g5',
|
||||
'gr_acc' : 'col_g5',
|
||||
'gr_hov' : 'col_g7',
|
||||
@ -64,11 +64,11 @@ RELAXED_RAW = { # "fresh" raw colors:
|
||||
'col_grass' :'#7AA621', 'col_l_grass' :'#BCD982', 'col_d_grass' :'#50730B',
|
||||
'col_yellow':'#BFB226', 'col_l_yellow':'#F2E985', 'col_d_yellow':'#80760D',
|
||||
'col_gold' :'#A67A21', 'col_l_gold' :'#D9B46C', 'col_d_gold' :'#73500B',
|
||||
'col_black' :'#000000', 'col_gr1' :'#242429', 'col_gr2' :'#44444D',
|
||||
'col_gr3' :'#575763', 'col_gr4' :'#7B7B8C', 'col_gr5' :'#B4B4CC',
|
||||
# 'col_black' :'#000000', 'col_gr1' :'#242429', 'col_gr2' :'#44444D',
|
||||
'col_black' :'#000000', 'col_gr1' :'#161619', 'col_gr2' :'#43434D',
|
||||
'col_gr3' :'#70707F', 'col_gr4' :'#9D9DB2', 'col_gr5' :'#C9C9E5',
|
||||
'col_white' :'#FFFFFF'
|
||||
}
|
||||
# 'col_gray' :'#666666', 'col_l_gray' :'#B6B6B6', 'col_d_gray' :'#3D3D3D',
|
||||
RELAXED_DARK_FUNC= { # functional colors:
|
||||
'gr_fg' : 'col_gr5',
|
||||
'gr_bg' : 'col_gr1',
|
||||
@ -97,6 +97,36 @@ RELAXED_DARK_PLOT = [ # plot / accent colors:
|
||||
'col_l_green'
|
||||
]
|
||||
|
||||
RELAXED_LIGHT_FUNC= { # functional colors:
|
||||
'gr_fg' : 'col_gr1',
|
||||
'gr_bg' : 'col_gr5',
|
||||
'gr_txt' : 'col_black',
|
||||
'gr_acc' : 'col_orange',
|
||||
'gr_hov' : 'col_black',
|
||||
'gr_reg' : ('col_blue', 30),
|
||||
# legacy colors:
|
||||
'b': 'col_blue' , 'c': 'col_cyan', 'g': 'col_green',
|
||||
'y': 'col_yellow', 'r': 'col_red' , 'm': 'col_violet',
|
||||
'k': 'col_black' , 'w': 'col_white',
|
||||
'd': 'col_gr2' , 'l': 'col_gr4' , 's': 'col_sky'
|
||||
}
|
||||
RELAXED_LIGHT_PLOT = [ # plot / accent colors:
|
||||
'col_sky' ,
|
||||
'col_indigo',
|
||||
'col_purple',
|
||||
'col_red' ,
|
||||
'col_gold' ,
|
||||
'col_grass' ,
|
||||
'col_cyan' ,
|
||||
'col_blue' ,
|
||||
'col_violet',
|
||||
'col_orange',
|
||||
'col_yellow',
|
||||
'col_green'
|
||||
]
|
||||
|
||||
|
||||
|
||||
def block_to_QColor( block, dic=None ):
|
||||
""" convert color information to a QColor """
|
||||
# allowed formats:
|
||||
@ -152,8 +182,8 @@ DEFAULT_PALETTE = assemble_palette( LEGACY_RAW, LEGACY_FUNC, LEGACY_PLOT )
|
||||
def get(name):
|
||||
if name == 'relaxed_dark':
|
||||
pal = assemble_palette( RELAXED_RAW, RELAXED_DARK_FUNC, RELAXED_DARK_PLOT )
|
||||
# elif name == 'relaxed_light':
|
||||
# pal = assemble_palette( RELAXED_RAW, RELAXED_LIGHT_FUNC, RELAXED_LIGHT_PLOT )
|
||||
elif name == 'relaxed_light':
|
||||
pal = assemble_palette( RELAXED_RAW, RELAXED_LIGHT_FUNC, RELAXED_LIGHT_PLOT )
|
||||
elif name == 'monogreen':
|
||||
pal = assemble_palette( MONOGREEN_RAW, MONOGREEN_FUNC, MONOGREEN_PLOT )
|
||||
else:
|
||||
|
@ -15,8 +15,15 @@ from .. import functions as fn
|
||||
from .. import debug as debug
|
||||
from .. import getConfigOption
|
||||
|
||||
try: # prepare common definition for slot decorator across PyQt / Pyside:
|
||||
QT_CORE_SLOT = QtCore.pyqtSlot
|
||||
except AttributeError:
|
||||
QT_CORE_SLOT = QtCore.Slot
|
||||
|
||||
__all__ = ['GraphicsView']
|
||||
|
||||
DEBUG = False
|
||||
|
||||
|
||||
class GraphicsView(QtGui.QGraphicsView):
|
||||
"""Re-implementation of QGraphicsView that removes scrollbars and allows unambiguous control of the
|
||||
@ -93,7 +100,6 @@ class GraphicsView(QtGui.QGraphicsView):
|
||||
self.setResizeAnchor(QtGui.QGraphicsView.AnchorViewCenter)
|
||||
self.setViewportUpdateMode(QtGui.QGraphicsView.MinimalViewportUpdate)
|
||||
|
||||
|
||||
self.lockedViewports = []
|
||||
self.lastMousePos = None
|
||||
self.setMouseTracking(True)
|
||||
@ -123,6 +129,10 @@ class GraphicsView(QtGui.QGraphicsView):
|
||||
self.scaleCenter = False ## should scaling center around view center (True) or mouse click (False)
|
||||
self.clickAccepted = False
|
||||
|
||||
# connect to style update signals from NamedColorManager:
|
||||
fn.NAMED_COLOR_MANAGER.paletteHasChangedSignal.connect(self.styleHasChanged)
|
||||
|
||||
|
||||
def setAntialiasing(self, aa):
|
||||
"""Enable or disable default antialiasing.
|
||||
Note that this will only affect items that do not specify their own antialiasing options."""
|
||||
@ -137,12 +147,17 @@ class GraphicsView(QtGui.QGraphicsView):
|
||||
To use the defaults specified py pyqtgraph.setConfigOption, use background='default'.
|
||||
To make the background transparent, use background=None.
|
||||
"""
|
||||
self._background = background
|
||||
if background == 'default':
|
||||
# background = getConfigOption('background')
|
||||
background = 'gr_bg' # default graphics background color
|
||||
brush = fn.mkBrush(background)
|
||||
self.setBackgroundBrush(brush)
|
||||
self._background = background # maintained for compatibility
|
||||
if DEBUG: print(' GraphicsView: Generating BG brush for', self._background)
|
||||
self._bgBrush = fn.mkBrush(self._background)
|
||||
if DEBUG: print(' GraphicsView: Background color: ',self._bgBrush.color().name(), self._bgBrush.color().alpha())
|
||||
self.setBackgroundBrush( self._bgBrush )
|
||||
# testBrush = QtGui.QBrush( QtGui.QColor('#000000') )
|
||||
# print(' test brush style:',testBrush.style() )
|
||||
# self.setBackgroundBrush( testBrush )
|
||||
|
||||
def paintEvent(self, ev):
|
||||
self.scene().prepareForPaint()
|
||||
@ -402,3 +417,10 @@ class GraphicsView(QtGui.QGraphicsView):
|
||||
|
||||
def dragEnterEvent(self, ev):
|
||||
ev.ignore() ## not sure why, but for some reason this class likes to consume drag events
|
||||
|
||||
@QT_CORE_SLOT()
|
||||
def styleHasChanged(self):
|
||||
""" called to trigger redraw after all named colors have been updated """
|
||||
self.setBackgroundBrush( self._bgBrush )
|
||||
# self.update()
|
||||
if DEBUG: print(' Background update and redraw after style change:', self)
|
||||
|
@ -27,13 +27,15 @@ def test_basics_graphics_view():
|
||||
assert view.scaleCenter is False
|
||||
assert view.clickAccepted is False
|
||||
assert view.centralWidget is not None
|
||||
assert view._background == "default"
|
||||
# assert view._background == "default"
|
||||
assert view._background == "gr_bg"
|
||||
|
||||
# Set background color
|
||||
# --------------------------------------
|
||||
view.setBackground("w")
|
||||
assert view._background == "w"
|
||||
assert view.backgroundBrush().color() == QtCore.Qt.white
|
||||
# assert view.backgroundBrush().color() == QtCore.Qt.white
|
||||
assert view.backgroundBrush().color().name() == '#ffffff' #QtCore.Qt.white
|
||||
|
||||
# Set anti aliasing
|
||||
# --------------------------------------
|
||||
|
Loading…
Reference in New Issue
Block a user